Design system.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

180 рядки
4.6 KiB

  1. import * as React from 'react';
  2. import clsx from 'clsx';
  3. import { Button } from '@tesseract-design/web-base';
  4. /**
  5. * Derived HTML element of the {@link LinkButton} component.
  6. */
  7. export type LinkButtonDerivedElement = HTMLAnchorElement;
  8. /**
  9. * Props of the {@link LinkButton} component.
  10. */
  11. export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButtonDerivedElement>, 'size'> {
  12. /**
  13. * Should the component occupy the whole width of its parent?
  14. */
  15. block?: boolean;
  16. /**
  17. * Variant of the component.
  18. */
  19. variant?: Button.Variant;
  20. /**
  21. * Complementary content of the component.
  22. */
  23. subtext?: React.ReactNode;
  24. /**
  25. * Short complementary content displayed at the edge of the component.
  26. */
  27. badge?: React.ReactNode;
  28. /**
  29. * Is this component part of a menu?
  30. */
  31. menuItem?: boolean;
  32. /**
  33. * Size of the component.
  34. */
  35. size?: Button.Size;
  36. /**
  37. * Should the component's content use minimal space?
  38. */
  39. compact?: boolean;
  40. /**
  41. * Component to use in rendering.
  42. */
  43. component?: React.ElementType<T>;
  44. /**
  45. * Is the component unable to receive activation?
  46. */
  47. disabled?: boolean;
  48. }
  49. export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonProps>((
  50. {
  51. variant = 'bare' as const,
  52. subtext,
  53. badge,
  54. menuItem = false,
  55. children,
  56. size = 'medium' as const,
  57. compact = false,
  58. className,
  59. block = false,
  60. component: EnabledComponent = 'a',
  61. disabled = false,
  62. href,
  63. style,
  64. ...etcProps
  65. },
  66. forwardedRef,
  67. ) => {
  68. const Component = disabled ? 'button' : EnabledComponent;
  69. return (
  70. <Component
  71. {...etcProps}
  72. href={disabled ? undefined : href}
  73. type={disabled ? 'button' : undefined}
  74. ref={forwardedRef}
  75. disabled={disabled || undefined}
  76. className={clsx(
  77. 'items-center justify-center rounded overflow-hidden ring-secondary/50 leading-none select-none no-underline m-0',
  78. 'focus:outline-0 focus:ring-4',
  79. 'active:ring-tertiary/50',
  80. 'disabled:opacity-50 disabled:cursor-not-allowed',
  81. {
  82. 'flex w-full': block,
  83. 'inline-flex max-w-full align-middle': !block,
  84. },
  85. {
  86. 'pl-2 gap-2': compact,
  87. 'pl-4 gap-4': !compact,
  88. 'pr-4': !(compact || menuItem),
  89. 'pr-2': compact || menuItem,
  90. },
  91. {
  92. 'border-2 border-primary focus:border-secondary active:border-tertiary disabled:border-primary': variant !== 'bare',
  93. 'bg-negative text-primary focus:text-secondary active:text-tertiary disabled:text-primary': variant !== 'filled',
  94. 'bg-primary text-negative focus:bg-secondary active:bg-tertiary focus:text-negative active:text-negative disabled:bg-primary': variant === 'filled',
  95. },
  96. {
  97. 'h-10': size === 'small',
  98. 'h-12': size === 'medium',
  99. 'h-16': size === 'large',
  100. },
  101. className,
  102. )}
  103. data-testid="link"
  104. style={style}
  105. >
  106. <span
  107. className={clsx(
  108. 'flex-auto min-w-0',
  109. {
  110. 'text-left': compact || menuItem,
  111. 'text-center': !(compact || menuItem),
  112. },
  113. )}
  114. >
  115. <span
  116. className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
  117. data-testid="children"
  118. >
  119. {children}
  120. </span>
  121. {subtext && (
  122. <>
  123. <span className="sr-only">
  124. {' - '}
  125. </span>
  126. <span
  127. className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
  128. data-testid="subtext"
  129. >
  130. {subtext}
  131. </span>
  132. </>
  133. )}
  134. </span>
  135. {badge && (
  136. <>
  137. <span className="sr-only">
  138. {' - '}
  139. </span>
  140. <span
  141. data-testid="badge"
  142. >
  143. {badge}
  144. </span>
  145. </>
  146. )}
  147. {menuItem && (
  148. <span
  149. data-testid="menuItemIndicator"
  150. >
  151. <svg
  152. className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round"
  153. viewBox="0 0 24 24"
  154. role="presentation"
  155. >
  156. <polyline points="9 18 15 12 9 6" />
  157. </svg>
  158. </span>
  159. )}
  160. </Component>
  161. );
  162. });
  163. LinkButton.displayName = 'LinkButton';
  164. LinkButton.defaultProps = {
  165. variant: 'bare',
  166. size: 'medium',
  167. compact: false,
  168. menuItem: false,
  169. component: 'a',
  170. badge: undefined,
  171. subtext: undefined,
  172. block: false,
  173. disabled: false,
  174. };