Last active
February 28, 2024 17:22
-
-
Save hexcowboy/4a97d66fb5dd9ded8bc8e8994c7f0bc2 to your computer and use it in GitHub Desktop.
Polymorphic React Components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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