@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,128 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as FormControlStories from './FormControl.stories';
5
+
6
+ <Meta of={FormControlStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # FormControl
13
+
14
+ Chakra's `Field.Root` under the design-system name: the wrapper that shares one
15
+ field's id and state with its label, control, helper and error.
16
+
17
+ ## When to use
18
+
19
+ - A field layout `FieldRow` does not cover, built from `FormLabel`, a control,
20
+ `FieldHelp` and `FieldError`.
21
+ - Wrapping a control so a parent can set `required`, `invalid`, `disabled` or
22
+ `readOnly` once.
23
+
24
+ ## When not to use
25
+
26
+ - A standard field → `FieldRow`, which is `FormControl` with the label, helper
27
+ and error already laid out.
28
+
29
+ ## Props
30
+
31
+ `required`, `invalid`, `disabled` and `readOnly` (plus every `Field.Root`
32
+ prop). The state reaches `Input`, `Textarea` and `PasswordInput` through
33
+ Chakra's field context, together with the id the label points at and the
34
+ `aria-describedby` for helper and error text. Composed controls (`SelectField`,
35
+ `ComboboxField`, `Slider`) take their name from their own label part, so give
36
+ them `label` or `ariaLabel` and pass `invalid` / `disabled` to them directly.
37
+
38
+ ## Do / Don't
39
+
40
+ </En>
41
+
42
+ <Ko>
43
+
44
+ # FormControl
45
+
46
+ Chakra `Field.Root`를 디자인 시스템 이름으로 내보낸 것입니다. 필드 하나의 id와 상태를
47
+ 라벨, 컨트롤, 도움말, 오류 문구에 나눠 주는 래퍼입니다.
48
+
49
+ ## 언제 쓰나요
50
+
51
+ - `FieldRow`로 안 되는 필드 배치를 `FormLabel`, 컨트롤, `FieldHelp`, `FieldError`로
52
+ 직접 짤 때.
53
+ - 상위에서 `required`, `invalid`, `disabled`, `readOnly`를 한 번에 정하려고 컨트롤을
54
+ 감쌀 때.
55
+
56
+ ## 언제 쓰지 않나요
57
+
58
+ - 일반적인 필드는 `FieldRow`를 씁니다. 라벨, 도움말, 오류 문구가 이미 배치된
59
+ `FormControl`입니다.
60
+
61
+ ## 속성
62
+
63
+ `required`, `invalid`, `disabled`, `readOnly`(그리고 `Field.Root`의 모든 속성)를
64
+ 받습니다. 이 상태는 Chakra의 필드 컨텍스트를 타고 `Input`, `Textarea`,
65
+ `PasswordInput`에 전달되며, 라벨이 가리키는 id와 도움말·오류 문구용
66
+ `aria-describedby`도 함께 전달됩니다. 부품을 조합한 컨트롤(`SelectField`,
67
+ `ComboboxField`, `Slider`)은 자기 라벨 부품에서 이름을 가져오므로 `label`이나
68
+ `ariaLabel`을 주고, `invalid`·`disabled`도 컨트롤에 직접 넘깁니다.
69
+
70
+ ## 이렇게 하세요 / 이렇게 하지 마세요
71
+
72
+ </Ko>
73
+
74
+ <Canvas of={FormControlStories.DoFieldRowFirst} />
75
+ <Verdict
76
+ kind="do"
77
+ en="Reach for FieldRow first. It is FormControl with the label, help and error placed for you."
78
+ ko="먼저 FieldRow를 씁니다. 라벨, 도움말, 오류 문구를 알아서 배치한 FormControl입니다."
79
+ />
80
+
81
+ <Canvas of={FormControlStories.DoInvalidOnTheField} />
82
+ <Verdict
83
+ kind="do"
84
+ en="When you compose by hand, set invalid on FormControl, not on the Input, and add a FieldError with the reason."
85
+ ko="직접 조합할 때는 invalid를 Input이 아니라 FormControl에 주고, 이유를 적은 FieldError를 함께 둡니다."
86
+ />
87
+
88
+ <En>
89
+
90
+ ## Accessibility
91
+
92
+ - `invalid` on `FormControl` sets `aria-invalid` on the input; `invalid` on
93
+ `Input` only paints the border (WCAG 3.3.1, 4.1.2).
94
+ - `required` marks the input required and shows the asterisk in `FormLabel`.
95
+ Say "required" in words somewhere on the form too; an asterisk alone is a
96
+ symbol not everyone knows (WCAG 3.3.2).
97
+
98
+ ## Tokens
99
+
100
+ None. FormControl draws nothing; the label colours are on the FormLabel page.
101
+
102
+ ## Related
103
+
104
+ - **FieldRow**: the laid-out field.
105
+ - **FormLabel**, **FieldHelp**, **FieldError**: the parts.
106
+
107
+ </En>
108
+
109
+ <Ko>
110
+
111
+ ## 접근성
112
+
113
+ - `FormControl`의 `invalid`는 입력란에 `aria-invalid`를 붙이고, `Input`의 `invalid`는
114
+ 테두리만 칠합니다(WCAG 3.3.1, 4.1.2).
115
+ - `required`는 입력란을 필수로 표시하고 `FormLabel`에 별표를 보여 줍니다. 별표는 모두가
116
+ 아는 기호가 아니므로 폼 어딘가에 "필수"라고 글자로도 적습니다(WCAG 3.3.2).
117
+
118
+ ## 토큰
119
+
120
+ 없습니다. FormControl은 아무것도 그리지 않습니다. 라벨 색은 FormLabel 페이지에
121
+ 있습니다.
122
+
123
+ ## 관련 컴포넌트
124
+
125
+ - **FieldRow**: 배치까지 된 필드.
126
+ - **FormLabel**, **FieldHelp**, **FieldError**: 부품.
127
+
128
+ </Ko>
@@ -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 FormIntegrationStories from './FormIntegration.stories';
5
+
6
+ <Meta title="Components/FormIntegration/Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Form integration
13
+
14
+ How the form controls connect to a form library. There is no
15
+ `FormIntegration` component: this page and the stories under
16
+ **Examples/Form Integration** show the wiring.
17
+
18
+ ## The rule
19
+
20
+ Put field state on the field, not on the control:
21
+
22
+ 1. One `FieldRow` (or `FormControl`) per field. Set `error` on it from the
23
+ library's error for that field; `invalid` follows, and `aria-invalid` and
24
+ `aria-describedby` reach the control.
25
+ 2. Pass the library's `value`, `onChange`, `onBlur` and `name` to the control.
26
+ `Input` re-emits change and blur events with `name` and the processed value
27
+ (trimmed, or digits only with `maskNumber`), so Formik's `handleChange` and
28
+ React Hook Form's `field.onChange` both work.
29
+ 3. Controls with their own value API take it directly: `SelectField` /
30
+ `ComboboxField` `onChange(value)`, `RadioGroup` `onValueChange`, `Checkbox`
31
+ / `Switch` `onCheckedChange`, `Slider` `onValueChange` (an array),
32
+ `FileInput` `onChange(files)`. With React Hook Form, wrap them in a
33
+ `Controller`.
34
+
35
+ ## When to use which library
36
+
37
+ - **React Hook Form** with a `Controller` per non-text control: what FactChat
38
+ uses for admin and studio forms.
39
+ - **Formik + Yup**: the first example below.
40
+ - **Plain state**: small forms, the second example.
41
+
42
+ ## Examples
43
+
44
+ </En>
45
+
46
+ <Ko>
47
+
48
+ # 폼 연동
49
+
50
+ 폼 컨트롤을 폼 라이브러리에 연결하는 방법입니다. `FormIntegration`이라는 컴포넌트는
51
+ 없습니다. 이 페이지와 **Examples/Form Integration** 아래 스토리가 연결 방법을 보여
52
+ 줍니다.
53
+
54
+ ## 원칙
55
+
56
+ 필드 상태는 컨트롤이 아니라 필드에 둡니다.
57
+
58
+ 1. 필드마다 `FieldRow`(또는 `FormControl`)를 하나씩 둡니다. 라이브러리가 그 필드에
59
+ 대해 준 오류를 `error`에 넣으면 `invalid`도 따라 바뀌고, `aria-invalid`와
60
+ `aria-describedby`가 컨트롤까지 전달됩니다.
61
+ 2. 라이브러리의 `value`, `onChange`, `onBlur`, `name`을 컨트롤에 넘깁니다. `Input`은
62
+ 변경·이탈 이벤트를 `name`과 가공한 값(공백을 정리한 값, `maskNumber`면 숫자만)으로
63
+ 다시 만들어 보내므로 Formik의 `handleChange`와 React Hook Form의 `field.onChange`가
64
+ 모두 동작합니다.
65
+ 3. 값을 다루는 방식이 따로 있는 컨트롤은 그 방식을 그대로 씁니다. `SelectField`·
66
+ `ComboboxField`는 `onChange(value)`, `RadioGroup`은 `onValueChange`, `Checkbox`·
67
+ `Switch`는 `onCheckedChange`, `Slider`는 `onValueChange`(배열), `FileInput`은
68
+ `onChange(files)`입니다. React Hook Form에서는 `Controller`로 감쌉니다.
69
+
70
+ ## 어떤 라이브러리를 쓰나요
71
+
72
+ - **React Hook Form**과 텍스트가 아닌 컨트롤마다 `Controller`: FactChat의 관리자·
73
+ 스튜디오 폼이 쓰는 방식입니다.
74
+ - **Formik + Yup**: 아래 첫 번째 예시.
75
+ - **일반 상태**: 작은 폼. 아래 두 번째 예시.
76
+
77
+ ## 예시
78
+
79
+ </Ko>
80
+
81
+ <Canvas of={FormIntegrationStories.FormikFormExample} />
82
+ <Verdict
83
+ kind="do"
84
+ en="Formik: the error for each field goes to that field's Field.Root, and the message renders under it."
85
+ ko="Formik: 필드마다 오류를 그 필드의 Field.Root에 넘기고, 문구는 필드 바로 아래에 그립니다."
86
+ />
87
+
88
+ <Canvas of={FormIntegrationStories.RegularFormExample} />
89
+ <Verdict
90
+ kind="do"
91
+ en="Plain state: validate on submit, keep errors in state per field, and clear a field's error when it changes."
92
+ ko="일반 상태: 제출할 때 검사하고, 오류는 필드별로 상태에 두며, 값이 바뀌면 그 필드의 오류를 지웁니다."
93
+ />
94
+
95
+ <En>
96
+
97
+ ## Pitfalls
98
+
99
+ - **`trimWhiteSpace` trims on every keystroke**, so a name with a space can
100
+ only be pasted. Trim at submit instead.
101
+ - **`maskNumber` needs `type="number"`** and then renders a text input; `min`
102
+ and `max` do nothing there. Validate the range in the schema.
103
+ - **`SelectField` inside `FieldRow` needs `ariaLabel`** with the row's label;
104
+ the row's label does not name it.
105
+ - **Don't set `invalid` on the control alone.** It paints the border without
106
+ telling assistive technology (WCAG 3.3.1).
107
+
108
+ ## Accessibility
109
+
110
+ - Every field has a visible label (WCAG 3.3.2; KWCAG 5.3.4.1 레이블 제공), and
111
+ every error is text under its field (WCAG 3.3.1).
112
+ - After a failed submit, move focus to the first invalid field or to an error
113
+ summary at the top.
114
+ - Do not disable the submit button until the form is valid without saying
115
+ why; the user cannot find out what is missing. Validate on submit and show
116
+ the errors.
117
+
118
+ ## Tokens
119
+
120
+ None of its own; see Input, Select and Form.
121
+
122
+ ## Related
123
+
124
+ - **Form** (`FieldRow`, `FormSection`, footers), **FormControl**, **Input**,
125
+ **Select**.
126
+
127
+ </En>
128
+
129
+ <Ko>
130
+
131
+ ## 자주 하는 실수
132
+
133
+ - **`trimWhiteSpace`는 입력할 때마다 공백을 지웁니다.** 그래서 공백이 든 이름은 붙여
134
+ 넣기로만 넣을 수 있습니다. 공백 정리는 제출할 때 합니다.
135
+ - **`maskNumber`는 `type="number"`가 있어야 동작하고**, 그때는 텍스트 입력란을 그립니다.
136
+ `min`과 `max`는 효과가 없으므로 범위는 스키마에서 검사합니다.
137
+ - **`FieldRow` 안의 `SelectField`에는 행의 라벨을 `ariaLabel`로 넘깁니다.** 행의 라벨은
138
+ 셀렉트의 이름이 되지 않습니다.
139
+ - **컨트롤에만 `invalid`를 주지 않습니다.** 테두리만 칠하고 보조기술에는 알리지
140
+ 않습니다(WCAG 3.3.1).
141
+
142
+ ## 접근성
143
+
144
+ - 모든 필드에 보이는 라벨을 두고(WCAG 3.3.2, KWCAG 5.3.4.1 레이블 제공), 모든 오류는 해당
145
+ 필드 아래에 문구로 보여 줍니다(WCAG 3.3.1).
146
+ - 제출에 실패하면 첫 오류 필드나 위쪽의 오류 요약으로 초점을 옮깁니다.
147
+ - 이유를 알리지 않은 채 폼이 유효해질 때까지 제출 버튼을 비활성으로 두지 않습니다.
148
+ 무엇이 빠졌는지 알 수 없습니다. 제출할 때 검사하고 오류를 보여 줍니다.
149
+
150
+ ## 토큰
151
+
152
+ 따로 정한 토큰이 없습니다. Input, Select, Form 페이지를 보세요.
153
+
154
+ ## 관련 컴포넌트
155
+
156
+ - **Form**(`FieldRow`, `FormSection`, 푸터), **FormControl**, **Input**, **Select**.
157
+
158
+ </Ko>
@@ -0,0 +1,71 @@
1
+ import { Stack } from '@chakra-ui/react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { FormControl } from '../FormControl';
5
+ import { Input } from '../Input';
6
+ import { FormLabel } from './FormLabel';
7
+
8
+ const meta = {
9
+ title: 'Components/FormLabel',
10
+ component: FormLabel,
11
+ parameters: { layout: 'centered' },
12
+ } satisfies Meta<typeof FormLabel>;
13
+
14
+ export default meta;
15
+
16
+ type Story = StoryObj<typeof meta>;
17
+
18
+ /** A label inside `FormControl`; it is associated with the control for you. */
19
+ export const Basic: Story = {
20
+ render: () => (
21
+ <FormControl w="300px">
22
+ <FormLabel>표시 이름</FormLabel>
23
+ <Input placeholder="홍길동" />
24
+ </FormControl>
25
+ ),
26
+ };
27
+
28
+ /** `required` on `FormControl` adds the asterisk; nothing to pass here. */
29
+ export const Required: Story = {
30
+ render: () => (
31
+ <FormControl required w="300px">
32
+ <FormLabel>업무용 이메일</FormLabel>
33
+ <Input type="email" />
34
+ </FormControl>
35
+ ),
36
+ };
37
+
38
+ // ───────────────────────── Usage-page specimens ─────────────────────────
39
+ // Pulled into `FormLabel.usage.mdx` with <Canvas of={…} />. Hidden (`!dev`).
40
+
41
+ export const DoNounLabels: Story = {
42
+ tags: ['!dev'],
43
+ parameters: { layout: 'padded' },
44
+ name: 'Usage / Do: short noun labels',
45
+ render: () => (
46
+ <Stack gap={4} maxW="320px">
47
+ <FormControl required>
48
+ <FormLabel>그룹 이름</FormLabel>
49
+ <Input />
50
+ </FormControl>
51
+ <FormControl>
52
+ <FormLabel>설명</FormLabel>
53
+ <Input />
54
+ </FormControl>
55
+ </Stack>
56
+ ),
57
+ };
58
+
59
+ export const DontSentenceLabels: Story = {
60
+ tags: ['!dev'],
61
+ parameters: { layout: 'padded' },
62
+ name: "Usage / Don't: instructions as labels",
63
+ render: () => (
64
+ <Stack gap={4} maxW="320px">
65
+ <FormControl required>
66
+ <FormLabel>그룹 이름을 입력해 주세요 (필수):</FormLabel>
67
+ <Input />
68
+ </FormControl>
69
+ </Stack>
70
+ ),
71
+ };
@@ -0,0 +1,125 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as FormLabelStories from './FormLabel.stories';
5
+
6
+ <Meta of={FormLabelStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # FormLabel
13
+
14
+ The visible label of a field. Inside `FormControl` it is associated with the
15
+ control and shows the required asterisk on its own.
16
+
17
+ ## When to use
18
+
19
+ - Inside `FormControl`, when you compose a field by hand. `FieldRow` (through
20
+ `FieldLabel`) already renders one.
21
+
22
+ ## When not to use
23
+
24
+ - A section title → `FormSection` `title`.
25
+ - A label for a checkbox, radio or switch option → `Checkbox.Label`,
26
+ `Radio.Text`, `Switch.Label`.
27
+
28
+ ## Do / Don't
29
+
30
+ </En>
31
+
32
+ <Ko>
33
+
34
+ # FormLabel
35
+
36
+ 필드의 보이는 라벨입니다. `FormControl` 안에서는 컨트롤과 연결되고 필수 별표도 알아서
37
+ 보여 줍니다.
38
+
39
+ ## 언제 쓰나요
40
+
41
+ - 필드를 직접 조합할 때 `FormControl` 안에서 씁니다. `FieldRow`는 `FieldLabel`을 통해
42
+ 이미 FormLabel을 그립니다.
43
+
44
+ ## 언제 쓰지 않나요
45
+
46
+ - 섹션 제목은 `FormSection`의 `title`을 씁니다.
47
+ - 체크박스, 라디오, 스위치 선택지의 라벨은 `Checkbox.Label`, `Radio.Text`,
48
+ `Switch.Label`을 씁니다.
49
+
50
+ ## 이렇게 하세요 / 이렇게 하지 마세요
51
+
52
+ </Ko>
53
+
54
+ <Canvas of={FormLabelStories.DoNounLabels} />
55
+ <Verdict
56
+ kind="do"
57
+ en="Write short nouns and let FormControl required add the asterisk."
58
+ ko="짧은 명사로 쓰고, 별표는 FormControl의 required가 붙이게 둡니다."
59
+ />
60
+
61
+ <Canvas of={FormLabelStories.DontSentenceLabels} />
62
+ <Verdict
63
+ kind="dont"
64
+ en="Write an instruction with a colon and type '(필수)' by hand. The asterisk already says it, so the label says it twice."
65
+ ko="쌍점을 붙인 지시문으로 쓰거나 '(필수)'를 직접 적지 마세요. 별표가 이미 알려 주므로 두 번 말하게 됩니다."
66
+ />
67
+
68
+ <En>
69
+
70
+ ## Content
71
+
72
+ - A noun phrase in sentence case, no colon, no "(required)".
73
+ - Keep it under about four words; anything longer goes in `FieldRow`
74
+ `description` or helper text.
75
+
76
+ ## Accessibility
77
+
78
+ - It renders Chakra's `Field.Label`, a `<label>` whose `for` is the field's
79
+ control id, so clicking it focuses the control and screen readers read it as
80
+ the control's name (WCAG 1.3.1, 4.1.2; KWCAG 5.3.4.1 레이블 제공).
81
+ - Outside `FormControl` there is no id to point at: pass `htmlFor` yourself.
82
+ - Composed controls (`SelectField`, `ComboboxField`, `Slider`) are not named
83
+ by it; give them `label` or `ariaLabel`.
84
+
85
+ ## Tokens
86
+
87
+ The label text is `fg.muted` from its wrapper (`FieldLabel` overrides it to
88
+ `fg.default`, semibold). The asterisk is `danger.fg`.
89
+
90
+ ## Related
91
+
92
+ - **FormControl**: the field it labels.
93
+ - **FieldRow** / **FieldLabel**: the laid-out label with description and an
94
+ end slot.
95
+
96
+ </En>
97
+
98
+ <Ko>
99
+
100
+ ## 문구
101
+
102
+ - 문장형 대소문자의 명사구로 쓰고, 쌍점이나 "(필수)"를 붙이지 않습니다.
103
+ - 네 단어 안팎으로 씁니다. 더 긴 설명은 `FieldRow`의 `description`이나 도움말에
104
+ 넣습니다.
105
+
106
+ ## 접근성
107
+
108
+ - Chakra `Field.Label`을 그립니다. `for`가 필드 컨트롤의 id인 `<label>`이라, 누르면
109
+ 컨트롤로 초점이 가고 화면 낭독기는 이를 컨트롤의 이름으로 읽습니다(WCAG 1.3.1, 4.1.2,
110
+ KWCAG 5.3.4.1 레이블 제공).
111
+ - `FormControl` 밖에서는 가리킬 id가 없으므로 `htmlFor`를 직접 넘깁니다.
112
+ - 부품을 조합한 컨트롤(`SelectField`, `ComboboxField`, `Slider`)에는 이 라벨이 이름으로
113
+ 닿지 않습니다. `label`이나 `ariaLabel`을 줍니다.
114
+
115
+ ## 토큰
116
+
117
+ 라벨 글자는 감싸는 요소의 `fg.muted`를 씁니다(`FieldLabel`은 `fg.default` 굵은
118
+ 글자로 바꿉니다). 별표는 `danger.fg`입니다.
119
+
120
+ ## 관련 컴포넌트
121
+
122
+ - **FormControl**: 라벨이 붙는 필드.
123
+ - **FieldRow** / **FieldLabel**: 설명과 끝 자리가 있는 배치된 라벨.
124
+
125
+ </Ko>
@@ -13,9 +13,18 @@ import { useMemo } from 'react';
13
13
  import { FaBuildingUser } from 'react-icons/fa6';
14
14
  import { MdDashboard } from 'react-icons/md';
15
15
 
16
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
17
+ import { Button } from '../Button';
18
+ import { IconButton } from '../IconButton';
16
19
  import { Icons } from './_constants/iconList';
17
20
  import { createIcon } from './_utils/createIcon';
18
- import { Analytics } from './index';
21
+ import {
22
+ Analytics,
23
+ CheckIcon,
24
+ CloseIcon,
25
+ DownloadIcon,
26
+ TrashIcon,
27
+ } from './index';
19
28
 
20
29
  const meta = {
21
30
  title: 'Components/Icon',
@@ -423,3 +432,54 @@ const MyCustomIcon = createIcon(
423
432
  </VStack>
424
433
  ),
425
434
  };
435
+
436
+ // ───────────────────────── Usage-page specimens ─────────────────────────
437
+ // Pulled into `Icon.usage.mdx` with <Canvas of={…} />. Hidden from the
438
+ // sidebar (`!dev`); `tags` is written out on each story because the indexer
439
+ // reads CSF statically.
440
+
441
+ export const DoIconWithLabel: Story = {
442
+ tags: ['!dev'],
443
+ parameters: { layout: 'padded' },
444
+ name: 'Usage / Do: decorative next to a label, named when alone',
445
+ render: () => (
446
+ <HStack gap={3}>
447
+ <Button variant="secondary">
448
+ <DownloadIcon boxSize="xs" aria-hidden />
449
+ 내려받기
450
+ </Button>
451
+ <IconButton aria-label="삭제" variant="ghost">
452
+ <TrashIcon boxSize="xs" aria-hidden />
453
+ </IconButton>
454
+ </HStack>
455
+ ),
456
+ };
457
+
458
+ export const DontIconAsStatus: Story = {
459
+ tags: ['!dev'],
460
+ parameters: { layout: 'padded' },
461
+ name: "Usage / Don't: a coloured icon as the only status",
462
+ render: () => (
463
+ <HStack gap={4}>
464
+ <Text>결제 1</Text>
465
+ <CheckIcon boxSize="xs" color="success.fg" />
466
+ <Text>결제 2</Text>
467
+ <CloseIcon boxSize="xs" color="danger.fg" />
468
+ </HStack>
469
+ ),
470
+ };
471
+
472
+ export const UsageTokens: Story = {
473
+ tags: ['!dev'],
474
+ parameters: { layout: 'padded' },
475
+ name: 'Usage / Tokens',
476
+ render: () => (
477
+ <TokenTable
478
+ rows={[
479
+ { token: 'fg.icon', use: 'icons on their own (stories default)' },
480
+ { token: 'fg.default', use: 'icon in running text' },
481
+ { token: 'fg.muted', use: 'secondary icon' },
482
+ ]}
483
+ />
484
+ ),
485
+ };