@mindlogic-ai/logician-ui 5.0.0-alpha.3 → 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 (240) hide show
  1. package/dist/components/Banner/Banner.types.d.ts +24 -1
  2. package/dist/components/Banner/Banner.types.d.ts.map +1 -1
  3. package/dist/components/Card/Card.types.d.ts +12 -0
  4. package/dist/components/Card/Card.types.d.ts.map +1 -1
  5. package/dist/components/ColorMode/ColorModeToggle.d.ts +7 -2
  6. package/dist/components/ColorMode/ColorModeToggle.d.ts.map +1 -1
  7. package/dist/components/ColorMode/ColorModeToggle.js +8 -3
  8. package/dist/components/ColorMode/ColorModeToggle.js.map +1 -1
  9. package/dist/components/ColorMode/ColorModeToggle.mjs +8 -3
  10. package/dist/components/ColorMode/ColorModeToggle.mjs.map +1 -1
  11. package/dist/components/Confetti/Confetti.types.d.ts +5 -1
  12. package/dist/components/Confetti/Confetti.types.d.ts.map +1 -1
  13. package/dist/components/Confetti/confettiColors.d.ts +5 -5
  14. package/dist/components/Confetti/confettiColors.js +5 -5
  15. package/dist/components/Confetti/confettiColors.mjs +5 -5
  16. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts +6 -0
  17. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts.map +1 -1
  18. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts +4 -1
  19. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts.map +1 -1
  20. package/dist/components/LineGraph/LineGraph.d.ts.map +1 -1
  21. package/dist/components/LineGraph/LineGraph.js +4 -5
  22. package/dist/components/LineGraph/LineGraph.js.map +1 -1
  23. package/dist/components/LineGraph/LineGraph.mjs +5 -6
  24. package/dist/components/LineGraph/LineGraph.mjs.map +1 -1
  25. package/dist/components/LineGraph/LineGraph.types.d.ts +12 -2
  26. package/dist/components/LineGraph/LineGraph.types.d.ts.map +1 -1
  27. package/dist/components/LineGraph/seriesColors.d.ts +12 -8
  28. package/dist/components/LineGraph/seriesColors.d.ts.map +1 -1
  29. package/dist/components/LineGraph/seriesColors.js +8 -7
  30. package/dist/components/LineGraph/seriesColors.js.map +1 -1
  31. package/dist/components/LineGraph/seriesColors.mjs +8 -7
  32. package/dist/components/LineGraph/seriesColors.mjs.map +1 -1
  33. package/dist/components/Masonry/Masonry.types.d.ts +8 -3
  34. package/dist/components/Masonry/Masonry.types.d.ts.map +1 -1
  35. package/dist/components/Menu/MenuItem.types.d.ts +8 -0
  36. package/dist/components/Menu/MenuItem.types.d.ts.map +1 -1
  37. package/dist/components/Modal/ModalCloseButton.d.ts +1 -1
  38. package/dist/components/Modal/ModalCloseButton.js +1 -1
  39. package/dist/components/Modal/ModalCloseButton.mjs +1 -1
  40. package/dist/components/Pagination/Pagination.d.ts +11 -10
  41. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  42. package/dist/components/Pagination/Pagination.js +11 -10
  43. package/dist/components/Pagination/Pagination.js.map +1 -1
  44. package/dist/components/Pagination/Pagination.mjs +11 -10
  45. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  46. package/dist/components/ProgressBar/ProgressBar.types.d.ts +9 -0
  47. package/dist/components/ProgressBar/ProgressBar.types.d.ts.map +1 -1
  48. package/dist/components/RadialProgress/RadialProgress.types.d.ts +21 -1
  49. package/dist/components/RadialProgress/RadialProgress.types.d.ts.map +1 -1
  50. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts +8 -0
  51. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts.map +1 -1
  52. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  53. package/dist/components/SegmentedControl/SegmentedControl.js +6 -7
  54. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  55. package/dist/components/SegmentedControl/SegmentedControl.mjs +6 -7
  56. package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
  57. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts +2 -0
  58. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts.map +1 -1
  59. package/dist/components/Toast/Toast.styles.d.ts +6 -2
  60. package/dist/components/Toast/Toast.styles.d.ts.map +1 -1
  61. package/dist/components/Toast/Toast.styles.js +18 -10
  62. package/dist/components/Toast/Toast.styles.js.map +1 -1
  63. package/dist/components/Toast/Toast.styles.mjs +18 -10
  64. package/dist/components/Toast/Toast.styles.mjs.map +1 -1
  65. package/dist/theme/colors.d.ts +2 -2
  66. package/dist/theme/colors.d.ts.map +1 -1
  67. package/dist/theme/colors.js +22 -2
  68. package/dist/theme/colors.js.map +1 -1
  69. package/dist/theme/colors.mjs +23 -3
  70. package/dist/theme/colors.mjs.map +1 -1
  71. package/dist/theme/palette.generated.d.ts +98 -0
  72. package/dist/theme/palette.generated.d.ts.map +1 -1
  73. package/dist/theme/palette.generated.js +99 -0
  74. package/dist/theme/palette.generated.js.map +1 -1
  75. package/dist/theme/palette.generated.mjs +99 -1
  76. package/dist/theme/palette.generated.mjs.map +1 -1
  77. package/dist/theme/paletteSwatches.d.ts +20 -0
  78. package/dist/theme/paletteSwatches.d.ts.map +1 -1
  79. package/package.json +1 -1
  80. package/src/components/Accordion/Accordion.stories.tsx +85 -0
  81. package/src/components/Accordion/Accordion.usage.mdx +200 -0
  82. package/src/components/Appear/Appear.usage.mdx +107 -0
  83. package/src/components/Avatar/Avatar.stories.tsx +71 -1
  84. package/src/components/Avatar/Avatar.usage.mdx +166 -0
  85. package/src/components/Banner/Banner.stories.tsx +152 -2
  86. package/src/components/Banner/Banner.types.ts +30 -1
  87. package/src/components/Banner/Banner.usage.mdx +233 -0
  88. package/src/components/BottomSheet/BottomSheet.stories.tsx +168 -1
  89. package/src/components/BottomSheet/BottomSheet.usage.mdx +216 -0
  90. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +59 -0
  91. package/src/components/Breadcrumb/Breadcrumb.usage.mdx +181 -0
  92. package/src/components/Button/Button.stories.tsx +263 -3
  93. package/src/components/Button/Button.usage.mdx +342 -0
  94. package/src/components/Card/Card.stories.tsx +106 -0
  95. package/src/components/Card/Card.types.ts +12 -0
  96. package/src/components/Card/Card.usage.mdx +216 -0
  97. package/src/components/Checkbox/Checkbox.stories.tsx +140 -13
  98. package/src/components/Checkbox/Checkbox.usage.mdx +214 -0
  99. package/src/components/Chip/Chip.usage.mdx +78 -0
  100. package/src/components/Code/Code.stories.tsx +60 -0
  101. package/src/components/Code/Code.usage.mdx +187 -0
  102. package/src/components/CodeTabs/CodeTabs.stories.tsx +53 -0
  103. package/src/components/CodeTabs/CodeTabs.usage.mdx +176 -0
  104. package/src/components/Collapsible/Collapsible.stories.tsx +58 -0
  105. package/src/components/Collapsible/Collapsible.usage.mdx +173 -0
  106. package/src/components/ColorMode/ColorMode.stories.tsx +50 -0
  107. package/src/components/ColorMode/ColorMode.usage.mdx +135 -0
  108. package/src/components/ColorMode/ColorModeToggle.tsx +10 -3
  109. package/src/components/Confetti/Confetti.types.ts +5 -1
  110. package/src/components/Confetti/Confetti.usage.mdx +111 -0
  111. package/src/components/Confetti/confettiColors.ts +5 -5
  112. package/src/components/Container/Container.stories.tsx +32 -0
  113. package/src/components/Container/Container.usage.mdx +130 -0
  114. package/src/components/CopyableCode/CopyableCode.stories.tsx +62 -0
  115. package/src/components/CopyableCode/CopyableCode.usage.mdx +168 -0
  116. package/src/components/CountBadge/CountBadge.stories.tsx +69 -0
  117. package/src/components/CountBadge/CountBadge.usage.mdx +215 -0
  118. package/src/components/CountUp/CountUp.usage.mdx +107 -0
  119. package/src/components/DatePicker/DatePicker.usage.mdx +177 -0
  120. package/src/components/DatePicker/RangeDatePicker.stories.tsx +87 -3
  121. package/src/components/ErrorFallback/ErrorFallback.types.ts +6 -0
  122. package/src/components/ErrorFallback/ErrorFallback.usage.mdx +127 -0
  123. package/src/components/ExpandableText/ExpandableText.stories.tsx +55 -0
  124. package/src/components/ExpandableText/ExpandableText.usage.mdx +176 -0
  125. package/src/components/FileInput/FileInput.stories.tsx +38 -1
  126. package/src/components/FileInput/FileInput.usage.mdx +178 -0
  127. package/src/components/FileItem/FileItem.stories.tsx +71 -0
  128. package/src/components/FileItem/FileItem.usage.mdx +180 -0
  129. package/src/components/FileList/FileList.stories.tsx +25 -0
  130. package/src/components/FileList/FileList.usage.mdx +165 -0
  131. package/src/components/FlyTo/FlyTo.usage.mdx +99 -0
  132. package/src/components/Form/Form.stories.tsx +149 -0
  133. package/src/components/Form/Form.usage.mdx +201 -0
  134. package/src/components/Form/FormModalFooter/FormModalFooter.types.ts +4 -1
  135. package/src/components/FormControl/FormControl.stories.tsx +35 -0
  136. package/src/components/FormControl/FormControl.usage.mdx +128 -0
  137. package/src/components/FormIntegration/FormIntegration.usage.mdx +158 -0
  138. package/src/components/FormLabel/FormLabel.stories.tsx +71 -0
  139. package/src/components/FormLabel/FormLabel.usage.mdx +125 -0
  140. package/src/components/Icon/Icon.stories.tsx +61 -1
  141. package/src/components/Icon/Icon.usage.mdx +158 -0
  142. package/src/components/IconButton/IconButton.stories.tsx +209 -5
  143. package/src/components/IconButton/IconButton.usage.mdx +273 -0
  144. package/src/components/InfoSprinkle/InfoSprinkle.stories.tsx +77 -1
  145. package/src/components/InfoSprinkle/InfoSprinkle.usage.mdx +189 -0
  146. package/src/components/InlineCode/InlineCode.stories.tsx +75 -0
  147. package/src/components/InlineCode/InlineCode.usage.mdx +142 -0
  148. package/src/components/Input/Input.stories.tsx +180 -0
  149. package/src/components/Input/Input.usage.mdx +278 -0
  150. package/src/components/LineGraph/LineGraph.stories.tsx +112 -0
  151. package/src/components/LineGraph/LineGraph.tsx +4 -5
  152. package/src/components/LineGraph/LineGraph.types.ts +12 -2
  153. package/src/components/LineGraph/LineGraph.usage.mdx +186 -0
  154. package/src/components/LineGraph/seriesColors.test.ts +11 -10
  155. package/src/components/LineGraph/seriesColors.ts +18 -16
  156. package/src/components/Loaders/Loaders.stories.tsx +93 -0
  157. package/src/components/Loaders/Loaders.usage.mdx +180 -0
  158. package/src/components/LogicianProvider/LogicianProvider.usage.mdx +98 -0
  159. package/src/components/Markdown/Markdown.stories.tsx +53 -0
  160. package/src/components/Markdown/Markdown.usage.mdx +182 -0
  161. package/src/components/Masonry/Masonry.stories.tsx +63 -1
  162. package/src/components/Masonry/Masonry.types.ts +8 -3
  163. package/src/components/Masonry/Masonry.usage.mdx +142 -0
  164. package/src/components/MaxLengthIndicator/MaxLengthIndicator.stories.tsx +57 -0
  165. package/src/components/MaxLengthIndicator/MaxLengthIndicator.usage.mdx +125 -0
  166. package/src/components/Menu/Menu.stories.tsx +146 -2
  167. package/src/components/Menu/Menu.usage.mdx +230 -0
  168. package/src/components/Menu/MenuItem.types.ts +8 -0
  169. package/src/components/Modal/Modal.stories.tsx +177 -1
  170. package/src/components/Modal/Modal.usage.mdx +262 -0
  171. package/src/components/Modal/ModalCloseButton.tsx +1 -1
  172. package/src/components/MonthPicker/MonthPicker.stories.tsx +30 -0
  173. package/src/components/MonthPicker/MonthPicker.usage.mdx +191 -0
  174. package/src/components/Pagination/Pagination.stories.tsx +90 -1
  175. package/src/components/Pagination/Pagination.tsx +11 -10
  176. package/src/components/Pagination/Pagination.usage.mdx +186 -0
  177. package/src/components/PasswordInput/PasswordInput.stories.tsx +51 -0
  178. package/src/components/PasswordInput/PasswordInput.usage.mdx +193 -0
  179. package/src/components/PinInput/PinInput.stories.tsx +91 -0
  180. package/src/components/PinInput/PinInput.usage.mdx +194 -0
  181. package/src/components/Popover/Popover.stories.tsx +104 -1
  182. package/src/components/Popover/Popover.usage.mdx +197 -0
  183. package/src/components/ProgressBar/ProgressBar.stories.tsx +92 -1
  184. package/src/components/ProgressBar/ProgressBar.types.ts +9 -0
  185. package/src/components/ProgressBar/ProgressBar.usage.mdx +210 -0
  186. package/src/components/Pulse/Pulse.usage.mdx +102 -0
  187. package/src/components/RadialProgress/RadialProgress.stories.tsx +74 -1
  188. package/src/components/RadialProgress/RadialProgress.types.ts +21 -1
  189. package/src/components/RadialProgress/RadialProgress.usage.mdx +153 -0
  190. package/src/components/Radio/Radio.stories.tsx +119 -0
  191. package/src/components/Radio/Radio.usage.mdx +187 -0
  192. package/src/components/Reveal/Reveal.usage.mdx +105 -0
  193. package/src/components/ScaledContext/ScaledContext.usage.mdx +111 -0
  194. package/src/components/SeeMoreButton/SeeMoreButton.stories.tsx +146 -2
  195. package/src/components/SeeMoreButton/SeeMoreButton.types.ts +8 -0
  196. package/src/components/SeeMoreButton/SeeMoreButton.usage.mdx +213 -0
  197. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +69 -0
  198. package/src/components/SegmentedControl/SegmentedControl.tsx +6 -7
  199. package/src/components/SegmentedControl/SegmentedControl.usage.mdx +209 -0
  200. package/src/components/SegmentedProgressBar/SegmentedProgressBar.stories.tsx +54 -0
  201. package/src/components/SegmentedProgressBar/SegmentedProgressBar.types.ts +2 -0
  202. package/src/components/SegmentedProgressBar/SegmentedProgressBar.usage.mdx +145 -0
  203. package/src/components/Select/Select.stories.tsx +209 -1
  204. package/src/components/Select/Select.usage.mdx +278 -0
  205. package/src/components/Shake/Shake.usage.mdx +107 -0
  206. package/src/components/Slider/Slider.stories.tsx +116 -0
  207. package/src/components/Slider/Slider.usage.mdx +179 -0
  208. package/src/components/Spinner/Spinner.stories.tsx +64 -0
  209. package/src/components/Spinner/Spinner.usage.mdx +136 -0
  210. package/src/components/SwapTransition/SwapTransition.usage.mdx +102 -0
  211. package/src/components/Switch/Switch.stories.tsx +131 -6
  212. package/src/components/Switch/Switch.usage.mdx +199 -0
  213. package/src/components/Table/Table.stories.tsx +159 -1
  214. package/src/components/Table/Table.usage.mdx +235 -0
  215. package/src/components/Tabs/Tabs.stories.tsx +86 -0
  216. package/src/components/Tabs/Tabs.usage.mdx +219 -0
  217. package/src/components/Tag/Tag.stories.tsx +181 -4
  218. package/src/components/Tag/Tag.usage.mdx +257 -0
  219. package/src/components/Textarea/Textarea.stories.tsx +113 -0
  220. package/src/components/Textarea/Textarea.usage.mdx +186 -0
  221. package/src/components/Toast/Toast.stories.tsx +185 -3
  222. package/src/components/Toast/Toast.styles.ts +18 -10
  223. package/src/components/Toast/Toast.usage.mdx +265 -0
  224. package/src/components/Tooltip/Tooltip.stories.tsx +86 -1
  225. package/src/components/Tooltip/Tooltip.usage.mdx +211 -0
  226. package/src/components/Tree/Tree.stories.tsx +89 -0
  227. package/src/components/Tree/Tree.usage.mdx +207 -0
  228. package/src/components/Typography/Typography.stories.tsx +117 -0
  229. package/src/components/Typography/Typography.usage.mdx +251 -0
  230. package/src/components/Workflow/Workflow.usage.mdx +199 -0
  231. package/src/components/noRawScales.test.ts +5 -1
  232. package/src/foundations/BrandColour.mdx +65 -2
  233. package/src/theme/BazePalette.stories.tsx +111 -1
  234. package/src/theme/Palette.stories.tsx +2 -2
  235. package/src/theme/SemanticTokens.mdx +75 -16
  236. package/src/theme/claude.md +15 -9
  237. package/src/theme/colors.ts +33 -3
  238. package/src/theme/contrast.test.ts +32 -0
  239. package/src/theme/palette.generated.ts +99 -0
  240. package/src/theme/paletteSwatches.ts +35 -0
@@ -0,0 +1,201 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as FormStories from './Form.stories';
5
+
6
+ <Meta of={FormStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Form
13
+
14
+ The layout parts every form shares: fields, sections, a scroll area and the
15
+ footer with the actions.
16
+
17
+ | Part | What it does |
18
+ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
19
+ | `FieldRow` | One field: label (with `description` and an `endAdornment` slot), the control, `helperText` and `error`. Wraps `FormControl`, so ids and ARIA are wired for you. |
20
+ | `FieldLabel` / `FieldHelp` / `FieldError` | The pieces `FieldRow` is made of, for layouts it does not cover. `FieldError` renders nothing when empty. |
21
+ | `FormSection` | A titled group of fields with one gap (default `4`). `divider` adds a top rule; `collapsible` (with a `title`) turns it into an accordion, and `hasError` flags a collapsed section that hides errors. |
22
+ | `FormSectionHeader` | The section title row (`H5`, description, `titleAdornment`, `action`) on its own. |
23
+ | `FormScrollArea` | A full-height scrolling column, so a sticky footer pins to its bottom. |
24
+ | `FormFooter` | A sticky footer for panel forms: `start` on the left, `meta` (saved time, cost) and `action` on the right. |
25
+ | `FormModalFooter` | The modal footer: optional delete on the far left, Cancel, and a primary submit with its own loading and disabled state. |
26
+
27
+ ## When to use
28
+
29
+ - Any settings panel, create or edit modal, or sidebar form. Start with
30
+ `FieldRow` for every field and `FormSection` for every group.
31
+ - `FormFooter` in a panel that scrolls; `FormModalFooter` in a modal.
32
+
33
+ ## When not to use
34
+
35
+ - A single search box or filter bar → the control on its own, with an
36
+ `ariaLabel` or visible label.
37
+ - A confirm dialog with no fields → `Modal` with its own footer.
38
+
39
+ ## Do / Don't
40
+
41
+ </En>
42
+
43
+ <Ko>
44
+
45
+ # Form
46
+
47
+ 모든 폼이 함께 쓰는 배치 부품입니다. 필드, 섹션, 스크롤 영역, 동작 버튼이 있는 푸터가
48
+ 있습니다.
49
+
50
+ | 부품 | 하는 일 |
51
+ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
+ | `FieldRow` | 필드 하나. 라벨(`description`, `endAdornment` 자리 포함), 컨트롤, `helperText`, `error`. `FormControl`을 감싸므로 id와 ARIA 연결을 대신 해 줍니다. |
53
+ | `FieldLabel` / `FieldHelp` / `FieldError` | `FieldRow`를 이루는 조각. `FieldRow`로 안 되는 배치에 씁니다. `FieldError`는 비어 있으면 아무것도 그리지 않습니다. |
54
+ | `FormSection` | 제목이 있는 필드 묶음. 간격은 하나로 통일합니다(기본 `4`). `divider`는 위에 구분선을 긋고, `collapsible`(`title` 필요)은 접히는 묶음으로 바꾸며, `hasError`는 접힌 섹션에 숨은 오류를 표시합니다. |
55
+ | `FormSectionHeader` | 섹션 제목 줄(`H5`, 설명, `titleAdornment`, `action`)만 따로 쓸 때. |
56
+ | `FormScrollArea` | 높이를 꽉 채우고 스크롤되는 세로 영역. 붙박이 푸터가 아래에 고정됩니다. |
57
+ | `FormFooter` | 패널 폼의 붙박이 푸터. 왼쪽에 `start`, 오른쪽에 `meta`(저장 시각, 비용)와 `action`. |
58
+ | `FormModalFooter` | 모달 푸터. 맨 왼쪽의 삭제(선택), 취소, 로딩과 비활성 상태를 스스로 가진 기본 제출 버튼. |
59
+
60
+ ## 언제 쓰나요
61
+
62
+ - 설정 패널, 만들기·수정 모달, 사이드바 폼 어디서나 씁니다. 필드마다 `FieldRow`를,
63
+ 묶음마다 `FormSection`을 먼저 씁니다.
64
+ - 스크롤되는 패널에는 `FormFooter`를, 모달에는 `FormModalFooter`를 씁니다.
65
+
66
+ ## 언제 쓰지 않나요
67
+
68
+ - 검색창이나 필터 막대 하나는 컨트롤만 두고 `ariaLabel`이나 보이는 라벨을 붙입니다.
69
+ - 입력란 없이 확인만 받는 대화상자는 `Modal`의 푸터를 씁니다.
70
+
71
+ ## 이렇게 하세요 / 이렇게 하지 마세요
72
+
73
+ </Ko>
74
+
75
+ <Canvas of={FormStories.Basic} />
76
+ <Verdict
77
+ kind="do"
78
+ en="Build panels from FormSection and FieldRow, and pin the action in a FormFooter inside a FormScrollArea."
79
+ ko="패널은 FormSection과 FieldRow로 짜고, 동작 버튼은 FormScrollArea 안의 FormFooter에 고정합니다."
80
+ />
81
+
82
+ <Canvas of={FormStories.DoErrorsAtTheField} />
83
+ <Verdict
84
+ kind="do"
85
+ en="Show each error under its own field with FieldRow error. The field is marked invalid for assistive technology at the same time."
86
+ ko="오류는 FieldRow의 error로 해당 필드 바로 아래에 보여 줍니다. 보조기술에도 그 필드가 오류 상태라고 함께 전달됩니다."
87
+ />
88
+
89
+ <Canvas of={FormStories.DoModalFooter} />
90
+ <Verdict
91
+ kind="do"
92
+ en="Use FormModalFooter in modals: delete far left, Cancel, then the primary action last."
93
+ ko="모달에는 FormModalFooter를 씁니다. 삭제는 맨 왼쪽, 그다음 취소, 기본 동작은 맨 끝입니다."
94
+ />
95
+
96
+ <Canvas of={FormStories.DontHandRolledFooter} />
97
+ <Verdict
98
+ kind="dont"
99
+ en="Hand-roll the footer. The order changes from modal to modal, and the danger action ends up next to Save."
100
+ ko="푸터를 직접 만들지 마세요. 모달마다 순서가 달라지고, 위험한 동작이 저장 버튼 옆에 붙게 됩니다."
101
+ />
102
+
103
+ <En>
104
+
105
+ ## Content
106
+
107
+ - Section titles are nouns (기본 정보, 동작). Field rules are on the Input and
108
+ Select pages.
109
+ - Footer labels name the result (저장, 만들기, 그룹 삭제). The design system
110
+ owns no copy: `cancelLabel`, `submitLabel` and `deleteLabel` come from your
111
+ translations.
112
+ - `meta` is a fact, not an instruction: 오후 2:14에 저장됨, 10 크레딧.
113
+
114
+ ## Accessibility
115
+
116
+ What these parts do for you:
117
+
118
+ - `FieldRow` associates the label, sets `aria-invalid` when `error` is set,
119
+ and points `aria-describedby` at the helper and error text. `required`
120
+ shows the asterisk and marks the control required.
121
+ - `FormModalFooter` keeps the submit a `type="submit"` button inside a
122
+ `<form>`, so Enter submits; pass `onSubmit` only for a portalled or
123
+ form-less modal. `isSubmitting` disables every button so the modal cannot be
124
+ dismissed mid-request.
125
+ - A collapsed `FormSection` with `hasError` swaps its chevron for a danger
126
+ glyph, so hidden errors are not missed.
127
+
128
+ What you still have to do:
129
+
130
+ - **Name controls that `FieldRow` cannot reach.** `SelectField`,
131
+ `ComboboxField` and `Slider` take their name from their own label part: pass
132
+ the row's label as `ariaLabel` (`ACCESSIBILITY.md` §1).
133
+ - A flat `FormSection` and `FormSectionHeader` render the title as an `<h5>`. Check
134
+ that the level fits the page outline; where it does not, leave `title` out
135
+ and put your own heading of the right level above the fields (WCAG 1.3.1;
136
+ KWCAG 5.2.4.2 제목 제공).
137
+ - On submit, move focus to the first field with an error, or summarise the
138
+ errors at the top (WCAG 3.3.1).
139
+
140
+ ## Tokens
141
+
142
+ Form parts are layout. `FormFooter` uses `bg.surface` with a `border.subtle`
143
+ top rule, `FormSection` `divider` uses `border.subtle`, and `FieldError` uses
144
+ `danger.fg`. Section descriptions and `FieldLabel` descriptions are
145
+ `fg.muted`.
146
+
147
+ ## Related
148
+
149
+ - **FormControl** / **FormLabel**: the primitives under `FieldRow`.
150
+ - **FormIntegration**: wiring these to Formik or React Hook Form.
151
+ - **Modal**: `FormModalFooter` sits in `ModalFooter`.
152
+
153
+ </En>
154
+
155
+ <Ko>
156
+
157
+ ## 문구
158
+
159
+ - 섹션 제목은 명사로 씁니다(기본 정보, 동작). 필드 문구 규칙은 Input과 Select 페이지에
160
+ 있습니다.
161
+ - 푸터 버튼에는 결과를 씁니다(저장, 만들기, 그룹 삭제). 디자인 시스템은 문구를 가지지
162
+ 않으므로 `cancelLabel`, `submitLabel`, `deleteLabel`은 앱의 번역에서 넘깁니다.
163
+ - `meta`에는 지시가 아니라 사실을 씁니다. 예: 오후 2:14에 저장됨, 10 크레딧.
164
+
165
+ ## 접근성
166
+
167
+ 이 부품들이 알아서 하는 일
168
+
169
+ - `FieldRow`는 라벨을 연결하고, `error`가 있으면 `aria-invalid`를 붙이며, 도움말과 오류
170
+ 문구를 `aria-describedby`로 가리킵니다. `required`를 주면 별표가 보이고 컨트롤도 필수로
171
+ 표시됩니다.
172
+ - `FormModalFooter`는 `<form>` 안에서 제출 버튼을 `type="submit"`으로 두어 Enter로
173
+ 제출되게 합니다. `onSubmit`은 포털로 그려지거나 `<form>`이 없는 모달에서만 넘깁니다.
174
+ `isSubmitting`이면 모든 버튼이 비활성이 되어 요청 중에 모달이 닫히지 않습니다.
175
+ - `hasError`인 `FormSection`이 접혀 있으면 펼침 화살표 대신 위험 표시가 보여 숨은
176
+ 오류를 놓치지 않습니다.
177
+
178
+ 직접 챙겨야 하는 일
179
+
180
+ - **`FieldRow`가 닿지 않는 컨트롤에는 따로 이름을 줍니다.** `SelectField`,
181
+ `ComboboxField`, `Slider`는 자기 라벨 부품에서 이름을 가져오므로 행의 라벨을
182
+ `ariaLabel`로 넘깁니다(`ACCESSIBILITY.md` 1절).
183
+ - 펼친 `FormSection`과 `FormSectionHeader`는 제목을 `<h5>`로 그립니다. 그 수준이 화면 구조에
184
+ 맞는지 확인하고, 맞지 않으면 `title`을 비우고 필드 위에 알맞은 수준의 제목을 직접
185
+ 둡니다(WCAG 1.3.1, KWCAG 5.2.4.2 제목 제공).
186
+ - 제출할 때 오류가 있으면 첫 오류 필드로 초점을 옮기거나 위쪽에 오류를 모아 보여
187
+ 줍니다(WCAG 3.3.1).
188
+
189
+ ## 토큰
190
+
191
+ Form 부품은 배치용입니다. `FormFooter`는 `bg.surface`에 `border.subtle` 윗선을,
192
+ `FormSection`의 `divider`는 `border.subtle`을, `FieldError`는 `danger.fg`를 씁니다.
193
+ 섹션 설명과 `FieldLabel` 설명은 `fg.muted`입니다.
194
+
195
+ ## 관련 컴포넌트
196
+
197
+ - **FormControl** / **FormLabel**: `FieldRow` 아래의 기본 부품.
198
+ - **FormIntegration**: Formik이나 React Hook Form과 연결하기.
199
+ - **Modal**: `FormModalFooter`는 `ModalFooter` 안에 들어갑니다.
200
+
201
+ </Ko>
@@ -25,7 +25,10 @@ export interface FormModalFooterProps extends Omit<
25
25
  cancelLabel: ReactNode;
26
26
  /** Primary submit button label. */
27
27
  submitLabel: ReactNode;
28
- /** Palette for the primary button. Defaults to `primary`. */
28
+ /**
29
+ * @deprecated 5.0 Button has no colour palette. Only `'danger'` changes
30
+ * anything (a danger submit button); every other value renders `primary`.
31
+ */
29
32
  submitColorPalette?: ButtonColorPalette;
30
33
  /**
31
34
  * In-flight state — shows the submit spinner and disables every button so the
@@ -1,6 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { Stack } from '@chakra-ui/react';
3
3
 
4
+ import { FieldError, FieldRow } from '../Form';
4
5
  import { FormLabel } from '../FormLabel';
5
6
  import { Input } from '../Input';
6
7
  import { FormControl } from './FormControl';
@@ -76,3 +77,37 @@ export const ReadOnly: Story = {
76
77
  </FormControl>
77
78
  ),
78
79
  };
80
+
81
+ // ───────────────────────── Usage-page specimens ─────────────────────────
82
+ // Pulled into `FormControl.usage.mdx` with <Canvas of={…} />. Hidden (`!dev`).
83
+
84
+ export const DoFieldRowFirst: Story = {
85
+ tags: ['!dev'],
86
+ parameters: { layout: 'padded' },
87
+ name: 'Usage / Do: FieldRow for the common field',
88
+ render: () => (
89
+ <Stack w="320px">
90
+ <FieldRow
91
+ label="표시 이름"
92
+ helperText="다른 멤버에게 보이는 이름입니다."
93
+ error="이름을 입력해 주세요."
94
+ required
95
+ >
96
+ <Input />
97
+ </FieldRow>
98
+ </Stack>
99
+ ),
100
+ };
101
+
102
+ export const DoInvalidOnTheField: Story = {
103
+ tags: ['!dev'],
104
+ parameters: { layout: 'padded' },
105
+ name: 'Usage / Do: invalid on FormControl',
106
+ render: () => (
107
+ <FormControl invalid required w="320px">
108
+ <FormLabel>업무용 이메일</FormLabel>
109
+ <Input type="email" value="name@company" onChange={() => {}} />
110
+ <FieldError>이메일 주소 형식이 아닙니다.</FieldError>
111
+ </FormControl>
112
+ ),
113
+ };
@@ -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
+ };