- import * as React from 'react';
- import clsx from 'clsx';
- import { Button } from '@tesseract-design/web-base';
-
- /**
- * Derived HTML element of the {@link LinkButton} component.
- */
- export type LinkButtonDerivedElement = HTMLAnchorElement;
-
- /**
- * Props of the {@link LinkButton} component.
- */
- export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButtonDerivedElement>, '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;
- /**
- * Component to use in rendering.
- */
- component?: React.ElementType<T>;
- /**
- * Is the component unable to receive activation?
- */
- disabled?: boolean;
- }
-
- export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonProps>((
- {
- variant = 'bare' as const,
- subtext,
- badge,
- menuItem = false,
- children,
- size = 'medium' as const,
- compact = false,
- className,
- block = false,
- component: EnabledComponent = 'a',
- disabled = false,
- href,
- style,
- ...etcProps
- },
- forwardedRef,
- ) => {
- const Component = disabled ? 'button' : EnabledComponent;
- return (
- <Component
- {...etcProps}
- href={disabled ? undefined : href}
- type={disabled ? 'button' : undefined}
- ref={forwardedRef}
- disabled={disabled || undefined}
- className={clsx(
- 'items-center justify-center rounded overflow-hidden ring-secondary/50 leading-none select-none no-underline m-0',
- 'focus:outline-0 focus:ring-4',
- 'active:ring-tertiary/50',
- 'disabled:opacity-50 disabled:cursor-not-allowed',
- {
- 'flex w-full': block,
- 'inline-flex max-w-full align-middle': !block,
- },
- {
- 'pl-2 gap-2': compact,
- 'pl-4 gap-4': !compact,
- 'pr-4': !(compact || menuItem),
- 'pr-2': compact || menuItem,
- },
- {
- 'border-2 border-primary focus:border-secondary active:border-tertiary disabled:border-primary': variant !== 'bare',
- 'bg-negative text-primary focus:text-secondary active:text-tertiary disabled:text-primary': variant !== 'filled',
- 'bg-primary text-negative focus:bg-secondary active:bg-tertiary focus:text-negative active:text-negative disabled:bg-primary': variant === 'filled',
- },
- {
- 'h-10': size === 'small',
- 'h-12': size === 'medium',
- 'h-16': size === 'large',
- },
- className,
- )}
- data-testid="link"
- style={style}
- >
- <span
- className={clsx(
- 'flex-auto min-w-0',
- {
- 'text-left': compact || menuItem,
- 'text-center': !(compact || menuItem),
- },
- )}
- >
- <span
- className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
- data-testid="children"
- >
- {children}
- </span>
- {subtext && (
- <>
- <span className="sr-only">
- {' - '}
- </span>
- <span
- className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
- data-testid="subtext"
- >
- {subtext}
- </span>
- </>
- )}
- </span>
- {badge && (
- <>
- <span className="sr-only">
- {' - '}
- </span>
- <span
- data-testid="badge"
- >
- {badge}
- </span>
- </>
- )}
- {menuItem && (
- <span
- data-testid="menuItemIndicator"
- >
- <svg
- className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round"
- viewBox="0 0 24 24"
- role="presentation"
- >
- <polyline points="9 18 15 12 9 6" />
- </svg>
- </span>
- )}
- </Component>
- );
- });
-
- LinkButton.displayName = 'LinkButton';
-
- LinkButton.defaultProps = {
- variant: 'bare',
- size: 'medium',
- compact: false,
- menuItem: false,
- component: 'a',
- badge: undefined,
- subtext: undefined,
- block: false,
- disabled: false,
- };
|