Skip to content

Instantly share code, notes, and snippets.

@xkisu
Created February 28, 2023 14:34
Show Gist options
  • Save xkisu/c0fae1ec3c84621be316039f3b67bf04 to your computer and use it in GitHub Desktop.
Save xkisu/c0fae1ec3c84621be316039f3b67bf04 to your computer and use it in GitHub Desktop.
Typescript React component with as prop to set wrapper component
import {Fragment, PropsWithChildren} from 'react';
import * as React from 'react';
type ButtonWithAsProps<T> = {
[K in keyof T]: T[K]
}
export interface ButtonProps<TComponent extends React.ComponentType<any> | keyof JSX.IntrinsicElements> {
as: TComponent
icon?: (props: any) => JSX.Element
className?: string
// props: React.ComponentProps<TComponent>;
}
export default function Button<TComponent extends React.ComponentType<any> | keyof JSX.IntrinsicElements>(props: PropsWithChildren<ButtonWithAsProps<ButtonProps<TComponent>>> & React.ComponentProps<TComponent>) {
const {
as: Component = "button",
children, className, icon,
... componentProps
} = props
const Icon: (props: any) => JSX.Element = icon ? icon : (props: any) => <Fragment />
return (
<Component
className={"inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 " + className}
{...componentProps}
>
{icon && <Icon className="-ml-1 mr-2 h-5 w-5" aria-hidden="true" />}
{children}
</Component>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment