Coder Social home page Coder Social logo

hipstersmoothie / react-polymorphic-box Goto Github PK

View Code? Open in Web Editor NEW

This project forked from kripod/react-polymorphic-box

0.0 2.0 0.0 1.1 MB

Building blocks for strongly typed polymorphic components in React.

License: MIT License

TypeScript 100.00%

react-polymorphic-box's Introduction

react-polymorphic-box

Building blocks for strongly typed polymorphic components in React.

npm Language grade: JavaScript Travis (.com) Commitizen friendly

Animated demonstration of package capabilities

๐Ÿ’ก Motivation

Popularized by Styled Components v4, the as prop allows changing the HTML tag rendered by a component, e.g.:

import { Box } from 'react-polymorphic-box';
import { Link } from 'react-router-dom';

<Box as="a" href="https://github.com/kripod">GitHub</Box>
<Box as={Link} to="/about">About</Box>

While this pattern has been encouraged by several libraries, typings had lacked support for polymorphism, missing benefits like:

  • Automatic code completion, based on the value of the as prop
  • Static type checking against the associated component's inferred props
  • HTML element name validation

๐Ÿ“š Usage

A Heading component can demonstrate the effectiveness of polymorphism:

<Heading color="rebeccapurple">Heading</Heading>
<Heading as="h3">Subheading</Heading>

Custom components like the previous one may utilize the package as shown below.

import * as React from 'react';
import { Box, PolymorphicComponentProps } from 'react-polymorphic-box';

// Component-specific props should be specified separately
export interface HeadingOwnProps {
  color?: string;
}

// Merge own props with others inherited from the underlying element type
export type HeadingProps<
  E extends React.ElementType
> = PolymorphicComponentProps<E, HeadingOwnProps>;

// An HTML tag or a different React component can be rendered by default
const defaultElement = 'h2';

export function Heading<E extends React.ElementType = typeof defaultElement>({
  color,
  style,
  ...restProps
}: HeadingProps<E>): JSX.Element {
  // The `as` prop may be overridden by the passed props
  return <Box as={defaultElement} style={{ color, ...style }} {...restProps} />;
}

Typing external components

Alternatively, you can also type your custom components by using the PolymorphicComponent type. This is especially handy when working with external libraries that already expose polymorphic components. Here's an example implementing the Heading component from above using styled-components:

import { PolymorphicComponent } from 'react-polymorphic-box';
import styled from 'styled-components';

// Component-specific props
interface HeadingProps {
  color?: string;
}

// An HTML tag or a different React component can be rendered by default
const defaultElement = 'h2';

const Heading: PolymorphicComponent<
  HeadingProps, // Merged with props from the underlying element type
  typeof defaultElement // Default element type (optional, defaults to 'div')
> = styled(defaultElement)<HeadingProps>`
  color: ${(props) => props.color};
`;

Forwarding Refs

Library authors should consider encapsulating reusable components, passing a ref through each of them:

import * as React from 'react';
import { Box } from 'react-polymorphic-box';

export const Heading = React.forwardRef(
  <E extends React.ElementType = typeof defaultElement>(
    { ref, color, style, ...restProps }: HeadingProps<E>,
    innerRef: typeof ref,
  ) => {
    return (
      <Box
        ref={innerRef}
        as={defaultElement}
        style={{ color, ...style }}
        {...restProps}
      />
    );
  },
) as <E extends React.ElementType = typeof defaultElement>(
  props: HeadingProps<E>,
) => JSX.Element;

react-polymorphic-box's People

Contributors

kripod avatar biowaffeln avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.