Skip to content

Instantly share code, notes, and snippets.

@hexcowboy
Last active February 28, 2024 17:22
Show Gist options
  • Save hexcowboy/4a97d66fb5dd9ded8bc8e8994c7f0bc2 to your computer and use it in GitHub Desktop.
Save hexcowboy/4a97d66fb5dd9ded8bc8e8994c7f0bc2 to your computer and use it in GitHub Desktop.
Polymorphic React Components
import React from "react";
import { Link } from "react-router-dom";
// Use React.ButtonHTMLAttributes for base button props to support all native button attributes
type BaseButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
// Polymorphic 'as' prop type, allowing for component type override
type AsProp<C extends React.ElementType> = {
as?: C;
};
// Props for the Button component, merging base button props with props of the 'as' component
type ButtonProps<C extends React.ElementType> = BaseButtonProps &
React.ComponentPropsWithoutRef<C> &
AsProp<C>;
// Button component with polymorphic 'as' prop
const Button = <C extends React.ElementType = "button">({
as,
children,
...props
}: ButtonProps<C>) => {
const Component = as || "button";
return <Component {...props}>{children}</Component>;
};
// Usage examples:
// Regular button usage
const RegularButton: React.FC = () => (
<Button
onClick={() => console.log("Clicked regular button")}
aria-label="Click me"
>
Click Me
</Button>
);
// Button as Link from react-router-dom
const LinkButton: React.FC = () => (
<Button as={Link} to="/path" aria-label="Go to path">
Go to Path
</Button>
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment