@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,176 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as ExpandableTextStories from './ExpandableText.stories';
5
+
6
+ <Meta of={ExpandableTextStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # ExpandableText
13
+
14
+ Text clipped to a number of lines, with a 더보기 / 접기 link that opens it.
15
+ Opening animates the height, so the content below slides down rather than
16
+ jumping. The link appears only when the text actually overflows.
17
+
18
+ ## When to use
19
+
20
+ - A long secondary description in a card or a header: a chatbot's
21
+ description, an announcement preview, an image prompt in a history list.
22
+
23
+ ## When not to use
24
+
25
+ - The main content the reader came for → show it in full.
26
+ - Warnings, prices, terms, or anything the reader must not miss → show it in
27
+ full.
28
+ - A section with a heading and structure → `Collapsible`.
29
+
30
+ ## Props
31
+
32
+ | Prop | Means |
33
+ | --- | --- |
34
+ | `lineClamp` | Lines shown while closed. Default `3`. |
35
+ | `component` | The typography tier that wraps it: `Text` (default), `Subtitle`, `Subtext`, `H1`–`H5`. Other props go to that component. |
36
+ | `charLimit` | Deprecated and ignored. Truncation is by line. |
37
+
38
+ ## Do / Don't
39
+
40
+ </En>
41
+
42
+ <Ko>
43
+
44
+ # ExpandableText
45
+
46
+ 정해진 줄 수만큼만 보여 주고, '더보기' / '접기' 링크로 펼치는 글입니다. 펼칠 때 높이가
47
+ 움직이므로 아래 내용이 갑자기 튀지 않고 밀려 내려갑니다. 링크는 글이 실제로 넘칠 때만
48
+ 나타납니다.
49
+
50
+ ## 언제 쓰나요
51
+
52
+ - 카드나 머리 영역의 긴 보조 설명: 챗봇 설명, 공지 미리보기, 이미지 기록 목록의
53
+ 프롬프트.
54
+
55
+ ## 언제 쓰지 않나요
56
+
57
+ - 읽는 사람이 보러 온 본 내용은 전부 보여 줍니다.
58
+ - 경고, 가격, 약관처럼 놓치면 안 되는 내용은 전부 보여 줍니다.
59
+ - 제목과 구조가 있는 섹션은 `Collapsible`을 씁니다.
60
+
61
+ ## 속성
62
+
63
+ | 속성 | 뜻 |
64
+ | --- | --- |
65
+ | `lineClamp` | 접혀 있을 때 보여 줄 줄 수. 기본값 `3`. |
66
+ | `component` | 감싸는 글자 단계: `Text`(기본값), `Subtitle`, `Subtext`, `H1`–`H5`. 나머지 속성은 이 컴포넌트로 넘어갑니다. |
67
+ | `charLimit` | deprecated이며 무시됩니다. 글은 줄 단위로 자릅니다. |
68
+
69
+ ## 이렇게 하세요 / 이렇게 하지 마세요
70
+
71
+ </Ko>
72
+
73
+ <Canvas of={ExpandableTextStories.DoSecondaryDescription} />
74
+ <Verdict
75
+ kind="do"
76
+ en="Clip a long secondary description so the cards in a row stay the same height."
77
+ ko="긴 보조 설명을 접어서, 한 줄에 놓인 카드들의 높이를 맞춥니다."
78
+ />
79
+
80
+ <Canvas of={ExpandableTextStories.DontClipTheMessage} />
81
+ <Verdict
82
+ kind="dont"
83
+ en="Clip a warning. The consequence sits behind 더보기, where most people never look."
84
+ ko="경고를 접지 마세요. 결과가 '더보기' 뒤에 숨어 대부분의 사람이 보지 못합니다."
85
+ />
86
+
87
+ <En>
88
+
89
+ ## Content
90
+
91
+ - Put the most important sentence first, so the clipped lines still say what
92
+ the text is about.
93
+ - Keep `lineClamp` the same for every item in a list.
94
+
95
+ ## Accessibility
96
+
97
+ What ExpandableText does for you:
98
+
99
+ - The toggle is a `<button>` styled as a link, with `aria-expanded`, and a
100
+ translated label (더보기 / 접기) (WCAG 2.1.1, 4.1.2).
101
+ - The full text is in the DOM while closed; only its height is clipped, so
102
+ find-in-page and text selection reach it.
103
+
104
+ What you still have to do:
105
+
106
+ - While closed, the hidden lines are still read by a screen reader (they are
107
+ only clipped visually). Do not rely on the clamp to shorten what is
108
+ announced.
109
+ - Do not use a heading tier (`H1`–`H5`) for a long paragraph only to get its
110
+ size; the whole paragraph becomes a heading (`ACCESSIBILITY.md` §2).
111
+ - Known markup issue: the clipping box is a `<div>` inside the `<p>` (or
112
+ heading) that `component` renders, which a markup validator reports as a
113
+ nesting error (KWCAG 5.4.1.1). Tracked in the PR that added this page.
114
+
115
+ ## Tokens
116
+
117
+ The toggle is a `Link`; on hover it turns `fg.default` instead of
118
+ `fg.linkHover`, and it has no underline.
119
+
120
+ </En>
121
+
122
+ <Ko>
123
+
124
+ ## 문구
125
+
126
+ - 가장 중요한 문장을 앞에 둡니다. 그래야 접힌 상태에서도 무엇에 관한 글인지 알 수
127
+ 있습니다.
128
+ - 한 목록 안의 항목은 모두 같은 `lineClamp`를 씁니다.
129
+
130
+ ## 접근성
131
+
132
+ ExpandableText가 알아서 하는 일
133
+
134
+ - 펼침 버튼은 링크 모양의 `<button>`이고, `aria-expanded`와 번역된 이름('더보기' /
135
+ '접기')이 있습니다(WCAG 2.1.1, 4.1.2).
136
+ - 접혀 있어도 전체 글이 DOM에 있고 높이만 잘립니다. 그래서 페이지 내 검색과 글 선택이
137
+ 닿습니다.
138
+
139
+ 직접 챙겨야 하는 일
140
+
141
+ - 접혀 있어도 화면 낭독기는 숨은 줄까지 읽습니다(화면에서만 잘립니다). 읽히는 양을
142
+ 줄이는 용도로 쓰지 않습니다.
143
+ - 크기만 보고 긴 문단에 제목 단계(`H1`–`H5`)를 쓰지 않습니다. 문단 전체가 제목이
144
+ 됩니다(`ACCESSIBILITY.md` 2절).
145
+ - 알려진 마크업 문제: 자르는 상자가 `component`가 그리는 `<p>`(또는 제목) 안의
146
+ `<div>`라서, 마크업 검사기가 중첩 오류로 봅니다(KWCAG 5.4.1.1). 이 페이지를 추가한
147
+ PR에 기록해 두었습니다.
148
+
149
+ ## 토큰
150
+
151
+ 펼침 버튼은 `Link`입니다. 호버하면 `fg.linkHover`가 아니라 `fg.default`로 바뀌고,
152
+ 밑줄이 없습니다.
153
+
154
+ </Ko>
155
+
156
+ <Canvas of={ExpandableTextStories.UsageTokens} sourceState="none" />
157
+
158
+ <En>
159
+
160
+ ## Related
161
+
162
+ - **Collapsible**: a section with a trigger.
163
+ - **Typography**: the tiers `component` can use.
164
+ - **Markdown**: formatted long text.
165
+
166
+ </En>
167
+
168
+ <Ko>
169
+
170
+ ## 관련 컴포넌트
171
+
172
+ - **Collapsible**: 트리거가 있는 섹션.
173
+ - **Typography**: `component`로 고를 수 있는 글자 단계.
174
+ - **Markdown**: 서식 있는 긴 글.
175
+
176
+ </Ko>
@@ -1,9 +1,12 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { useState } from 'react';
3
3
 
4
+ import { Stack } from '@chakra-ui/react';
5
+
6
+ import { FieldRow } from '../Form';
4
7
  import { FileInput } from '.';
5
8
 
6
- const meta = {
9
+ const meta = {
7
10
  title: 'Components/FileInput',
8
11
  component: FileInput,
9
12
  args: {
@@ -36,3 +39,37 @@ export const Basic: Story = {
36
39
  return <FileInput onChange={handleChange} bgImage={bgImage} />;
37
40
  },
38
41
  };
42
+
43
+ // ───────────────────────── Usage-page specimens ─────────────────────────
44
+ // Pulled into `FileInput.usage.mdx` with <Canvas of={…} />. Hidden (`!dev`).
45
+
46
+ export const DoSayWhatFits: Story = {
47
+ tags: ['!dev'],
48
+ parameters: { layout: 'padded' },
49
+ name: 'Usage / Do: say which files fit',
50
+ render: () => (
51
+ <Stack maxW="420px">
52
+ <FieldRow
53
+ label="멤버 목록 파일"
54
+ helperText="CSV 또는 XLSX, 최대 5MB. 첫 줄은 이메일, 이름 순서입니다."
55
+ >
56
+ <FileInput
57
+ accept=".csv,.xlsx"
58
+ fileInputLabel="파일을 눌러서 고르기"
59
+ onChange={() => {}}
60
+ />
61
+ </FieldRow>
62
+ </Stack>
63
+ ),
64
+ };
65
+
66
+ export const DontUnexplained: Story = {
67
+ tags: ['!dev'],
68
+ parameters: { layout: 'padded' },
69
+ name: "Usage / Don't: no type, size or purpose",
70
+ render: () => (
71
+ <Stack maxW="420px">
72
+ <FileInput onChange={() => {}} />
73
+ </Stack>
74
+ ),
75
+ };
@@ -0,0 +1,178 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as FileInputStories from './FileInput.stories';
5
+
6
+ <Meta of={FileInputStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # FileInput
13
+
14
+ A dashed area that opens the system file picker when clicked, with an
15
+ optional image preview behind it.
16
+
17
+ ## When to use
18
+
19
+ - Uploading a file into a form: a member list CSV, a policy document,
20
+ reference images, a project file.
21
+ - Replacing an image, with the current one shown through `bgImage`.
22
+
23
+ ## When not to use
24
+
25
+ - Attaching files to a chat message → the chat composer's attach button.
26
+ - Showing files already uploaded → `FileList` or `FileItem` (put them under
27
+ the FileInput).
28
+
29
+ ## Props
30
+
31
+ </En>
32
+
33
+ <Ko>
34
+
35
+ # FileInput
36
+
37
+ 누르면 시스템 파일 선택 창이 열리는 점선 영역입니다. 뒤에 이미지 미리보기를 깔 수
38
+ 있습니다.
39
+
40
+ ## 언제 쓰나요
41
+
42
+ - 폼에 파일을 올릴 때: 멤버 목록 CSV, 정책 문서, 참고 이미지, 프로젝트 파일.
43
+ - 이미지를 바꿀 때. 지금 이미지는 `bgImage`로 보여 줍니다.
44
+
45
+ ## 언제 쓰지 않나요
46
+
47
+ - 채팅 메시지에 파일을 붙일 때는 채팅 입력창의 첨부 버튼을 씁니다.
48
+ - 이미 올린 파일을 보여 줄 때는 `FileList`나 `FileItem`을 씁니다(FileInput 아래에
49
+ 둡니다).
50
+
51
+ ## 속성
52
+
53
+ </Ko>
54
+
55
+ <ArgTypes
56
+ of={FileInputStories}
57
+ include={[
58
+ 'onChange',
59
+ 'fileInputLabel',
60
+ 'bgImage',
61
+ 'isLoading',
62
+ 'containerStyle',
63
+ ]}
64
+ />
65
+
66
+ <En>
67
+
68
+ `onChange` receives the browser's `FileList` (or `null`). Native input props
69
+ such as `accept`, `multiple` and `name` pass through to the hidden
70
+ `<input type="file">`, and the forwarded ref points at it. `isLoading`
71
+ replaces the prompt with a spinner. The default prompt is translated
72
+ (`upload_your_file`). The area does not handle drag and drop.
73
+
74
+ ## Do / Don't
75
+
76
+ </En>
77
+
78
+ <Ko>
79
+
80
+ `onChange`는 브라우저의 `FileList`(또는 `null`)를 받습니다. `accept`, `multiple`,
81
+ `name` 같은 네이티브 속성은 숨은 `<input type="file">`에 그대로 전달되고, 넘긴 ref도 이
82
+ 입력을 가리킵니다. `isLoading`이면 안내 문구 대신 스피너를 보여 줍니다. 기본 안내
83
+ 문구는 번역됩니다(`upload_your_file`). 끌어다 놓기는 처리하지 않습니다.
84
+
85
+ ## 이렇게 하세요 / 이렇게 하지 마세요
86
+
87
+ </Ko>
88
+
89
+ <Canvas of={FileInputStories.DoSayWhatFits} />
90
+ <Verdict
91
+ kind="do"
92
+ en="Label it, set accept, and say the allowed types, size limit and expected layout in helper text."
93
+ ko="라벨을 붙이고 accept를 지정하며, 받는 형식, 최대 크기, 내용 형식을 도움말로 알려 줍니다."
94
+ />
95
+
96
+ <Canvas of={FileInputStories.DontUnexplained} />
97
+ <Verdict
98
+ kind="dont"
99
+ en="Show the drop area with only the default prompt. The user finds out the rules by failing."
100
+ ko="기본 안내 문구만 있는 영역을 두지 마세요. 사용자는 실패하고 나서야 조건을 압니다."
101
+ />
102
+
103
+ <En>
104
+
105
+ ## Content
106
+
107
+ - The prompt says what to do with the pointer (파일을 눌러서 고르기). Do not
108
+ promise dragging; it is not supported.
109
+ - Types and size limit go in `FieldRow` `helperText`, the same words the
110
+ error will use.
111
+
112
+ ## Accessibility
113
+
114
+ What FileInput does for you:
115
+
116
+ - The prompt sits inside a `<label>` around the file input, so clicking
117
+ anywhere in it opens the picker. There is no extra role on the wrapper
118
+ (`ACCESSIBILITY.md` §3).
119
+
120
+ Known gap, and what to do:
121
+
122
+ - **It cannot be reached by keyboard.** The file input is `hidden`, so it is
123
+ out of the tab order and the label is not focusable (WCAG 2.1.1). Until the
124
+ component is fixed, add a visible `Button` next to it that calls
125
+ `ref.current?.click()`.
126
+ - Wrap it in `FieldRow` with a label so the purpose is in text (WCAG 3.3.2),
127
+ and report rejected files in words, not only with the red row in
128
+ `FileItem` (WCAG 3.3.1).
129
+
130
+ ## Tokens
131
+
132
+ The dashed border is `border.default`; the prompt and icon are `fg.subtle` on
133
+ a `bg.muted` tile, over an 85% `bg.surface` wash. With `bgImage` the prompt
134
+ turns `fg.default` and appears on hover.
135
+
136
+ ## Related
137
+
138
+ - **FileList** / **FileItem**: what was uploaded.
139
+ - **FieldRow**: label, rules and error.
140
+
141
+ </En>
142
+
143
+ <Ko>
144
+
145
+ ## 문구
146
+
147
+ - 안내 문구에는 포인터로 할 일을 씁니다(파일을 눌러서 고르기). 끌어다 놓기는 지원하지
148
+ 않으므로 약속하지 않습니다.
149
+ - 형식과 최대 크기는 `FieldRow`의 `helperText`에 쓰고, 오류 문구에서도 같은 표현을
150
+ 씁니다.
151
+
152
+ ## 접근성
153
+
154
+ FileInput이 알아서 하는 일
155
+
156
+ - 안내 문구가 파일 입력을 감싼 `<label>` 안에 있어서 영역 어디를 눌러도 선택 창이
157
+ 열립니다. 감싸는 요소에 불필요한 역할을 주지 않습니다(`ACCESSIBILITY.md` 3절).
158
+
159
+ 알려진 한계와 대처
160
+
161
+ - **키보드로 닿을 수 없습니다.** 파일 입력이 `hidden`이라 Tab 순서에서 빠지고, 라벨도
162
+ 초점을 받지 않습니다(WCAG 2.1.1). 고쳐지기 전까지는 옆에 `ref.current?.click()`을
163
+ 호출하는 보이는 `Button`을 둡니다.
164
+ - 라벨이 있는 `FieldRow`로 감싸 용도를 글자로 알리고(WCAG 3.3.2), 받지 못한 파일은
165
+ `FileItem`의 빨간 행만이 아니라 문구로 알립니다(WCAG 3.3.1).
166
+
167
+ ## 토큰
168
+
169
+ 점선 테두리는 `border.default`, 안내 문구와 아이콘은 `bg.muted` 타일 위의
170
+ `fg.subtle`이며, 바탕은 85% `bg.surface`입니다. `bgImage`가 있으면 안내 문구가
171
+ `fg.default`로 바뀌고 마우스를 올렸을 때 나타납니다.
172
+
173
+ ## 관련 컴포넌트
174
+
175
+ - **FileList** / **FileItem**: 올린 파일.
176
+ - **FieldRow**: 라벨, 조건, 오류 문구.
177
+
178
+ </Ko>
@@ -1,5 +1,10 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
+ import { Stack } from '@chakra-ui/react';
4
+
5
+ import { T } from '../../guidelines/_components/Lang';
6
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
7
+ import { FieldRow } from '../Form';
3
8
  import { FileItem } from './FileItem';
4
9
 
5
10
  const meta = {
@@ -53,3 +58,69 @@ export const Deleting: Story = {
53
58
  isDeleting: true,
54
59
  },
55
60
  };
61
+
62
+ // ───────────────────────── Usage-page specimens ─────────────────────────
63
+ // Pulled into `FileItem.usage.mdx` with <Canvas of={…} />. Hidden (`!dev`).
64
+
65
+ export const DoErrorInText: Story = {
66
+ tags: ['!dev'],
67
+ parameters: { layout: 'padded' },
68
+ name: 'Usage / Do: repeat the error in text',
69
+ render: () => (
70
+ <Stack maxW="480px">
71
+ <FieldRow error="members.xlsx: 파일이 5MB를 넘습니다. 나눠서 올려 주세요.">
72
+ <FileItem
73
+ fileName="members.xlsx"
74
+ error="파일이 5MB를 넘습니다."
75
+ onFileDelete={() => {}}
76
+ />
77
+ </FieldRow>
78
+ </Stack>
79
+ ),
80
+ };
81
+
82
+ export const DontErrorInTooltipOnly: Story = {
83
+ tags: ['!dev'],
84
+ parameters: { layout: 'padded' },
85
+ name: "Usage / Don't: the reason only in a tooltip",
86
+ render: () => (
87
+ <Stack maxW="480px">
88
+ <FileItem
89
+ fileName="members.xlsx"
90
+ error="파일이 5MB를 넘습니다."
91
+ onFileDelete={() => {}}
92
+ />
93
+ </Stack>
94
+ ),
95
+ };
96
+
97
+ /** Tokens `FileItem.tsx` reads. */
98
+ export const UsageTokens: Story = {
99
+ tags: ['!dev'],
100
+ parameters: { layout: 'padded' },
101
+ name: 'Usage / Tokens',
102
+ render: () => (
103
+ <TokenTable
104
+ rows={[
105
+ { token: 'border.subtle', use: <T en="Row border" ko="행 테두리" /> },
106
+ {
107
+ token: 'fg.muted',
108
+ use: <T en="File icon, action icons" ko="파일 아이콘, 동작 아이콘" />,
109
+ },
110
+ {
111
+ token: 'fg.subtle',
112
+ use: <T en="Cancel-upload icon" ko="업로드 취소 아이콘" />,
113
+ },
114
+ {
115
+ token: 'danger.fg',
116
+ use: (
117
+ <T
118
+ en="Error: left bar, icon, file name"
119
+ ko="오류: 왼쪽 막대, 아이콘, 파일 이름"
120
+ />
121
+ ),
122
+ },
123
+ ]}
124
+ />
125
+ ),
126
+ };
@@ -0,0 +1,180 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as FileItemStories from './FileItem.stories';
5
+
6
+ <Meta of={FileItemStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # FileItem
13
+
14
+ One row for one file: its name, upload progress or size, and download and
15
+ delete buttons.
16
+
17
+ ## When to use
18
+
19
+ - A single attached or uploaded file in a form: the CSV just picked, a
20
+ template being uploaded, a verification document.
21
+
22
+ ## When not to use
23
+
24
+ - Several files → `FileList`, which renders FileItem rows and a "see more".
25
+ - A file inside a chat message → the chat attachment components.
26
+
27
+ ## Props
28
+
29
+ </En>
30
+
31
+ <Ko>
32
+
33
+ # FileItem
34
+
35
+ 파일 하나를 보여 주는 한 줄입니다. 파일 이름, 업로드 진행률이나 크기, 내려받기와 삭제
36
+ 버튼이 있습니다.
37
+
38
+ ## 언제 쓰나요
39
+
40
+ - 폼에 붙인 파일 하나: 방금 고른 CSV, 올리는 중인 템플릿, 증빙 서류.
41
+
42
+ ## 언제 쓰지 않나요
43
+
44
+ - 파일이 여러 개라면 `FileList`를 씁니다. FileItem 행과 "더 보기"를 그려 줍니다.
45
+ - 채팅 메시지 안의 파일은 채팅 첨부 컴포넌트를 씁니다.
46
+
47
+ ## 속성
48
+
49
+ </Ko>
50
+
51
+ <ArgTypes
52
+ of={FileItemStories}
53
+ include={[
54
+ 'fileName',
55
+ 'progress',
56
+ 'fileSize',
57
+ 'error',
58
+ 'onFileDownload',
59
+ 'onFileDelete',
60
+ 'isDownloading',
61
+ 'isDeleting',
62
+ ]}
63
+ />
64
+
65
+ <En>
66
+
67
+ - `progress` from 0 to 99 shows a percentage, a bar, a spinner and a cancel
68
+ button that calls `onFileDelete`. At 100, or with no `progress`, the row
69
+ shows the size and the actions.
70
+ - The download and delete buttons appear only when you pass their handlers.
71
+ `isDownloading` / `isDeleting` swap them for a spinner.
72
+ - `error` turns the name, icon and left edge `danger.fg` and puts the message
73
+ in a tooltip on an alert icon. It hides the download button.
74
+
75
+ ## Do / Don't
76
+
77
+ </En>
78
+
79
+ <Ko>
80
+
81
+ - `progress`가 0~99이면 백분율, 진행 막대, 스피너, `onFileDelete`를 부르는 취소 버튼을
82
+ 보여 줍니다. 100이거나 `progress`가 없으면 크기와 동작 버튼을 보여 줍니다.
83
+ - 내려받기와 삭제 버튼은 처리 함수를 넘겼을 때만 나타납니다. `isDownloading`·
84
+ `isDeleting`이면 버튼 대신 스피너가 보입니다.
85
+ - `error`를 주면 이름, 아이콘, 왼쪽 가장자리가 `danger.fg`로 바뀌고, 문구는 경고
86
+ 아이콘의 툴팁에 들어갑니다. 내려받기 버튼은 숨겨집니다.
87
+
88
+ ## 이렇게 하세요 / 이렇게 하지 마세요
89
+
90
+ </Ko>
91
+
92
+ <Canvas of={FileItemStories.DoErrorInText} />
93
+ <Verdict
94
+ kind="do"
95
+ en="Repeat the reason in text under the row, with the file name, so it can be read without hovering."
96
+ ko="실패 이유를 파일 이름과 함께 행 아래에 글자로 한 번 더 보여 줍니다. 마우스를 올리지 않아도 읽을 수 있습니다."
97
+ />
98
+
99
+ <Canvas of={FileItemStories.DontErrorInTooltipOnly} />
100
+ <Verdict
101
+ kind="dont"
102
+ en="Leave the reason only in the tooltip. The icon is not focusable, so keyboard and screen reader users never reach it."
103
+ ko="실패 이유를 툴팁에만 두지 마세요. 아이콘이 초점을 받지 않아서 키보드와 화면 낭독기 사용자는 끝내 읽지 못합니다."
104
+ />
105
+
106
+ <En>
107
+
108
+ ## Content
109
+
110
+ - Show the real file name; let it truncate rather than rewriting it.
111
+ - Error text says what failed and what to do (파일이 5MB를 넘습니다. 나눠서
112
+ 올려 주세요.).
113
+
114
+ ## Accessibility
115
+
116
+ What FileItem does for you:
117
+
118
+ - Download and delete are `IconButton`s with translated names and tooltips.
119
+
120
+ Known gaps, and what to do:
121
+
122
+ - **The error is in a hover tooltip on a non-focusable icon** (WCAG 1.4.1,
123
+ 3.3.1). Repeat it in text, as above.
124
+ - **The cancel-upload button is named in English** ("remove uploading file
125
+ button") on every screen, Korean included.
126
+ - Progress is shown as a percentage and a bar; a screen reader is not told
127
+ when the upload finishes. Announce completion with a toast (WCAG 4.1.3).
128
+
129
+ ## Tokens
130
+
131
+ </En>
132
+
133
+ <Ko>
134
+
135
+ ## 문구
136
+
137
+ - 실제 파일 이름을 그대로 보여 줍니다. 길면 고쳐 쓰지 말고 말줄임표로 자릅니다.
138
+ - 오류 문구는 무엇이 실패했고 어떻게 하면 되는지 씁니다(파일이 5MB를 넘습니다. 나눠서
139
+ 올려 주세요.).
140
+
141
+ ## 접근성
142
+
143
+ FileItem이 알아서 하는 일
144
+
145
+ - 내려받기와 삭제는 번역된 이름과 툴팁이 있는 `IconButton`입니다.
146
+
147
+ 알려진 한계와 대처
148
+
149
+ - **오류 문구가 초점을 받지 않는 아이콘의 툴팁에만 있습니다**(WCAG 1.4.1, 3.3.1). 위처럼
150
+ 글자로 한 번 더 보여 줍니다.
151
+ - **업로드 취소 버튼 이름이 영어입니다**("remove uploading file button"). 한국어 화면에서도
152
+ 영어로 읽힙니다.
153
+ - 진행 상황은 백분율과 막대로만 보이고, 업로드가 끝났다는 사실은 화면 낭독기에 알리지
154
+ 않습니다. 끝나면 토스트로 알립니다(WCAG 4.1.3).
155
+
156
+ ## 토큰
157
+
158
+ </Ko>
159
+
160
+ <Canvas of={FileItemStories.UsageTokens} sourceState="none" />
161
+
162
+ <En>
163
+
164
+ ## Related
165
+
166
+ - **FileList**: several FileItem rows.
167
+ - **FileInput**: picking the file.
168
+ - **ProgressBar** / **Tooltip**: the parts it uses.
169
+
170
+ </En>
171
+
172
+ <Ko>
173
+
174
+ ## 관련 컴포넌트
175
+
176
+ - **FileList**: FileItem 여러 줄.
177
+ - **FileInput**: 파일 고르기.
178
+ - **ProgressBar** / **Tooltip**: 안에서 쓰는 부품.
179
+
180
+ </Ko>
@@ -53,3 +53,28 @@ export const Default: Story = {
53
53
  return <FileList {...args} files={files} onFileDelete={handleFileDelete} />;
54
54
  },
55
55
  };
56
+
57
+ // ───────────────────────── Usage-page specimens ─────────────────────────
58
+ // Pulled into `FileList.usage.mdx` with <Canvas of={…} />. Hidden (`!dev`).
59
+
60
+ export const DoDownloadAndDelete: Story = {
61
+ tags: ['!dev'],
62
+ parameters: { layout: 'padded' },
63
+ name: 'Usage / Do: download where there is a URL',
64
+ render: () => (
65
+ <FileList
66
+ files={[
67
+ {
68
+ id: 1,
69
+ name: '2026년 3분기 이용 보고서.pdf',
70
+ size: 482_133,
71
+ fileUrl: '#',
72
+ },
73
+ { id: 2, name: '서비스 이용약관.docx', size: 91_204, fileUrl: '#' },
74
+ { id: 3, name: '업로드 중인 파일.pptx', progress: 40 },
75
+ ]}
76
+ onFileDownload={() => {}}
77
+ onFileDelete={async () => {}}
78
+ />
79
+ ),
80
+ };