import * as React from 'react'; import { Button, tailwind } from '@tesseract-design/web-base'; const { tw } = tailwind; const LinkButtonDerivedElementComponent = 'a' as const; /** * Derived HTML element of the {@link LinkButton} component. */ export type LinkButtonDerivedElement = HTMLElementTagNameMap[ typeof LinkButtonDerivedElementComponent ]; interface LinkButtonCommonProps extends Omit, 'href' | 'size'> { /** * Should the component occupy the whole width of its parent? */ block?: boolean; /** * Variant of the component. */ variant?: Button.Variant; /** * Complementary content of the component. */ subtext?: React.ReactNode; /** * Short complementary content displayed at the edge of the component. */ badge?: React.ReactNode; /** * Is this component part of a menu? */ menuItem?: boolean; /** * Size of the component. */ size?: Button.Size; /** * Should the component's content use minimal space? */ compact?: boolean; /** * Is the component unable to receive activation? */ disabled?: boolean; /** * Graphical representation of the component. */ icon?: React.ReactNode; /** * Should the graphical representation of the component be placed after the children? */ iconAfterChildren?: boolean; } interface LinkButtonAnchorProps extends Pick, 'href'> { component: typeof LinkButtonDerivedElementComponent; } interface LinkButtonComponentType { (props: { href?: string }): React.ReactNode; } interface LinkButtonFCProps< C extends LinkButtonComponentType = LinkButtonComponentType > { component: C; href: C extends (props: { href?: infer Href }) => React.ReactNode ? Href : never; } type LinkButtonAllProps< T extends LinkButtonComponentType = LinkButtonComponentType > = LinkButtonAnchorProps | LinkButtonFCProps; /** * Props of the {@link LinkButton} component. */ export type LinkButtonProps< T extends LinkButtonComponentType = LinkButtonComponentType > = LinkButtonCommonProps & LinkButtonAllProps; /** * Component for performing a navigation action. */ export const LinkButton = React.forwardRef(( { variant = 'bare' as const, subtext, badge, menuItem = false, children, size = 'medium' as const, compact = false, className, block = false, component: EnabledComponent = LinkButtonDerivedElementComponent, disabled = false, href, style, icon, iconAfterChildren = false as const, ...etcProps }, forwardedRef, ) => { const Component = (disabled ? 'button' : EnabledComponent) as typeof LinkButtonDerivedElementComponent; const extraProps = { disabled: disabled || undefined, }; return ( {icon && ( {icon} )} {(children || subtext) && ( {children && ( {children} )} {subtext && ( <> {' - '} {subtext} )} )} {badge && ( <> {' - '} {badge} )} {menuItem && ( )} ); }); LinkButton.displayName = 'LinkButton'; LinkButton.defaultProps = { variant: 'bare' as const, size: 'medium' as const, compact: false as const, menuItem: false as const, badge: undefined, subtext: undefined, block: false as const, disabled: false as const, icon: undefined, iconAfterChildren: false as const, // eslint-disable-next-line react/default-props-match-prop-types component: LinkButtonDerivedElementComponent, // eslint-disable-next-line react/default-props-match-prop-types href: undefined, }; // extend the component type here for defining new props // interface LinkButtonComponentType { // (props: { href?: number }): React.ReactNode; // } // const CustomLink = (props: { href?: string | number }) => { // return null; // }; // // const a = ( // // );