Utilities
Polymorphic

Polymorphic

The term Polymorphic means a special way to define the component element from outside, by using a property which is commonly called as or tag.

Lualtek UI react-components provide typescript types to create these polymorphic components.

Basic example

In this example we can see how to create a polymorphic Button component:

import React, { forwardRef } from "react";
import type { Polymorphic } from "@lualtek/react-components";
 
/* Define the default element tag */
const ElementType = "button";
 
/* Define Box's custom properties */
type ButtonProps = {};
 
/* Set the default HTMLELement type */
type PolymorphicButton = Polymorphic.ForwardRefComponent<
  typeof ElementType,
  ButtonProps
>;
 
/**
 * Rename as into Wrapper andmake
 * it a <button> element as default
 */
const Button = forwardRef(
  ({ as: Component = ElementType, ...props }, forwardedRef) => (
    <Component ref={forwardedRef} {...props} />
  )
) as PolymorphicButton;

Once created, you can now import and use the Button component as following:

export default () => (
  <>
    <Button>As "<button>"</Button>
    <Button as="a" href="https://www.google.com">
      As "<a>"
    </Button>
  </>
);

API Reference

ForwardRefComponent

Adds polymorphic as prop types to a forwardRef component.

Polymorphic.ForwardRefComponent<keyof JSX.IntrinsicElements, OwnProps>;

The OwnProps should not contain DOM attributes. These will be added for you. Use the Polymorphic.OwnProps utility to extract these from existing polymorphic components.

Usage

Polymorphic.ForwardRefComponent<"button", { variant: "solid" | "outline" }>;

OwnProps

Extract props from a polymorphic component, excluding its DOM props.

Polymorphic.OwnProps<Polymorphic.ForwardRefComponent>;

Usage

Polymorphic.OwnProps<typeof Button>;
// { variant: 'solid' | 'outline' }

IntrinsicElement

Extract the JSX.IntrinsicElements key from a polymorphic component.

Polymorphic.IntrinsicElement<Polymorphic.ForwardRefComponent>;

Usage

Polymorphic.IntrinsicElement<typeof Button>;
// 'button'

Extending polymorphic components

Maintain polymorphism when wrapping a polymorphic component in your own custom component by combining the above utilities.

import React from "react";
import { Button, Polymorphic } from "@lualtek/react-components";
 
/* Define custom props for IconButton */
type IconButtonProps = {
  size?: "small" | "large";
};
 
/* Get the element type from the base Button component
 * extract their props and merge them with IconButtonProps
 */
type PolymorphicIconButton = Polymorphic.ForwardRefComponent<
  Polymorphic.IntrinsicElement<typeof Button>,
  Polymorphic.OwnProps<typeof Button> & IconButtonProps
>;
 
/* Define the IconButton component as PolymorphicIconButton */
const IconButton = React.forwardRef(
  ({ size = "small", ...props }, forwardedRef) => (
    <Button {...props} ref={forwardedRef} />
  )
) as PolymorphicIconButton;
 
/* Usage */
export default () => <IconButton as="a" size="large" />;