@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,107 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle } from '../../guidelines/_components/Lang';
4
+ import * as ShakeStories from './Shake.stories';
5
+
6
+ <Meta of={ShakeStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Shake
13
+
14
+ Shakes its content once each time `trigger` changes: the "no, not that"
15
+ gesture for a rejected answer, an invalid field or a refused action.
16
+
17
+ </En>
18
+
19
+ <Ko>
20
+
21
+ # Shake
22
+
23
+ `trigger`가 바뀔 때마다 내용을 한 번 좌우로 흔듭니다. 틀린 답, 잘못 입력한 칸, 거절된
24
+ 동작에 "그건 아니에요"라고 답하는 몸짓입니다.
25
+
26
+ </Ko>
27
+
28
+ <Canvas of={ShakeStories.Default} />
29
+
30
+ <En>
31
+
32
+ ## When to use
33
+
34
+ - A wrong answer in a quiz or a choice list, with the option row itself
35
+ shaking (`display="block"` and `w="100%"` keep a full-width row full width).
36
+ - A submit that was refused because a field is invalid, shaking that field.
37
+
38
+ ## When not to use
39
+
40
+ - The change is good news or plain emphasis → `Pulse`. A shake used as
41
+ emphasis reads as an error the reader then goes looking for.
42
+ - As the only error signal → never. Pair it with colour, an icon and words.
43
+ - On the first render → it never shakes then; show the error state instead.
44
+
45
+ ## Reduced motion and accessibility
46
+
47
+ - With `prefers-reduced-motion: reduce` the shake is removed entirely, so for
48
+ some readers nothing moves at all. The refusal must be readable without it:
49
+ describe the error in text (WCAG 3.3.1) and do not rely on colour alone
50
+ (WCAG 1.4.1). The **동작 줄이기에서 남는 것** story shows both columns.
51
+ - Replaying does not remount the children, so the keyboard focus of the person
52
+ who was just told no stays where it was.
53
+ - Shake adds one `div` (`display: inline-flex`) around `children`. Inside a
54
+ `<button>` pass `as="span"` (ACCESSIBILITY.md §5).
55
+
56
+ </En>
57
+
58
+ <Ko>
59
+
60
+ ## 언제 쓰나요
61
+
62
+ - 퀴즈나 선택지 목록에서 틀린 답을 골랐을 때 그 선택지 행을 흔듭니다. 가로로 꽉 찬
63
+ 행이라면 `display="block"`과 `w="100%"`를 넘겨 너비를 유지합니다.
64
+ - 입력란이 잘못되어 제출이 거절됐을 때 그 입력란을 흔듭니다.
65
+
66
+ ## 언제 쓰지 않나요
67
+
68
+ - 좋은 소식이거나 단순한 강조라면 `Pulse`를 씁니다. 강조하려고 흔들면 사용자는
69
+ 오류로 읽고 무엇이 잘못됐는지 찾아 나섭니다.
70
+ - 오류를 알리는 유일한 신호로는 쓰지 않습니다. 색, 아이콘, 문구와 함께 씁니다.
71
+ - 첫 렌더에서는 흔들리지 않습니다. 처음부터 오류 상태라면 그 상태를 그대로 보여 줍니다.
72
+
73
+ ## 동작 줄이기와 접근성
74
+
75
+ - `prefers-reduced-motion: reduce`에서는 흔들림을 아예 빼므로, 어떤 사용자에게는 아무것도
76
+ 움직이지 않습니다. 흔들림 없이도 거절이 읽혀야 합니다. 오류를 문구로 설명하고
77
+ (WCAG 3.3.1) 색에만 기대지 않습니다(WCAG 1.4.1). **동작 줄이기에서 남는 것**
78
+ 스토리에서 두 경우를 나란히 볼 수 있습니다.
79
+ - 다시 재생할 때 자식을 새로 마운트하지 않으므로, 방금 거절당한 사람의 키보드 초점이
80
+ 제자리에 남습니다.
81
+ - Shake는 `children` 바깥에 `div`(`display: inline-flex`)를 하나 더합니다. `<button>`
82
+ 안에서는 `as="span"`을 넘깁니다(ACCESSIBILITY.md 5절).
83
+
84
+ </Ko>
85
+
86
+ <Canvas of={ShakeStories.ReducedMotion} />
87
+
88
+ <En>
89
+
90
+ ## Props
91
+
92
+ Any changing value works as `trigger`: an attempt counter, a verdict, a
93
+ timestamp. Two rejections of the same answer are two shakes if the counter
94
+ moves.
95
+
96
+ </En>
97
+
98
+ <Ko>
99
+
100
+ ## 속성
101
+
102
+ `trigger`에는 바뀌는 값이면 무엇이든 넣을 수 있습니다. 시도 횟수, 판정 결과,
103
+ 타임스탬프 모두 됩니다. 같은 답을 두 번 틀려도 카운터가 올라가면 두 번 흔들립니다.
104
+
105
+ </Ko>
106
+
107
+ <ArgTypes of={ShakeStories} include={['trigger', 'distance']} />
@@ -9,6 +9,11 @@ import {
9
9
  SliderThumbs,
10
10
  SliderTrack,
11
11
  } from '@/components/Slider';
12
+ import { Flex } from '@chakra-ui/react';
13
+
14
+ import { T } from '../../guidelines/_components/Lang';
15
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
16
+ import { Text } from '../Typography';
12
17
 
13
18
  const meta = {
14
19
  title: 'Components/Slider',
@@ -277,3 +282,114 @@ export const Sizes: Story = {
277
282
  );
278
283
  },
279
284
  };
285
+
286
+ // ───────────────────────── Usage-page specimens ─────────────────────────
287
+ // Pulled into `Slider.usage.mdx` with <Canvas of={…} />. Hidden (`!dev`).
288
+
289
+ export const DoValueBeside: Story = {
290
+ tags: ['!dev'],
291
+ parameters: { layout: 'padded' },
292
+ name: 'Usage / Do: a name and the value beside it',
293
+ render: () => {
294
+ const [value, setValue] = useState([70]);
295
+ return (
296
+ <Flex align="center" gap={4} maxW="420px">
297
+ <Text id="usage-volume" fontWeight="semibold" minW="48px">
298
+ 음량
299
+ </Text>
300
+ <Slider
301
+ flex={1}
302
+ ariaLabel="음량"
303
+ value={value}
304
+ min={0}
305
+ max={100}
306
+ onValueChange={(d) => setValue(d.value)}
307
+ >
308
+ <SliderTrack>
309
+ <SliderFilledTrack />
310
+ </SliderTrack>
311
+ <SliderThumb />
312
+ </Slider>
313
+ <Text minW="40px" textAlign="end">
314
+ {value[0]}%
315
+ </Text>
316
+ </Flex>
317
+ );
318
+ },
319
+ };
320
+
321
+ export const DontExactNumber: Story = {
322
+ tags: ['!dev'],
323
+ parameters: { layout: 'padded' },
324
+ name: "Usage / Don't: a slider for an exact number",
325
+ render: () => {
326
+ const [value, setValue] = useState([1250]);
327
+ return (
328
+ <Flex align="center" gap={4} maxW="420px">
329
+ <Text fontWeight="semibold">월 한도</Text>
330
+ <Slider
331
+ flex={1}
332
+ ariaLabel="월 한도"
333
+ value={value}
334
+ min={0}
335
+ max={100000}
336
+ onValueChange={(d) => setValue(d.value)}
337
+ >
338
+ <SliderTrack>
339
+ <SliderFilledTrack />
340
+ </SliderTrack>
341
+ <SliderThumb />
342
+ </Slider>
343
+ </Flex>
344
+ );
345
+ },
346
+ };
347
+
348
+ /** Tokens the slider parts read, as written in their `.tsx` files. */
349
+ export const UsageTokens: Story = {
350
+ tags: ['!dev'],
351
+ parameters: { layout: 'padded' },
352
+ name: 'Usage / Tokens',
353
+ render: () => (
354
+ <TokenTable
355
+ rows={[
356
+ {
357
+ token: 'bg.track',
358
+ use: <T en="Empty rail (SliderTrack)" ko="빈 레일(SliderTrack)" />,
359
+ },
360
+ {
361
+ token: 'primary.main',
362
+ use: (
363
+ <T
364
+ en="Filled rail and thumb border"
365
+ ko="채운 레일과 손잡이 테두리"
366
+ />
367
+ ),
368
+ },
369
+ { token: 'bg.canvas', use: <T en="Thumb centre" ko="손잡이 가운데" /> },
370
+ {
371
+ token: 'bg.muted',
372
+ use: (
373
+ <T
374
+ en="Disabled thumb and filled rail"
375
+ ko="비활성 손잡이와 채운 레일"
376
+ />
377
+ ),
378
+ },
379
+ {
380
+ token: 'border.default',
381
+ use: <T en="Disabled thumb border" ko="비활성 손잡이 테두리" />,
382
+ },
383
+ {
384
+ token: 'focus.ring',
385
+ use: (
386
+ <T
387
+ en="Keyboard focus ring on the thumb"
388
+ ko="손잡이의 키보드 초점 링"
389
+ />
390
+ ),
391
+ },
392
+ ]}
393
+ />
394
+ ),
395
+ };
@@ -0,0 +1,179 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as SliderStories from './Slider.stories';
5
+
6
+ <Meta of={SliderStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Slider
13
+
14
+ A thumb the user drags along a rail to set a value, or two thumbs for a range,
15
+ when the position matters more than the exact number.
16
+
17
+ ## When to use
18
+
19
+ - Seeking in audio or video, setting a volume.
20
+ - A value the user tunes by feel and sees the effect of right away, with the
21
+ number shown beside it.
22
+
23
+ ## When not to use
24
+
25
+ - An exact number (a credit limit, a count) → `Input` with `type="number"`.
26
+ - A choice between a few named levels → `Radio` or `SegmentedControl`.
27
+ - Showing progress the user cannot change → `ProgressBar`.
28
+
29
+ ## Props
30
+
31
+ </En>
32
+
33
+ <Ko>
34
+
35
+ # Slider
36
+
37
+ 레일 위의 손잡이를 끌어 값을 정합니다. 손잡이 두 개로 범위도 정할 수 있습니다. 정확한
38
+ 숫자보다 위치가 중요할 때 씁니다.
39
+
40
+ ## 언제 쓰나요
41
+
42
+ - 오디오나 영상의 재생 위치 이동, 음량 조절.
43
+ - 감으로 맞추면서 결과를 바로 확인하는 값. 숫자는 옆에 함께 보여 줍니다.
44
+
45
+ ## 언제 쓰지 않나요
46
+
47
+ - 크레딧 한도나 개수처럼 정확한 숫자는 `type="number"`인 `Input`을 씁니다.
48
+ - 이름 붙은 몇 단계 중 하나를 고를 때는 `Radio`나 `SegmentedControl`을 씁니다.
49
+ - 사용자가 바꿀 수 없는 진행 상황은 `ProgressBar`를 씁니다.
50
+
51
+ ## 속성
52
+
53
+ </Ko>
54
+
55
+ <ArgTypes
56
+ of={SliderStories}
57
+ include={['value', 'defaultValue', 'onValueChange', 'ariaLabel']}
58
+ />
59
+
60
+ <En>
61
+
62
+ Values are arrays: `[50]` for one thumb, `[20, 80]` for a range. Compose
63
+ `SliderTrack` > `SliderFilledTrack` and one `SliderThumb` per value (with
64
+ `index`), or `SliderThumbs` to render one per value automatically. Children
65
+ are wrapped in `SliderControl` for you. `min`, `max`, `step`, `disabled` and
66
+ `onValueChangeEnd` come from Chakra's `Slider.Root`.
67
+
68
+ ## Do / Don't
69
+
70
+ </En>
71
+
72
+ <Ko>
73
+
74
+ 값은 배열입니다. 손잡이 하나는 `[50]`, 범위는 `[20, 80]`입니다. `SliderTrack` 안에
75
+ `SliderFilledTrack`을 두고, 값마다 `SliderThumb`를 하나씩(`index`와 함께) 두거나
76
+ `SliderThumbs`로 값 개수만큼 자동으로 그립니다. 자식은 `SliderControl`로 알아서
77
+ 감쌉니다. `min`, `max`, `step`, `disabled`, `onValueChangeEnd`는 Chakra
78
+ `Slider.Root`의 속성입니다.
79
+
80
+ ## 이렇게 하세요 / 이렇게 하지 마세요
81
+
82
+ </Ko>
83
+
84
+ <Canvas of={SliderStories.DoValueBeside} />
85
+ <Verdict
86
+ kind="do"
87
+ en="Show the name and the current value beside the slider, and pass the name as ariaLabel."
88
+ ko="슬라이더 옆에 이름과 현재 값을 보여 주고, 이름은 ariaLabel로도 넘깁니다."
89
+ />
90
+
91
+ <Canvas of={SliderStories.DontExactNumber} />
92
+ <Verdict
93
+ kind="dont"
94
+ en="Ask for an exact number with a slider. One pixel covers dozens of values, and the user cannot see what they chose."
95
+ ko="정확한 숫자를 슬라이더로 받지 마세요. 1픽셀에 수십 개의 값이 걸리고, 무엇을 골랐는지도 보이지 않습니다."
96
+ />
97
+
98
+ <En>
99
+
100
+ ## Content
101
+
102
+ - Show the value with its unit (70%, 1:24) next to the rail, and update it
103
+ while dragging.
104
+ - Label the ends when the meaning is not obvious (느리게 / 빠르게).
105
+
106
+ ## Accessibility
107
+
108
+ What Slider does for you:
109
+
110
+ - Each thumb is a `slider` with its value exposed. Arrow keys step, Page Up /
111
+ Page Down jump, Home / End go to the ends (Chakra / Zag) (WCAG 2.1.1).
112
+ - The thumb shows the keyboard focus ring (WCAG 2.4.7). The empty rail is the
113
+ filled `bg.track`, which stays visible on sunken surfaces (WCAG 1.4.11).
114
+ - With `ariaLabel` it renders a visually hidden label part, so the name is in
115
+ the server markup.
116
+
117
+ What you still have to do:
118
+
119
+ - **Pass `ariaLabel`, or compose a visible `Slider.Label`.** Without either
120
+ the thumb has no name: it points at a label part that does not exist
121
+ (`ACCESSIBILITY.md` §1; KWCAG 5.3.4.1 레이블 제공).
122
+ - Dragging is not the only way: keyboard works, but give an `Input` as well
123
+ when people need an exact value (WCAG 2.5.7).
124
+
125
+ ## Tokens
126
+
127
+ </En>
128
+
129
+ <Ko>
130
+
131
+ ## 문구
132
+
133
+ - 레일 옆에 단위와 함께 값을 보여 주고(70%, 1:24), 끄는 동안 바로 바꿉니다.
134
+ - 양 끝의 뜻이 분명하지 않다면 끝에 라벨을 붙입니다(느리게 / 빠르게).
135
+
136
+ ## 접근성
137
+
138
+ Slider가 알아서 하는 일
139
+
140
+ - 손잡이마다 값을 드러내는 `slider`입니다. 방향키로 한 단계씩, Page Up·Page Down으로
141
+ 크게, Home·End로 끝까지 옮깁니다(Chakra와 Zag가 제공, WCAG 2.1.1).
142
+ - 손잡이에 키보드 초점 링이 보입니다(WCAG 2.4.7). 빈 레일은 채워진 `bg.track`이라
143
+ 움푹한 면 위에서도 보입니다(WCAG 1.4.11).
144
+ - `ariaLabel`을 주면 시각적으로 숨긴 라벨 부품을 그리므로 이름이 서버 마크업 안에
145
+ 있습니다.
146
+
147
+ 직접 챙겨야 하는 일
148
+
149
+ - **`ariaLabel`을 넘기거나 보이는 `Slider.Label`을 조합합니다.** 둘 다 없으면 손잡이가
150
+ 있지도 않은 라벨 부품을 가리켜서 이름이 없습니다(`ACCESSIBILITY.md` 1절, KWCAG
151
+ 5.3.4.1 레이블 제공).
152
+ - 끄는 것이 유일한 방법이 되지 않게 합니다. 키보드로도 움직일 수 있지만, 정확한 값이
153
+ 필요한 사람을 위해 `Input`도 함께 둡니다(WCAG 2.5.7).
154
+
155
+ ## 토큰
156
+
157
+ </Ko>
158
+
159
+ <Canvas of={SliderStories.UsageTokens} sourceState="none" />
160
+
161
+ <En>
162
+
163
+ ## Related
164
+
165
+ - **Input**: exact numbers.
166
+ - **ProgressBar**: progress the user cannot change.
167
+ - **SegmentedControl**: a few named levels.
168
+
169
+ </En>
170
+
171
+ <Ko>
172
+
173
+ ## 관련 컴포넌트
174
+
175
+ - **Input**: 정확한 숫자.
176
+ - **ProgressBar**: 사용자가 바꿀 수 없는 진행 상황.
177
+ - **SegmentedControl**: 이름 붙은 몇 단계.
178
+
179
+ </Ko>
@@ -1,5 +1,10 @@
1
+ import { HStack } from '@chakra-ui/react';
1
2
  import type { Meta, StoryObj } from '@storybook/react';
2
3
 
4
+ import { T } from '../../guidelines/_components/Lang';
5
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
6
+ import { Button } from '../Button';
7
+ import { Subtext } from '../Typography';
3
8
  import { Spinner } from './Spinner';
4
9
 
5
10
  const meta = {
@@ -14,3 +19,62 @@ type Story = StoryObj<typeof meta>;
14
19
  export const Default: Story = {
15
20
  args: {},
16
21
  };
22
+
23
+ export const Sizes: Story = {
24
+ render: () => (
25
+ <HStack gap={4}>
26
+ <Spinner size="xs" />
27
+ <Spinner size="sm" />
28
+ <Spinner size="md" />
29
+ <Spinner size="lg" />
30
+ </HStack>
31
+ ),
32
+ };
33
+
34
+ // ───────────────────────── Usage-page specimens ─────────────────────────
35
+ // Pulled into `Spinner.usage.mdx` with <Canvas of={…} />. Hidden from the
36
+ // sidebar (`!dev`).
37
+
38
+ export const DoSpinnerWithStatus: Story = {
39
+ tags: ['!dev'],
40
+ parameters: { layout: 'padded' },
41
+ name: 'Usage / Do: spinner and words in a status',
42
+ render: () => (
43
+ <HStack gap={2} role="status">
44
+ <Spinner size="sm" />
45
+ <Subtext>파일을 불러오는 중</Subtext>
46
+ </HStack>
47
+ ),
48
+ };
49
+
50
+ export const DoButtonLoading: Story = {
51
+ tags: ['!dev'],
52
+ parameters: { layout: 'padded' },
53
+ name: 'Usage / Do: a busy button uses its own loading state',
54
+ render: () => (
55
+ <Button variant="primary" loading loadingText="저장 중">
56
+ 저장
57
+ </Button>
58
+ ),
59
+ };
60
+
61
+ /** Tokens the spinner reads, from `Spinner.tsx` and the theme. */
62
+ export const UsageTokens: Story = {
63
+ tags: ['!dev'],
64
+ parameters: { layout: 'padded' },
65
+ name: 'Usage / Tokens',
66
+ render: () => (
67
+ <TokenTable
68
+ rows={[
69
+ {
70
+ token: 'primary.main',
71
+ use: <T en="turning arc (default colour)" ko="도는 호(기본 색)" />,
72
+ },
73
+ {
74
+ token: 'bg.track',
75
+ use: <T en="track ring" ko="트랙 고리" />,
76
+ },
77
+ ]}
78
+ />
79
+ ),
80
+ };
@@ -0,0 +1,136 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as SpinnerStories from './Spinner.stories';
5
+
6
+ <Meta of={SpinnerStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Spinner
13
+
14
+ A small turning ring that says "still working" when the wait is short and its
15
+ length is unknown.
16
+
17
+ ## When to use
18
+
19
+ - Inline, next to the words that say what is loading: a list row, a menu, a
20
+ file being read.
21
+ - Inside a custom control that has no loading state of its own.
22
+
23
+ ## When not to use
24
+
25
+ - A busy button → the button's `loading` prop (Chakra draws the spinner and
26
+ disables the button).
27
+ - A whole region or page → `SectionLoader` or `PageLoader`, which also
28
+ announce themselves.
29
+ - The AI is working → `ThinkingDots` or the loaders' `thinking` variant.
30
+ - Work with a known length → `ProgressBar`.
31
+
32
+ ## How it works
33
+
34
+ - Chakra's `Spinner` with `color="primary.main"` and the `bg.track` ring.
35
+ `size` takes Chakra's `xs` to `xl`; `color` can be overridden with a token.
36
+ - It turns at a constant rate. Under `prefers-reduced-motion` it keeps turning
37
+ at about a third of the speed, because a frozen spinner reads as a hung
38
+ request.
39
+
40
+ ## Do
41
+
42
+ </En>
43
+
44
+ <Ko>
45
+
46
+ # Spinner
47
+
48
+ 대기가 짧고 얼마나 걸릴지 모를 때 "아직 처리 중"이라고 알려 주는 작은 회전 고리입니다.
49
+
50
+ ## 언제 쓰나요
51
+
52
+ - 무엇을 불러오는지 알려 주는 글자 옆에 작게 둘 때: 목록 행, 메뉴, 읽는 중인 파일.
53
+ - 로딩 상태를 따로 갖지 않은 직접 만든 컨트롤 안에 둘 때.
54
+
55
+ ## 언제 쓰지 않나요
56
+
57
+ - 작업 중인 버튼은 그 버튼의 `loading` 속성을 씁니다(Chakra가 스피너를 그리고 버튼을
58
+ 비활성으로 만듭니다).
59
+ - 영역이나 페이지 전체는 `SectionLoader`나 `PageLoader`를 씁니다. 이 둘은 스스로 상태를
60
+ 알립니다.
61
+ - AI가 일하는 동안에는 `ThinkingDots`나 로더의 `thinking` 변형을 씁니다.
62
+ - 길이를 아는 작업은 `ProgressBar`를 씁니다.
63
+
64
+ ## 동작 방식
65
+
66
+ - `color="primary.main"`과 `bg.track` 고리를 쓴 Chakra `Spinner`입니다. `size`는
67
+ Chakra의 `xs`부터 `xl`까지 받으며, `color`는 토큰으로 바꿀 수 있습니다.
68
+ - 일정한 속도로 돕니다. `prefers-reduced-motion`에서는 멈추지 않고 약 3분의 1 속도로
69
+ 돕니다. 멈춘 스피너는 요청이 멈춘 것처럼 보이기 때문입니다.
70
+
71
+ ## 이렇게 하세요
72
+
73
+ </Ko>
74
+
75
+ <Canvas of={SpinnerStories.DoSpinnerWithStatus} />
76
+ <Verdict
77
+ kind="do"
78
+ en='Put the spinner next to words that say what is loading, inside a role="status" element. The spinner itself is a plain span with no name.'
79
+ ko='스피너는 무엇을 불러오는지 알려 주는 글자 옆에 두고, 둘을 role="status" 요소로 감쌉니다. 스피너 자체는 이름 없는 span일 뿐입니다.'
80
+ />
81
+
82
+ <Canvas of={SpinnerStories.DoButtonLoading} />
83
+ <Verdict
84
+ kind="do"
85
+ en="For a busy button, use the button's loading state instead of placing a Spinner inside it."
86
+ ko="작업 중인 버튼에는 Spinner를 직접 넣지 말고 버튼의 loading 상태를 씁니다."
87
+ />
88
+
89
+ <En>
90
+
91
+ ## Accessibility
92
+
93
+ - **Spinner has no role and no accessible name.** On its own it says nothing
94
+ to a screen reader. Pair it with visible text and wrap both in
95
+ `role="status"` so the change is announced (WCAG 4.1.3, 1.1.1).
96
+ - The `bg.track` ring is there so the spinner stays visible on any background
97
+ (WCAG 1.4.11).
98
+
99
+ ## Tokens
100
+
101
+ </En>
102
+
103
+ <Ko>
104
+
105
+ ## 접근성
106
+
107
+ - **Spinner에는 역할도 접근 가능한 이름도 없습니다.** 혼자서는 화면 낭독기에 아무것도
108
+ 알리지 않습니다. 눈에 보이는 글자와 함께 두고 둘을 `role="status"`로 감싸서 변화가
109
+ 읽히게 합니다(WCAG 4.1.3, 1.1.1).
110
+ - `bg.track` 고리 덕분에 어떤 배경 위에서도 스피너가 보입니다(WCAG 1.4.11).
111
+
112
+ ## 토큰
113
+
114
+ </Ko>
115
+
116
+ <Canvas of={SpinnerStories.UsageTokens} sourceState="none" />
117
+
118
+ <En>
119
+
120
+ ## Related
121
+
122
+ - **Loaders**: `PageLoader`, `SectionLoader`, `ThinkingDots`.
123
+ - **ProgressBar**: work whose length is known.
124
+ - **Button**: `loading`.
125
+
126
+ </En>
127
+
128
+ <Ko>
129
+
130
+ ## 관련 컴포넌트
131
+
132
+ - **Loaders**: `PageLoader`, `SectionLoader`, `ThinkingDots`.
133
+ - **ProgressBar**: 길이를 아는 작업.
134
+ - **Button**: `loading`.
135
+
136
+ </Ko>