Component with dynamic tag
export type Prefer<P, T> = P & Omit<T, keyof P>;export type ElementPropsWithoutRef<T extends ElementType> = Pick<ComponentPropsWithoutRef<T>,keyof ComponentPropsWithoutRef<T>>;export type DynamicHTMLProps<OwnProps, Type extends ElementType> = Prefer<OwnProps,ElementPropsWithoutRef<Type>>;type ButtonProps<As extends React.ElementType> = {variant: 'primary' | 'secondary'as: As}export const Button = <As extends React.ElementType = 'button'>({as,children,variant,...props}: DynamicHTMLProps<ButtonProps<As>, As>) => {const Tag: React.ElementType = as || 'button';return <Tag {...props} className={variant}>{children}</Tag>;};
And with forward ref
// React 🥰function fixedForwardRef<T, P = {}>(render: (props: P, ref: React.Ref<T>) => React.ReactNode): (props: P & React.RefAttributes<T>) => React.ReactNode {return React.forwardRef(render) as any;}export const ButtonRaw = <As extends React.ElementType, Ref>(props: DynamicHTMLProps<ButtonProps<As>, As>, ref: Ref) => {const { as = 'button', variant, children, ...rest } = props;const Tag: React.ElementType = props.as;return <Tag {...rest} className={variant} ref={ref}>{children}</Tag>;};const Button = fixedForwardRef(ButtonRaw);