Design system.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

119 lines
3.0 KiB

  1. import * as React from 'react';
  2. import clsx from 'clsx';
  3. import { Button } from '@tesseract-design/web-base';
  4. export type LinkButtonDerivedElement = HTMLAnchorElement;
  5. export interface LinkButtonProps extends Omit<React.HTMLProps<LinkButtonDerivedElement>, 'size'> {
  6. block?: boolean;
  7. variant: Button.Variant;
  8. subtext?: React.ReactNode;
  9. badge?: React.ReactNode;
  10. menuItem?: boolean;
  11. size?: Button.Size;
  12. compact?: boolean;
  13. component?: React.ElementType;
  14. }
  15. export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonProps>(({
  16. variant,
  17. subtext,
  18. badge,
  19. menuItem = false,
  20. children,
  21. size = 'medium' as const,
  22. compact = false,
  23. className,
  24. block = false,
  25. component: Component = 'a',
  26. ...etcProps
  27. }, forwardedRef) => (
  28. <Component
  29. {...etcProps}
  30. ref={forwardedRef}
  31. className={clsx(
  32. 'items-center justify-center rounded overflow-hidden ring-secondary/50 leading-none select-none',
  33. 'focus:outline-0 focus:ring-4',
  34. 'active:ring-tertiary/50',
  35. {
  36. 'flex w-full': block,
  37. 'inline-flex max-w-full align-middle': !block,
  38. },
  39. {
  40. 'pl-2 gap-2': compact,
  41. 'pl-4 gap-4': !compact,
  42. 'pr-4': !(compact || menuItem),
  43. 'pr-2': compact || menuItem,
  44. },
  45. {
  46. 'border-2 border-primary focus:border-secondary active:border-tertiary' : variant !== 'bare',
  47. 'bg-negative text-primary focus:text-secondary active:text-tertiary': variant !== 'filled',
  48. 'bg-primary text-negative focus:bg-secondary active:bg-tertiary': variant === 'filled',
  49. },
  50. {
  51. 'h-10': size === 'small',
  52. 'h-12': size === 'medium',
  53. 'h-16': size === 'large',
  54. },
  55. className,
  56. )}
  57. >
  58. <span
  59. className={clsx(
  60. 'flex-auto min-w-0',
  61. {
  62. 'text-left': compact || menuItem,
  63. 'text-center': !(compact || menuItem),
  64. },
  65. )}
  66. >
  67. <span
  68. className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
  69. data-testid="children"
  70. >
  71. {children}
  72. </span>
  73. {subtext && (
  74. <>
  75. <span className="sr-only">
  76. {' - '}
  77. </span>
  78. <span
  79. className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
  80. data-testid="subtext"
  81. >
  82. {subtext}
  83. </span>
  84. </>
  85. )}
  86. </span>
  87. {badge && (
  88. <>
  89. <span className="sr-only">
  90. {' - '}
  91. </span>
  92. <span
  93. data-testid="badge"
  94. >
  95. {badge}
  96. </span>
  97. </>
  98. )}
  99. {menuItem && (
  100. <span
  101. data-testid="menuItemIndicator"
  102. >
  103. <svg
  104. className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round"
  105. viewBox="0 0 24 24"
  106. role="presentation"
  107. >
  108. <polyline points="9 18 15 12 9 6"/>
  109. </svg>
  110. </span>
  111. )}
  112. </Component>
  113. ));
  114. LinkButton.displayName = 'LinkButton';