@mindlogic-ai/logician-ui 5.0.0-alpha.2 → 5.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/components/Badge/Badge.d.ts.map +1 -1
  2. package/dist/components/Badge/Badge.js +5 -3
  3. package/dist/components/Badge/Badge.js.map +1 -1
  4. package/dist/components/Badge/Badge.mjs +5 -3
  5. package/dist/components/Badge/Badge.mjs.map +1 -1
  6. package/dist/components/Badge/Badge.types.d.ts +7 -5
  7. package/dist/components/Badge/Badge.types.d.ts.map +1 -1
  8. package/dist/components/Banner/Banner.types.d.ts +24 -1
  9. package/dist/components/Banner/Banner.types.d.ts.map +1 -1
  10. package/dist/components/Card/Card.types.d.ts +12 -0
  11. package/dist/components/Card/Card.types.d.ts.map +1 -1
  12. package/dist/components/ColorMode/ColorModeToggle.d.ts +7 -2
  13. package/dist/components/ColorMode/ColorModeToggle.d.ts.map +1 -1
  14. package/dist/components/ColorMode/ColorModeToggle.js +8 -3
  15. package/dist/components/ColorMode/ColorModeToggle.js.map +1 -1
  16. package/dist/components/ColorMode/ColorModeToggle.mjs +8 -3
  17. package/dist/components/ColorMode/ColorModeToggle.mjs.map +1 -1
  18. package/dist/components/Confetti/Confetti.types.d.ts +5 -1
  19. package/dist/components/Confetti/Confetti.types.d.ts.map +1 -1
  20. package/dist/components/Confetti/confettiColors.d.ts +5 -5
  21. package/dist/components/Confetti/confettiColors.js +5 -5
  22. package/dist/components/Confetti/confettiColors.mjs +5 -5
  23. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts +6 -0
  24. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts.map +1 -1
  25. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts +4 -1
  26. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts.map +1 -1
  27. package/dist/components/LineGraph/LineGraph.d.ts.map +1 -1
  28. package/dist/components/LineGraph/LineGraph.js +4 -5
  29. package/dist/components/LineGraph/LineGraph.js.map +1 -1
  30. package/dist/components/LineGraph/LineGraph.mjs +5 -6
  31. package/dist/components/LineGraph/LineGraph.mjs.map +1 -1
  32. package/dist/components/LineGraph/LineGraph.types.d.ts +12 -2
  33. package/dist/components/LineGraph/LineGraph.types.d.ts.map +1 -1
  34. package/dist/components/LineGraph/seriesColors.d.ts +12 -8
  35. package/dist/components/LineGraph/seriesColors.d.ts.map +1 -1
  36. package/dist/components/LineGraph/seriesColors.js +8 -7
  37. package/dist/components/LineGraph/seriesColors.js.map +1 -1
  38. package/dist/components/LineGraph/seriesColors.mjs +8 -7
  39. package/dist/components/LineGraph/seriesColors.mjs.map +1 -1
  40. package/dist/components/Masonry/Masonry.types.d.ts +8 -3
  41. package/dist/components/Masonry/Masonry.types.d.ts.map +1 -1
  42. package/dist/components/Menu/MenuItem.types.d.ts +8 -0
  43. package/dist/components/Menu/MenuItem.types.d.ts.map +1 -1
  44. package/dist/components/Modal/ModalCloseButton.d.ts +1 -1
  45. package/dist/components/Modal/ModalCloseButton.js +1 -1
  46. package/dist/components/Modal/ModalCloseButton.mjs +1 -1
  47. package/dist/components/Pagination/Pagination.d.ts +11 -10
  48. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  49. package/dist/components/Pagination/Pagination.js +11 -10
  50. package/dist/components/Pagination/Pagination.js.map +1 -1
  51. package/dist/components/Pagination/Pagination.mjs +11 -10
  52. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  53. package/dist/components/ProgressBar/ProgressBar.types.d.ts +9 -0
  54. package/dist/components/ProgressBar/ProgressBar.types.d.ts.map +1 -1
  55. package/dist/components/RadialProgress/RadialProgress.types.d.ts +21 -1
  56. package/dist/components/RadialProgress/RadialProgress.types.d.ts.map +1 -1
  57. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts +8 -0
  58. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts.map +1 -1
  59. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  60. package/dist/components/SegmentedControl/SegmentedControl.js +6 -7
  61. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  62. package/dist/components/SegmentedControl/SegmentedControl.mjs +6 -7
  63. package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
  64. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts +2 -0
  65. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts.map +1 -1
  66. package/dist/components/Toast/Toast.styles.d.ts +6 -2
  67. package/dist/components/Toast/Toast.styles.d.ts.map +1 -1
  68. package/dist/components/Toast/Toast.styles.js +18 -10
  69. package/dist/components/Toast/Toast.styles.js.map +1 -1
  70. package/dist/components/Toast/Toast.styles.mjs +18 -10
  71. package/dist/components/Toast/Toast.styles.mjs.map +1 -1
  72. package/dist/theme/colors.d.ts +2 -2
  73. package/dist/theme/colors.d.ts.map +1 -1
  74. package/dist/theme/colors.js +22 -2
  75. package/dist/theme/colors.js.map +1 -1
  76. package/dist/theme/colors.mjs +23 -3
  77. package/dist/theme/colors.mjs.map +1 -1
  78. package/dist/theme/palette.generated.d.ts +98 -0
  79. package/dist/theme/palette.generated.d.ts.map +1 -1
  80. package/dist/theme/palette.generated.js +99 -0
  81. package/dist/theme/palette.generated.js.map +1 -1
  82. package/dist/theme/palette.generated.mjs +99 -1
  83. package/dist/theme/palette.generated.mjs.map +1 -1
  84. package/dist/theme/paletteSwatches.d.ts +20 -0
  85. package/dist/theme/paletteSwatches.d.ts.map +1 -1
  86. package/package.json +1 -1
  87. package/src/components/Accordion/Accordion.stories.tsx +85 -0
  88. package/src/components/Accordion/Accordion.usage.mdx +200 -0
  89. package/src/components/Appear/Appear.usage.mdx +107 -0
  90. package/src/components/Avatar/Avatar.stories.tsx +71 -1
  91. package/src/components/Avatar/Avatar.usage.mdx +166 -0
  92. package/src/components/Badge/Badge.stories.tsx +193 -3
  93. package/src/components/Badge/Badge.tsx +5 -3
  94. package/src/components/Badge/Badge.types.ts +7 -5
  95. package/src/components/Badge/Badge.usage.mdx +265 -0
  96. package/src/components/Banner/Banner.stories.tsx +152 -2
  97. package/src/components/Banner/Banner.types.ts +30 -1
  98. package/src/components/Banner/Banner.usage.mdx +233 -0
  99. package/src/components/BottomSheet/BottomSheet.stories.tsx +168 -1
  100. package/src/components/BottomSheet/BottomSheet.usage.mdx +216 -0
  101. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +59 -0
  102. package/src/components/Breadcrumb/Breadcrumb.usage.mdx +181 -0
  103. package/src/components/Button/Button.stories.tsx +263 -3
  104. package/src/components/Button/Button.usage.mdx +342 -0
  105. package/src/components/Card/Card.stories.tsx +106 -0
  106. package/src/components/Card/Card.types.ts +12 -0
  107. package/src/components/Card/Card.usage.mdx +216 -0
  108. package/src/components/Checkbox/Checkbox.stories.tsx +140 -13
  109. package/src/components/Checkbox/Checkbox.usage.mdx +214 -0
  110. package/src/components/Chip/Chip.usage.mdx +78 -0
  111. package/src/components/Code/Code.stories.tsx +60 -0
  112. package/src/components/Code/Code.usage.mdx +187 -0
  113. package/src/components/CodeTabs/CodeTabs.stories.tsx +53 -0
  114. package/src/components/CodeTabs/CodeTabs.usage.mdx +176 -0
  115. package/src/components/Collapsible/Collapsible.stories.tsx +58 -0
  116. package/src/components/Collapsible/Collapsible.usage.mdx +173 -0
  117. package/src/components/ColorMode/ColorMode.stories.tsx +50 -0
  118. package/src/components/ColorMode/ColorMode.usage.mdx +135 -0
  119. package/src/components/ColorMode/ColorModeToggle.tsx +10 -3
  120. package/src/components/Confetti/Confetti.types.ts +5 -1
  121. package/src/components/Confetti/Confetti.usage.mdx +111 -0
  122. package/src/components/Confetti/confettiColors.ts +5 -5
  123. package/src/components/Container/Container.stories.tsx +32 -0
  124. package/src/components/Container/Container.usage.mdx +130 -0
  125. package/src/components/CopyableCode/CopyableCode.stories.tsx +62 -0
  126. package/src/components/CopyableCode/CopyableCode.usage.mdx +168 -0
  127. package/src/components/CountBadge/CountBadge.stories.tsx +69 -0
  128. package/src/components/CountBadge/CountBadge.usage.mdx +215 -0
  129. package/src/components/CountUp/CountUp.usage.mdx +107 -0
  130. package/src/components/DatePicker/DatePicker.usage.mdx +177 -0
  131. package/src/components/DatePicker/RangeDatePicker.stories.tsx +87 -3
  132. package/src/components/ErrorFallback/ErrorFallback.types.ts +6 -0
  133. package/src/components/ErrorFallback/ErrorFallback.usage.mdx +127 -0
  134. package/src/components/ExpandableText/ExpandableText.stories.tsx +55 -0
  135. package/src/components/ExpandableText/ExpandableText.usage.mdx +176 -0
  136. package/src/components/FileInput/FileInput.stories.tsx +38 -1
  137. package/src/components/FileInput/FileInput.usage.mdx +178 -0
  138. package/src/components/FileItem/FileItem.stories.tsx +71 -0
  139. package/src/components/FileItem/FileItem.usage.mdx +180 -0
  140. package/src/components/FileList/FileList.stories.tsx +25 -0
  141. package/src/components/FileList/FileList.usage.mdx +165 -0
  142. package/src/components/FlyTo/FlyTo.usage.mdx +99 -0
  143. package/src/components/Form/Form.stories.tsx +149 -0
  144. package/src/components/Form/Form.usage.mdx +201 -0
  145. package/src/components/Form/FormModalFooter/FormModalFooter.types.ts +4 -1
  146. package/src/components/FormControl/FormControl.stories.tsx +35 -0
  147. package/src/components/FormControl/FormControl.usage.mdx +128 -0
  148. package/src/components/FormIntegration/FormIntegration.usage.mdx +158 -0
  149. package/src/components/FormLabel/FormLabel.stories.tsx +71 -0
  150. package/src/components/FormLabel/FormLabel.usage.mdx +125 -0
  151. package/src/components/Icon/Icon.stories.tsx +61 -1
  152. package/src/components/Icon/Icon.usage.mdx +158 -0
  153. package/src/components/IconButton/IconButton.stories.tsx +209 -5
  154. package/src/components/IconButton/IconButton.usage.mdx +273 -0
  155. package/src/components/InfoSprinkle/InfoSprinkle.stories.tsx +77 -1
  156. package/src/components/InfoSprinkle/InfoSprinkle.usage.mdx +189 -0
  157. package/src/components/InlineCode/InlineCode.stories.tsx +75 -0
  158. package/src/components/InlineCode/InlineCode.usage.mdx +142 -0
  159. package/src/components/Input/Input.stories.tsx +180 -0
  160. package/src/components/Input/Input.usage.mdx +278 -0
  161. package/src/components/LineGraph/LineGraph.stories.tsx +112 -0
  162. package/src/components/LineGraph/LineGraph.tsx +4 -5
  163. package/src/components/LineGraph/LineGraph.types.ts +12 -2
  164. package/src/components/LineGraph/LineGraph.usage.mdx +186 -0
  165. package/src/components/LineGraph/seriesColors.test.ts +11 -10
  166. package/src/components/LineGraph/seriesColors.ts +18 -16
  167. package/src/components/Loaders/Loaders.stories.tsx +93 -0
  168. package/src/components/Loaders/Loaders.usage.mdx +180 -0
  169. package/src/components/LogicianProvider/LogicianProvider.usage.mdx +98 -0
  170. package/src/components/Markdown/Markdown.stories.tsx +53 -0
  171. package/src/components/Markdown/Markdown.usage.mdx +182 -0
  172. package/src/components/Masonry/Masonry.stories.tsx +63 -1
  173. package/src/components/Masonry/Masonry.types.ts +8 -3
  174. package/src/components/Masonry/Masonry.usage.mdx +142 -0
  175. package/src/components/MaxLengthIndicator/MaxLengthIndicator.stories.tsx +57 -0
  176. package/src/components/MaxLengthIndicator/MaxLengthIndicator.usage.mdx +125 -0
  177. package/src/components/Menu/Menu.stories.tsx +146 -2
  178. package/src/components/Menu/Menu.usage.mdx +230 -0
  179. package/src/components/Menu/MenuItem.types.ts +8 -0
  180. package/src/components/Modal/Modal.stories.tsx +177 -1
  181. package/src/components/Modal/Modal.usage.mdx +262 -0
  182. package/src/components/Modal/ModalCloseButton.tsx +1 -1
  183. package/src/components/MonthPicker/MonthPicker.stories.tsx +30 -0
  184. package/src/components/MonthPicker/MonthPicker.usage.mdx +191 -0
  185. package/src/components/Pagination/Pagination.stories.tsx +90 -1
  186. package/src/components/Pagination/Pagination.tsx +11 -10
  187. package/src/components/Pagination/Pagination.usage.mdx +186 -0
  188. package/src/components/PasswordInput/PasswordInput.stories.tsx +51 -0
  189. package/src/components/PasswordInput/PasswordInput.usage.mdx +193 -0
  190. package/src/components/PinInput/PinInput.stories.tsx +91 -0
  191. package/src/components/PinInput/PinInput.usage.mdx +194 -0
  192. package/src/components/Popover/Popover.stories.tsx +104 -1
  193. package/src/components/Popover/Popover.usage.mdx +197 -0
  194. package/src/components/ProgressBar/ProgressBar.stories.tsx +92 -1
  195. package/src/components/ProgressBar/ProgressBar.types.ts +9 -0
  196. package/src/components/ProgressBar/ProgressBar.usage.mdx +210 -0
  197. package/src/components/Pulse/Pulse.usage.mdx +102 -0
  198. package/src/components/RadialProgress/RadialProgress.stories.tsx +74 -1
  199. package/src/components/RadialProgress/RadialProgress.types.ts +21 -1
  200. package/src/components/RadialProgress/RadialProgress.usage.mdx +153 -0
  201. package/src/components/Radio/Radio.stories.tsx +119 -0
  202. package/src/components/Radio/Radio.usage.mdx +187 -0
  203. package/src/components/Reveal/Reveal.usage.mdx +105 -0
  204. package/src/components/ScaledContext/ScaledContext.usage.mdx +111 -0
  205. package/src/components/SeeMoreButton/SeeMoreButton.stories.tsx +146 -2
  206. package/src/components/SeeMoreButton/SeeMoreButton.types.ts +8 -0
  207. package/src/components/SeeMoreButton/SeeMoreButton.usage.mdx +213 -0
  208. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +69 -0
  209. package/src/components/SegmentedControl/SegmentedControl.tsx +6 -7
  210. package/src/components/SegmentedControl/SegmentedControl.usage.mdx +209 -0
  211. package/src/components/SegmentedProgressBar/SegmentedProgressBar.stories.tsx +54 -0
  212. package/src/components/SegmentedProgressBar/SegmentedProgressBar.types.ts +2 -0
  213. package/src/components/SegmentedProgressBar/SegmentedProgressBar.usage.mdx +145 -0
  214. package/src/components/Select/Select.stories.tsx +209 -1
  215. package/src/components/Select/Select.usage.mdx +278 -0
  216. package/src/components/Shake/Shake.usage.mdx +107 -0
  217. package/src/components/Slider/Slider.stories.tsx +116 -0
  218. package/src/components/Slider/Slider.usage.mdx +179 -0
  219. package/src/components/Spinner/Spinner.stories.tsx +64 -0
  220. package/src/components/Spinner/Spinner.usage.mdx +136 -0
  221. package/src/components/SwapTransition/SwapTransition.usage.mdx +102 -0
  222. package/src/components/Switch/Switch.stories.tsx +131 -6
  223. package/src/components/Switch/Switch.usage.mdx +199 -0
  224. package/src/components/Table/Table.stories.tsx +159 -1
  225. package/src/components/Table/Table.usage.mdx +235 -0
  226. package/src/components/Tabs/Tabs.stories.tsx +86 -0
  227. package/src/components/Tabs/Tabs.usage.mdx +219 -0
  228. package/src/components/Tag/Tag.stories.tsx +181 -4
  229. package/src/components/Tag/Tag.usage.mdx +257 -0
  230. package/src/components/Textarea/Textarea.stories.tsx +113 -0
  231. package/src/components/Textarea/Textarea.usage.mdx +186 -0
  232. package/src/components/Toast/Toast.stories.tsx +185 -3
  233. package/src/components/Toast/Toast.styles.ts +18 -10
  234. package/src/components/Toast/Toast.usage.mdx +265 -0
  235. package/src/components/Tooltip/Tooltip.stories.tsx +86 -1
  236. package/src/components/Tooltip/Tooltip.usage.mdx +211 -0
  237. package/src/components/Tree/Tree.stories.tsx +89 -0
  238. package/src/components/Tree/Tree.usage.mdx +207 -0
  239. package/src/components/Typography/Typography.stories.tsx +117 -0
  240. package/src/components/Typography/Typography.usage.mdx +251 -0
  241. package/src/components/Workflow/Workflow.usage.mdx +199 -0
  242. package/src/components/noRawScales.test.ts +5 -1
  243. package/src/foundations/BrandColour.mdx +364 -0
  244. package/src/foundations/BrandColour.stories.tsx +334 -0
  245. package/src/guidelines/ComponentPageTemplate.mdx +84 -0
  246. package/src/guidelines/FeedbackActions.mdx +162 -23
  247. package/src/guidelines/_components/Lang.tsx +175 -0
  248. package/src/guidelines/_components/TokenTable.tsx +136 -0
  249. package/src/theme/BazePalette.stories.tsx +111 -1
  250. package/src/theme/Palette.stories.tsx +2 -2
  251. package/src/theme/SemanticTokens.mdx +75 -16
  252. package/src/theme/claude.md +15 -9
  253. package/src/theme/colors.ts +33 -3
  254. package/src/theme/contrast.test.ts +32 -0
  255. package/src/theme/palette.generated.ts +99 -0
  256. package/src/theme/paletteSwatches.ts +35 -0
@@ -0,0 +1,158 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as IconStories from './Icon.stories';
5
+
6
+ <Meta of={IconStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Icon
13
+
14
+ The icon set: named exports such as `DownloadIcon`, `TrashIcon` and
15
+ `CheckIcon`, wrapped from react-icons and custom SVGs with `createIcon`.
16
+ Every icon takes `boxSize` (`2xs` 14px, `xs` 16px, `sm` 20px, `md` 24px
17
+ default, `lg` 32px, `xl` 40px) and paints `currentColor`, so it takes the
18
+ text colour around it unless you pass `color`.
19
+
20
+ ## When to use
21
+
22
+ - To help recognise an action or item next to its label.
23
+ - Inside an `IconButton`, where the button carries the name.
24
+
25
+ ## When not to use
26
+
27
+ - As the only way to say something (a status, an error) → words, with the
28
+ icon as support (`Badge`, `Banner`).
29
+ - As a decorative illustration → an image.
30
+ - A new icon from another set inline at the call site → add it to the set
31
+ (see `ICON_MANAGEMENT.md`) so every app gets the same one.
32
+
33
+ ## Do / Don't
34
+
35
+ </En>
36
+
37
+ <Ko>
38
+
39
+ # Icon
40
+
41
+ 아이콘 모음입니다. `DownloadIcon`, `TrashIcon`, `CheckIcon` 같은 이름으로 내보내며,
42
+ react-icons와 직접 만든 SVG를 `createIcon`으로 감쌌습니다. 모든 아이콘은
43
+ `boxSize`(`2xs` 14px, `xs` 16px, `sm` 20px, 기본 `md` 24px, `lg` 32px, `xl` 40px)를 받고
44
+ `currentColor`로 칠하므로, `color`를 넘기지 않으면 주변 글자색을 따릅니다.
45
+
46
+ ## 언제 쓰나요
47
+
48
+ - 라벨 옆에서 동작이나 항목을 알아보기 쉽게 할 때.
49
+ - `IconButton` 안에서. 이름은 버튼이 가집니다.
50
+
51
+ ## 언제 쓰지 않나요
52
+
53
+ - 아이콘만으로 무언가(상태, 오류)를 알리지 않습니다. 문구를 쓰고 아이콘은 거들게
54
+ 합니다(`Badge`, `Banner`).
55
+ - 장식용 그림에는 이미지를 씁니다.
56
+ - 다른 아이콘 모음의 아이콘을 호출부에서 바로 쓰지 않습니다. 모든 앱이 같은 아이콘을
57
+ 쓰도록 모음에 추가합니다(`ICON_MANAGEMENT.md` 참고).
58
+
59
+ ## 이렇게 하세요 / 이렇게 하지 마세요
60
+
61
+ </Ko>
62
+
63
+ <Canvas of={IconStories.DoIconWithLabel} />
64
+ <Verdict
65
+ kind="do"
66
+ en="Next to a label the icon is decorative (aria-hidden). On its own, the IconButton carries the name (aria-label)."
67
+ ko="라벨 옆의 아이콘은 장식이므로 aria-hidden을 붙입니다. 아이콘만 있다면 IconButton이 이름(aria-label)을 가집니다."
68
+ />
69
+
70
+ <Canvas of={IconStories.DontIconAsStatus} />
71
+ <Verdict
72
+ kind="dont"
73
+ en="Use a green check and a red cross as the only status. Without words the meaning rests on colour and shape alone."
74
+ ko="초록 체크와 빨간 X만으로 상태를 알리지 마세요. 문구가 없으면 색과 모양에만 뜻이 실립니다."
75
+ />
76
+
77
+ <En>
78
+
79
+ ## Content
80
+
81
+ - Use the same icon for the same action everywhere (`TrashIcon` is always
82
+ delete).
83
+ - Match the icon size to the text: `xs` beside body text and small buttons,
84
+ `sm`–`md` on their own.
85
+
86
+ ## Accessibility
87
+
88
+ What Icon does for you:
89
+
90
+ - It renders an inline SVG in `currentColor`, so it follows the text colour
91
+ in light, dark and high-contrast modes.
92
+
93
+ What you still have to do:
94
+
95
+ - **Mark decorative icons `aria-hidden`.** The icon does not hide itself.
96
+ - **Name icon-only controls** with `aria-label` on the button (WCAG 4.1.2),
97
+ and keep the label the same as any visible tooltip (WCAG 2.5.3).
98
+ - **Icons do not replace words** (WCAG 1.4.1). A standalone icon that means
99
+ something needs at least 3:1 against its background (WCAG 1.4.11);
100
+ `fg.icon` is tuned for that.
101
+
102
+ ## Tokens
103
+
104
+ The icon paints `currentColor`; these are the roles to set when you pass
105
+ `color`.
106
+
107
+ </En>
108
+
109
+ <Ko>
110
+
111
+ ## 문구
112
+
113
+ - 같은 동작에는 어디서나 같은 아이콘을 씁니다(`TrashIcon`은 언제나 삭제).
114
+ - 아이콘 크기는 글자에 맞춥니다. 본문과 작은 버튼 옆에는 `xs`, 아이콘만 있을 때는
115
+ `sm`–`md`를 씁니다.
116
+
117
+ ## 접근성
118
+
119
+ Icon이 알아서 하는 일
120
+
121
+ - `currentColor`로 칠하는 인라인 SVG라서 라이트, 다크, 고대비 모드에서 글자색을
122
+ 따릅니다.
123
+
124
+ 직접 챙겨야 하는 일
125
+
126
+ - **장식 아이콘에는 `aria-hidden`을 붙입니다.** 아이콘이 스스로 숨지 않습니다.
127
+ - **아이콘만 있는 컨트롤에는 버튼에 `aria-label`로 이름을 붙이고**(WCAG 4.1.2), 보이는
128
+ 툴팁이 있다면 같은 말을 씁니다(WCAG 2.5.3).
129
+ - **아이콘이 문구를 대신하지 않습니다**(WCAG 1.4.1). 뜻을 가진 아이콘이 혼자 있다면
130
+ 바탕과 3:1 이상이어야 하며(WCAG 1.4.11), `fg.icon`이 그 기준에 맞춰져 있습니다.
131
+
132
+ ## 토큰
133
+
134
+ 아이콘은 `currentColor`로 칠합니다. 아래는 `color`를 넘길 때 쓰는 역할입니다.
135
+
136
+ </Ko>
137
+
138
+ <Canvas of={IconStories.UsageTokens} sourceState="none" />
139
+
140
+ <En>
141
+
142
+ ## Related
143
+
144
+ - **IconButton**: an icon-only control with a name.
145
+ - **Badge** / **Banner**: status in words, with an icon as support.
146
+ - `ICON_MANAGEMENT.md`: adding an icon to the set.
147
+
148
+ </En>
149
+
150
+ <Ko>
151
+
152
+ ## 관련 컴포넌트
153
+
154
+ - **IconButton**: 이름이 있는 아이콘 전용 컨트롤.
155
+ - **Badge** / **Banner**: 아이콘이 거드는 문구 상태.
156
+ - `ICON_MANAGEMENT.md`: 아이콘 추가 방법.
157
+
158
+ </Ko>
@@ -1,8 +1,21 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
- import { Grid, HStack, Text, VStack } from '@chakra-ui/react';
4
- import { FaUniversity, SendIcon, TrashIcon } from '../Icon';
5
- import { IconButton, iconButtonVariants } from '.';
3
+ import { Box, Flex, Grid, HStack, Text, VStack } from '@chakra-ui/react';
4
+ import { T } from '../../guidelines/_components/Lang';
5
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
6
+ import { Button } from '../Button';
7
+ import {
8
+ CopyIcon,
9
+ DownloadIcon,
10
+ EditIcon,
11
+ FaUniversity,
12
+ PlusIcon,
13
+ SendIcon,
14
+ ShareIcon,
15
+ TrashIcon,
16
+ } from '../Icon';
17
+ import { Tooltip } from '../Tooltip';
18
+ import { IconButton, iconButtonVariants, iconButtonVariantStyles } from '.';
6
19
  import { IconButtonVariant } from './IconButton.types';
7
20
 
8
21
  const meta = {
@@ -16,11 +29,13 @@ const meta = {
16
29
  variant: {
17
30
  control: 'select',
18
31
  options: iconButtonVariants,
19
- description: 'Role. Default `ghost`.',
32
+ description:
33
+ 'Role. `ghost` (default): toolbars and row actions, glyph in `fg.icon`. `secondary`: ghost with an outline, for a control that must read as a button on its own. `primary`: black fill, the one main icon action. `danger`: red fill, confirms a destructive step. `action`: the coral send button of a chat composer.',
20
34
  },
21
35
  isDestructive: {
22
36
  control: 'boolean',
23
- description: 'Danger icon on ghost / secondary',
37
+ description:
38
+ 'Danger-coloured glyph (`danger.fg`) on `ghost` / `secondary`, for a delete icon in a row. Ignored on filled roles.',
24
39
  },
25
40
  children: {
26
41
  table: { disable: true },
@@ -121,3 +136,192 @@ export const ActionSend: Story = {
121
136
  </HStack>
122
137
  ),
123
138
  };
139
+
140
+ // ───────────────────────── Usage-page specimens ─────────────────────────
141
+ // Pulled into `IconButton.usage.mdx` with <Canvas of={…} />. Hidden from the
142
+ // sidebar (`!dev`); `tags` is written out on each story because the indexer
143
+ // reads CSF statically.
144
+
145
+ /** A chat message's action row: copy, edit, share, delete. */
146
+ export const DoGhostToolbar: Story = {
147
+ tags: ['!dev'],
148
+ parameters: { layout: 'padded' },
149
+ name: 'Usage / Do: ghost icon buttons in a toolbar',
150
+ render: () => (
151
+ <HStack gap={1}>
152
+ <Tooltip content="복사">
153
+ <IconButton aria-label="복사" size="sm">
154
+ <CopyIcon />
155
+ </IconButton>
156
+ </Tooltip>
157
+ <Tooltip content="수정">
158
+ <IconButton aria-label="수정" size="sm">
159
+ <EditIcon />
160
+ </IconButton>
161
+ </Tooltip>
162
+ <Tooltip content="공유">
163
+ <IconButton aria-label="공유" size="sm">
164
+ <ShareIcon />
165
+ </IconButton>
166
+ </Tooltip>
167
+ <Tooltip content="삭제">
168
+ <IconButton aria-label="삭제" size="sm" isDestructive>
169
+ <TrashIcon />
170
+ </IconButton>
171
+ </Tooltip>
172
+ </HStack>
173
+ ),
174
+ };
175
+
176
+ export const DontFilledToolbar: Story = {
177
+ tags: ['!dev'],
178
+ parameters: { layout: 'padded' },
179
+ name: "Usage / Don't: filled icon buttons in a toolbar",
180
+ render: () => (
181
+ <HStack gap={1}>
182
+ <IconButton aria-label="복사" size="sm" variant="primary">
183
+ <CopyIcon />
184
+ </IconButton>
185
+ <IconButton aria-label="수정" size="sm" variant="primary">
186
+ <EditIcon />
187
+ </IconButton>
188
+ <IconButton aria-label="공유" size="sm" variant="primary">
189
+ <ShareIcon />
190
+ </IconButton>
191
+ <IconButton aria-label="삭제" size="sm" variant="danger">
192
+ <TrashIcon />
193
+ </IconButton>
194
+ </HStack>
195
+ ),
196
+ };
197
+
198
+ /** A chat composer: the coral send button is the one run signal. */
199
+ export const DoActionForSend: Story = {
200
+ tags: ['!dev'],
201
+ parameters: { layout: 'padded' },
202
+ name: 'Usage / Do: action only for send',
203
+ render: () => (
204
+ <Flex
205
+ align="center"
206
+ gap={2}
207
+ maxW="420px"
208
+ px={4}
209
+ py={2}
210
+ borderWidth="1px"
211
+ borderColor="border.default"
212
+ borderRadius="xl"
213
+ bg="bg.surface"
214
+ >
215
+ <Tooltip content="파일 첨부">
216
+ <IconButton aria-label="파일 첨부" size="sm">
217
+ <PlusIcon />
218
+ </IconButton>
219
+ </Tooltip>
220
+ <Text flex={1} fontSize="sm" color="fg.default">
221
+ 지난달 사용량을 요약해 줘
222
+ </Text>
223
+ <IconButton aria-label="보내기" size="sm" variant="action">
224
+ <SendIcon />
225
+ </IconButton>
226
+ </Flex>
227
+ ),
228
+ };
229
+
230
+ export const DontActionForAdd: Story = {
231
+ tags: ['!dev'],
232
+ parameters: { layout: 'padded' },
233
+ name: "Usage / Don't: the coral action button for a non-send action",
234
+ render: () => (
235
+ <Flex align="center" justify="space-between" maxW="420px">
236
+ <Text fontWeight="bold" color="fg.default">
237
+ 멤버
238
+ </Text>
239
+ <IconButton aria-label="멤버 추가" size="sm" variant="action">
240
+ <PlusIcon />
241
+ </IconButton>
242
+ </Flex>
243
+ ),
244
+ };
245
+
246
+ export const DoTextWhenUnclear: Story = {
247
+ tags: ['!dev'],
248
+ parameters: { layout: 'padded' },
249
+ name: 'Usage / Do: a labelled Button when the icon is not obvious',
250
+ render: () => (
251
+ <Box>
252
+ <Button variant="secondary" size="sm">
253
+ <DownloadIcon />
254
+ 사용 내역 내려받기
255
+ </Button>
256
+ </Box>
257
+ ),
258
+ };
259
+
260
+ export const DontUnclearIcon: Story = {
261
+ tags: ['!dev'],
262
+ parameters: { layout: 'padded' },
263
+ name: "Usage / Don't: an icon only you can read",
264
+ render: () => (
265
+ <HStack gap={1}>
266
+ <IconButton aria-label="사용 내역 내려받기" variant="secondary" size="sm">
267
+ <FaUniversity />
268
+ </IconButton>
269
+ </HStack>
270
+ ),
271
+ };
272
+
273
+ type StateStyles = {
274
+ bgColor?: unknown;
275
+ borderColor?: unknown;
276
+ color?: unknown;
277
+ _hover?: { bgColor?: unknown; color?: unknown };
278
+ _active?: { bgColor?: unknown };
279
+ };
280
+
281
+ type Use = { en: string; ko: string };
282
+
283
+ /**
284
+ * One row per token, listing every role and state that reads it. Read from
285
+ * `iconButtonVariantStyles`, so a recipe change shows up on the next build.
286
+ */
287
+ const iconButtonTokenRows = () => {
288
+ const uses = new Map<string, Use[]>();
289
+ const add = (token: unknown, use: Use) => {
290
+ if (typeof token !== 'string' || token === 'transparent') return;
291
+ uses.set(token, [...(uses.get(token) ?? []), use]);
292
+ };
293
+ iconButtonVariants.forEach((variant) => {
294
+ const s = iconButtonVariantStyles[variant] as StateStyles;
295
+ const at = (en: string, ko: string) => ({
296
+ en: `${variant} ${en}`,
297
+ ko: `${variant} ${ko}`,
298
+ });
299
+ add(s.bgColor, at('fill', '바탕'));
300
+ add(s.borderColor, at('border', '테두리'));
301
+ add(s.color, at('icon', '아이콘'));
302
+ add(s._hover?.bgColor, at('hover fill', '마우스 올림 바탕'));
303
+ add(s._hover?.color, at('hover icon', '마우스 올림 아이콘'));
304
+ add(s._active?.bgColor, at('pressed fill', '누름 바탕'));
305
+ });
306
+ add('danger.fg', { en: 'isDestructive icon', ko: 'isDestructive 아이콘' });
307
+ add('disabled.bg', { en: 'disabled fill', ko: '비활성 바탕' });
308
+ add('disabled.fg', { en: 'disabled icon', ko: '비활성 아이콘' });
309
+ add('focus.ring', { en: 'keyboard focus ring', ko: '키보드 초점 링' });
310
+ return [...uses].map(([token, list]) => ({
311
+ token,
312
+ use: (
313
+ <T
314
+ en={list.map((u) => u.en).join(', ')}
315
+ ko={list.map((u) => u.ko).join(', ')}
316
+ />
317
+ ),
318
+ }));
319
+ };
320
+
321
+ /** Tokens each role reads, resolved from `IconButton.styles.ts` and the theme. */
322
+ export const UsageTokens: Story = {
323
+ tags: ['!dev'],
324
+ parameters: { layout: 'padded' },
325
+ name: 'Usage / Tokens',
326
+ render: () => <TokenTable rows={iconButtonTokenRows()} />,
327
+ };
@@ -0,0 +1,273 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as IconButtonStories from './IconButton.stories';
5
+
6
+ <Meta of={IconButtonStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # IconButton
13
+
14
+ A round button with an icon and no visible label, for actions so common that
15
+ the icon alone is enough: close, copy, edit, delete, send.
16
+
17
+ ## When to use
18
+
19
+ - Toolbars and per-item actions where a row of labels would crowd the
20
+ content: the copy, edit and share actions under a chat message, the delete
21
+ icon on a list row.
22
+ - Close and back in dialogs, drawers and panels.
23
+ - The send button of a chat composer (`variant="action"`).
24
+
25
+ ## When not to use
26
+
27
+ - The icon is not universally understood, or the action is rare or
28
+ destructive enough that the user should read it → `Button` with an icon and
29
+ a label.
30
+ - Opening a menu of more actions on its own → wrap the IconButton in
31
+ `Menu.Trigger asChild`, so the menu supplies the popup ARIA.
32
+ - A setting that stays on or off → `Switch`.
33
+ - "Load more" at the end of a list → `SeeMoreButton`.
34
+
35
+ ## Variants and what they mean
36
+
37
+ </En>
38
+
39
+ <Ko>
40
+
41
+ # IconButton
42
+
43
+ 글자 없이 아이콘만 있는 둥근 버튼입니다. 닫기, 복사, 수정, 삭제, 보내기처럼 아이콘만
44
+ 봐도 알 만큼 흔한 동작에 씁니다.
45
+
46
+ ## 언제 쓰나요
47
+
48
+ - 라벨을 늘어놓으면 내용이 답답해지는 툴바와 항목별 동작: 채팅 메시지 아래의 복사,
49
+ 수정, 공유, 목록 행의 삭제 아이콘.
50
+ - 대화상자, 서랍, 패널의 닫기와 뒤로 가기.
51
+ - 채팅 입력창의 보내기 버튼(`variant="action"`).
52
+
53
+ ## 언제 쓰지 않나요
54
+
55
+ - 누구나 아는 아이콘이 아니거나, 드물게 쓰거나, 사용자가 글로 읽어야 할 만큼 위험한
56
+ 동작이라면 아이콘과 라벨을 함께 넣은 `Button`을 씁니다.
57
+ - 더 많은 동작을 담은 메뉴를 IconButton 혼자 열게 하지 않습니다. `Menu.Trigger asChild`로
58
+ 감싸 메뉴가 팝업 ARIA를 붙이게 합니다.
59
+ - 켜짐과 꺼짐이 유지되는 설정이라면 `Switch`를 씁니다.
60
+ - 목록 끝의 "더보기"라면 `SeeMoreButton`을 씁니다.
61
+
62
+ ## 변형과 뜻
63
+
64
+ </Ko>
65
+
66
+ <ArgTypes of={IconButtonStories} include={['variant', 'isDestructive']} />
67
+
68
+ <En>
69
+
70
+ | Variant | Means | Use for |
71
+ | --- | --- | --- |
72
+ | `ghost` (default) | A routine action next to content. Glyph `fg.icon`, darkens on hover | 닫기, 복사, 수정, 뒤로 가기 |
73
+ | `secondary` | Ghost with an outline, so it reads as a button on its own | 이전 / 다음, 일시정지, 수정 취소 |
74
+ | `primary` | The one main icon action of its area. Black fill | 재생, 수정 저장 (check icon) |
75
+ | `danger` | Confirms a destructive step. Red fill | Rare; prefer `ghost` + `isDestructive` |
76
+ | `action` | Send. Coral fill, dark arrow | The chat composer's 보내기, nothing else |
77
+
78
+ `isDestructive` turns the glyph `danger.fg` on `ghost` and `secondary`; it is
79
+ ignored on the filled roles.
80
+
81
+ In FactChat, `ghost` makes up most IconButtons; `secondary` is used about a
82
+ fifth as often, and the filled roles are rare. Start from `ghost`.
83
+
84
+ ## Do / Don't
85
+
86
+ </En>
87
+
88
+ <Ko>
89
+
90
+ | 변형 | 뜻 | 예 |
91
+ | --- | --- | --- |
92
+ | `ghost` (기본) | 내용 옆의 일상적인 동작. 아이콘은 `fg.icon`이며 마우스를 올리면 진해짐 | 닫기, 복사, 수정, 뒤로 가기 |
93
+ | `secondary` | 테두리가 있는 ghost. 혼자 있어도 버튼으로 보임 | 이전 / 다음, 일시정지, 수정 취소 |
94
+ | `primary` | 그 영역의 주 아이콘 동작 하나. 검정 바탕 | 재생, 수정 저장(체크 아이콘) |
95
+ | `danger` | 되돌릴 수 없는 단계를 확정. 빨간 바탕 | 드물게 씀. 보통은 `ghost` + `isDestructive` |
96
+ | `action` | 보내기. 코랄 바탕에 어두운 화살표 | 채팅 입력창의 보내기에만 씀 |
97
+
98
+ `isDestructive`는 `ghost`와 `secondary`의 아이콘을 `danger.fg`로 바꿉니다. 바탕이
99
+ 있는 변형에서는 무시됩니다.
100
+
101
+ FactChat에서는 IconButton 대부분이 `ghost`이고, `secondary`는 그 5분의 1 정도이며,
102
+ 바탕이 있는 변형은 드뭅니다. `ghost`에서 시작합니다.
103
+
104
+ ## 이렇게 하세요 / 이렇게 하지 마세요
105
+
106
+ </Ko>
107
+
108
+ <Canvas of={IconButtonStories.DoGhostToolbar} />
109
+ <Verdict
110
+ kind="do"
111
+ en="Use ghost icon buttons in a toolbar, each with an aria-label and a tooltip that says the same thing. Mark delete with isDestructive."
112
+ ko="툴바에는 ghost 아이콘 버튼을 쓰고, 버튼마다 aria-label과 같은 말을 담은 툴팁을 붙입니다. 삭제에는 isDestructive를 붙입니다."
113
+ />
114
+
115
+ <Canvas of={IconButtonStories.DontFilledToolbar} />
116
+ <Verdict
117
+ kind="dont"
118
+ en="Fill every icon in a toolbar. Four black and red circles compete with the content they act on, and none of them is the main action."
119
+ ko="툴바의 아이콘마다 바탕을 채우지 마세요. 검정과 빨강 원 네 개가 정작 내용보다 눈에 띄고, 그중 어느 것도 주 행동이 아닙니다."
120
+ />
121
+
122
+ <Canvas of={IconButtonStories.DoActionForSend} />
123
+ <Verdict
124
+ kind="do"
125
+ en="Keep the coral action variant for send. It is the screen's one run signal; the attach button next to it stays ghost."
126
+ ko="코랄 action 변형은 보내기에만 씁니다. 화면의 유일한 실행 신호이며, 옆의 첨부 버튼은 ghost로 둡니다."
127
+ />
128
+
129
+ <Canvas of={IconButtonStories.DontActionForAdd} />
130
+ <Verdict
131
+ kind="dont"
132
+ en="Use the coral action button for add, settings or anything else. Coral means send or run; on any other action it reads as a second run signal."
133
+ ko="추가, 설정 같은 다른 동작에 코랄 action 버튼을 쓰지 마세요. 코랄은 보내기와 실행을 뜻하므로, 다른 동작에 쓰면 실행 신호가 두 개로 보입니다."
134
+ />
135
+
136
+ <Canvas of={IconButtonStories.DoTextWhenUnclear} />
137
+ <Verdict
138
+ kind="do"
139
+ en="When the icon would need explaining, use a Button with an icon and a label."
140
+ ko="아이콘에 설명이 필요하다면 아이콘과 라벨을 함께 넣은 Button을 씁니다."
141
+ />
142
+
143
+ <Canvas of={IconButtonStories.DontUnclearIcon} />
144
+ <Verdict
145
+ kind="dont"
146
+ en="Rely on an icon only its designer can read. The aria-label helps screen readers, but sighted users still have to guess."
147
+ ko="만든 사람만 알아보는 아이콘에 기대지 마세요. aria-label은 화면 낭독기 사용자에게만 도움이 되고, 화면을 보는 사용자는 여전히 짐작해야 합니다."
148
+ />
149
+
150
+ <En>
151
+
152
+ ## Content
153
+
154
+ IconButton has no visible text, so its content is the `aria-label` and the
155
+ tooltip.
156
+
157
+ - Name the action, not the icon: 삭제, not 휴지통; 보내기, not 화살표.
158
+ - Add the object when the row alone does not make it clear: 멤버 삭제,
159
+ 파일 내려받기.
160
+ - Use the same word as the tooltip and as any Button for the same action
161
+ elsewhere in the flow.
162
+ - Sentence case in English ("Copy link"). No full stop.
163
+
164
+ ## Accessibility
165
+
166
+ What IconButton does for you:
167
+
168
+ - It renders a native `<button>`, so Tab reaches it and Enter and Space
169
+ activate it (WCAG 2.1.1).
170
+ - A keyboard focus ring (`focus.ring` with a canvas-coloured inner band) on
171
+ `:focus-visible` only (WCAG 2.4.7).
172
+ - The resting glyph on `ghost` and `secondary` is `fg.icon`, chosen for 3:1
173
+ against the surface as a non-text graphic (WCAG 1.4.11).
174
+ - Disabled is a fixed colour pair, not opacity, and does not react to hover or
175
+ press.
176
+
177
+ What you still have to do:
178
+
179
+ - **Always pass `aria-label`.** The type does not require it, and without it
180
+ the button has no accessible name (WCAG 4.1.2; axe `button-name`, KWCAG
181
+ 5.3.4.1 in ACCESSIBILITY.md §1). Pass it on the first render, not after
182
+ hydration.
183
+ - **A tooltip is not the name.** Give the tooltip the same words as the
184
+ `aria-label`, so what a sighted user sees and what a speech-input user says
185
+ match (WCAG 2.5.3).
186
+ - **Hide nothing behind colour.** `isDestructive` and `danger` colour the
187
+ glyph; the label (삭제) is what carries the meaning (WCAG 1.4.1).
188
+ - **No IconButton inside another control** (ACCESSIBILITY.md §3, axe
189
+ `nested-interactive`). A delete icon on a clickable card goes next to the
190
+ card's link, not inside it.
191
+ - **Say why it is disabled.** A disabled send button (nothing typed yet) is
192
+ skipped by Tab; the empty input already explains it. Elsewhere, explain in
193
+ text.
194
+
195
+ ## Tokens
196
+
197
+ The table is generated from `IconButton.styles.ts` and the theme.
198
+ `transparent` fills and borders are left out. `primary` and `danger` reuse
199
+ Button's styles.
200
+
201
+ </En>
202
+
203
+ <Ko>
204
+
205
+ ## 문구
206
+
207
+ IconButton에는 보이는 글자가 없으므로 문구는 `aria-label`과 툴팁입니다.
208
+
209
+ - 아이콘이 아니라 동작을 적습니다. "휴지통"이 아니라 "삭제", "화살표"가 아니라
210
+ "보내기"입니다.
211
+ - 행만 보고는 대상이 분명하지 않다면 대상을 붙입니다: 멤버 삭제, 파일 내려받기.
212
+ - 툴팁, 그리고 같은 흐름에서 같은 동작을 하는 Button과 같은 말을 씁니다.
213
+ - 영어는 문장형 대소문자를 쓰고("Copy link") 마침표를 찍지 않습니다.
214
+
215
+ ## 접근성
216
+
217
+ IconButton이 알아서 하는 일
218
+
219
+ - 기본 `<button>`으로 렌더하므로 Tab으로 이동하고 Enter와 Space로 실행합니다(WCAG
220
+ 2.1.1).
221
+ - 키보드 초점에만(`:focus-visible`) 초점 링을 그립니다. `focus.ring`에 바탕색 안쪽
222
+ 띠를 더한 모양입니다(WCAG 2.4.7).
223
+ - `ghost`와 `secondary`의 평소 아이콘 색은 `fg.icon`입니다. 글자가 아닌 그래픽으로서
224
+ 바탕과 3:1 대비를 맞춘 값입니다(WCAG 1.4.11).
225
+ - 비활성 상태는 투명도가 아니라 고정된 색 한 쌍이며, 마우스를 올리거나 눌러도 변하지
226
+ 않습니다.
227
+
228
+ 직접 챙겨야 하는 일
229
+
230
+ - **`aria-label`을 반드시 줍니다.** 타입이 강제하지 않으며, 빠뜨리면 버튼에 접근 가능한
231
+ 이름이 없습니다(WCAG 4.1.2, axe `button-name`, ACCESSIBILITY.md 1절의 KWCAG
232
+ 5.3.4.1). 하이드레이션 이후가 아니라 첫 렌더부터 줍니다.
233
+ - **툴팁은 이름이 아닙니다.** 툴팁에 `aria-label`과 같은 말을 넣어, 눈으로 보는 말과
234
+ 음성으로 부르는 말이 같게 합니다(WCAG 2.5.3).
235
+ - **색에 뜻을 숨기지 않습니다.** `isDestructive`와 `danger`는 아이콘 색만 바꾸고, 뜻은
236
+ "삭제" 같은 라벨이 전합니다(WCAG 1.4.1).
237
+ - **컨트롤 안에 IconButton을 넣지 않습니다**(ACCESSIBILITY.md 3절, axe
238
+ `nested-interactive`). 누를 수 있는 카드의 삭제 아이콘은 카드 링크 안이 아니라
239
+ 옆에 둡니다.
240
+ - **왜 비활성인지 알립니다.** 아직 아무것도 입력하지 않아 비활성인 보내기 버튼은 Tab이
241
+ 건너뛰지만, 빈 입력창이 이유를 보여 줍니다. 다른 자리에서는 글로 이유를 적습니다.
242
+
243
+ ## 토큰
244
+
245
+ 아래 표는 `IconButton.styles.ts`와 테마에서 자동으로 만듭니다. `transparent`인
246
+ 바탕과 테두리는 뺐습니다. `primary`와 `danger`는 Button의 스타일을 그대로 씁니다.
247
+
248
+ </Ko>
249
+
250
+ <Canvas of={IconButtonStories.UsageTokens} sourceState="none" />
251
+
252
+ <En>
253
+
254
+ ## Related
255
+
256
+ - **Button**: the same roles with a visible label.
257
+ - **Tooltip**: the visible name of an IconButton.
258
+ - **Menu**: an icon that opens more actions.
259
+ - **Foundations/Brand & colour usage**: why the send button is the one coral
260
+ fill.
261
+
262
+ </En>
263
+
264
+ <Ko>
265
+
266
+ ## 관련 컴포넌트
267
+
268
+ - **Button**: 보이는 라벨이 있는 버튼. 역할은 같습니다.
269
+ - **Tooltip**: IconButton의 이름을 눈에 보이게 하는 도구.
270
+ - **Menu**: 더 많은 동작을 여는 아이콘.
271
+ - **Foundations/Brand & colour usage**: 보내기 버튼만 코랄 바탕인 이유.
272
+
273
+ </Ko>