@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
@@ -1,8 +1,14 @@
1
- import { VStack } from '@chakra-ui/react';
1
+ import type { ReactNode } from 'react';
2
+ import { Flex, Stack, VStack } from '@chakra-ui/react';
2
3
  import type { Meta, StoryObj } from '@storybook/react';
3
4
 
4
- import { H5, Subtext } from '../Typography';
5
+ import { T } from '../../guidelines/_components/Lang';
6
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
7
+ import { Button } from '../Button';
8
+ import { Card } from '../Card';
9
+ import { H5, Subtext, Text } from '../Typography';
5
10
  import { Banner } from './Banner';
11
+ import { accentStyles, bannerStyles } from './Banner.styles';
6
12
 
7
13
  const meta = {
8
14
  title: 'Components/Banner',
@@ -10,6 +16,14 @@ const meta = {
10
16
  args: {
11
17
  children: 'This is a banner message',
12
18
  },
19
+ argTypes: {
20
+ variant: {
21
+ control: 'select',
22
+ options: ['info', 'success', 'warning', 'danger', 'neutral'],
23
+ description:
24
+ '`info` (default): a system fact to know before acting; nothing is wrong. `success`: finished, and the result stays relevant here. `warning`: still works, read this first. `danger`: failed or blocked; the reader must act. `neutral`: a brand notice with no status.',
25
+ },
26
+ },
13
27
  } satisfies Meta<typeof Banner>;
14
28
 
15
29
  export default meta;
@@ -79,3 +93,139 @@ export const AllVariants: Story = {
79
93
  </VStack>
80
94
  ),
81
95
  };
96
+
97
+ // ───────────────────────── Usage-page specimens ─────────────────────────
98
+ // Pulled into `Banner.usage.mdx` with <Canvas of={…} />. Hidden from the
99
+ // sidebar (`!dev`); `tags` is written on each story because the indexer reads
100
+ // CSF statically.
101
+
102
+ /** A confirm step like FactChat's credit distribution dialog. */
103
+ const ConfirmPanel = ({ children }: { children?: ReactNode }) => (
104
+ <Card p={4} maxW="420px">
105
+ <Stack gap={3}>
106
+ <Text fontWeight="bold">크레딧 1,000을 하위 그룹 3곳에 나눕니다</Text>
107
+ {children}
108
+ <Flex gap={2} justify="flex-end">
109
+ <Button variant="secondary">취소</Button>
110
+ <Button variant="primary">나누기</Button>
111
+ </Flex>
112
+ </Stack>
113
+ </Card>
114
+ );
115
+
116
+ export const DoWarningBeforeAction: Story = {
117
+ tags: ['!dev'],
118
+ parameters: { layout: 'padded' },
119
+ name: 'Usage / Do: warning next to the action it is about',
120
+ render: () => (
121
+ <ConfirmPanel>
122
+ <Banner variant="warning" size="sm" my={0}>
123
+ 나눈 크레딧은 되돌릴 수 없습니다.
124
+ </Banner>
125
+ </ConfirmPanel>
126
+ ),
127
+ };
128
+
129
+ export const DontBannerForTransientSuccess: Story = {
130
+ tags: ['!dev'],
131
+ parameters: { layout: 'padded' },
132
+ name: "Usage / Don't: a banner for a passing success",
133
+ render: () => (
134
+ <Card p={4} maxW="420px">
135
+ <Stack gap={3}>
136
+ <Banner variant="success" size="sm" my={0}>
137
+ 저장했습니다.
138
+ </Banner>
139
+ <Text fontWeight="bold">그룹 설정</Text>
140
+ <Subtext>이름, 설명, 관리자</Subtext>
141
+ </Stack>
142
+ </Card>
143
+ ),
144
+ };
145
+
146
+ export const DoInfoForLockedSetting: Story = {
147
+ tags: ['!dev'],
148
+ parameters: { layout: 'padded' },
149
+ name: 'Usage / Do: info for a locked setting',
150
+ render: () => (
151
+ <Card p={4} maxW="420px">
152
+ <Stack gap={2}>
153
+ <Text fontWeight="bold">인증 방식</Text>
154
+ <Banner variant="info" size="sm" my={0}>
155
+ 인증 방식은 연결을 만든 뒤에는 바꿀 수 없습니다.
156
+ </Banner>
157
+ </Stack>
158
+ </Card>
159
+ ),
160
+ };
161
+
162
+ export const DontStackBanners: Story = {
163
+ tags: ['!dev'],
164
+ parameters: { layout: 'padded' },
165
+ name: "Usage / Don't: a stack of banners",
166
+ render: () => (
167
+ <Stack gap={0} maxW="420px">
168
+ <Banner variant="info" size="sm">
169
+ 이 그룹에만 적용됩니다.
170
+ </Banner>
171
+ <Banner variant="warning" size="sm">
172
+ 크레딧이 7일 뒤 만료됩니다.
173
+ </Banner>
174
+ <Banner variant="warning" size="sm">
175
+ 나눈 크레딧은 되돌릴 수 없습니다.
176
+ </Banner>
177
+ <Banner variant="danger" size="sm">
178
+ 한 번에 50곳까지만 나눌 수 있습니다.
179
+ </Banner>
180
+ </Stack>
181
+ ),
182
+ };
183
+
184
+ export const DoDangerWithAlert: Story = {
185
+ tags: ['!dev'],
186
+ parameters: { layout: 'padded' },
187
+ name: 'Usage / Do: danger with role="alert" when it appears after submit',
188
+ render: () => (
189
+ <Stack gap={3} maxW="420px">
190
+ <Banner variant="danger" size="sm" my={0} role="alert">
191
+ 저장하지 못했습니다. 네트워크 연결을 확인한 뒤 다시 시도해 주세요.
192
+ </Banner>
193
+ <Flex justify="flex-end">
194
+ <Button variant="primary">다시 저장</Button>
195
+ </Flex>
196
+ </Stack>
197
+ ),
198
+ };
199
+
200
+ const VARIANTS = ['info', 'success', 'warning', 'danger', 'neutral'] as const;
201
+
202
+ /** Tokens each variant reads, from `Banner.styles.ts` and the theme. */
203
+ export const UsageTokens: Story = {
204
+ tags: ['!dev'],
205
+ parameters: { layout: 'padded' },
206
+ name: 'Usage / Tokens',
207
+ render: () => (
208
+ <TokenTable
209
+ rows={VARIANTS.flatMap((variant) => [
210
+ {
211
+ token: bannerStyles[variant].bg as string,
212
+ use: <T en={`${variant} · background`} ko={`${variant} · 배경`} />,
213
+ },
214
+ {
215
+ token: bannerStyles[variant].borderColor as string,
216
+ use: <T en={`${variant} · border`} ko={`${variant} · 테두리`} />,
217
+ },
218
+ {
219
+ token: (accentStyles[variant] as { bg: string }).bg,
220
+ use: <T en={`${variant} · accent bar`} ko={`${variant} · 왼쪽 막대`} />,
221
+ },
222
+ {
223
+ token: bannerStyles[variant].color as string,
224
+ use: (
225
+ <T en={`${variant} · text and icon`} ko={`${variant} · 글자와 아이콘`} />
226
+ ),
227
+ },
228
+ ])}
229
+ />
230
+ ),
231
+ };
@@ -2,8 +2,37 @@ import { BoxProps } from '@chakra-ui/react';
2
2
 
3
3
  export type BannerSize = 'sm' | 'md' | 'lg';
4
4
 
5
+ /**
6
+ * Banner variants (5.0).
7
+ *
8
+ * - `info` (default): a system fact the reader should know before acting
9
+ * (a setting that is locked, where a value comes from). Nothing is wrong.
10
+ * - `success`: something finished and the result stays relevant on this
11
+ * screen.
12
+ * - `warning`: it still works, but read this first (irreversible step,
13
+ * something expiring).
14
+ * - `danger`: it failed or is blocked, and the reader has to do something.
15
+ * - `neutral`: a brand notice with no status (`primary.main` accent bar).
16
+ */
17
+ export type BannerVariant =
18
+ | 'info'
19
+ | 'success'
20
+ | 'warning'
21
+ | 'danger'
22
+ | 'neutral';
23
+
5
24
  export interface BannerProps extends BoxProps {
6
- variant?: 'info' | 'success' | 'warning' | 'danger' | 'neutral';
25
+ /**
26
+ * Meaning of the message. Status variants only for a status every reader
27
+ * shares; `neutral` for a notice with none.
28
+ * @default 'info'
29
+ */
30
+ variant?: BannerVariant;
31
+ /** Hide the leading status icon. The text must still say the status. */
7
32
  hideIcon?: boolean;
33
+ /**
34
+ * `sm` = subtext, `md` = body text, `lg` = h5 text style.
35
+ * @default 'md'
36
+ */
8
37
  size?: BannerSize;
9
38
  }
@@ -0,0 +1,233 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as BannerStories from './Banner.stories';
5
+
6
+ <Meta of={BannerStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Banner
13
+
14
+ An inline message that stays on the page, next to the thing it is about, until
15
+ the condition behind it changes.
16
+
17
+ ## When to use
18
+
19
+ - To warn before an action the reader is about to take: an irreversible step,
20
+ something about to expire.
21
+ - To state a system fact that shapes what the reader can do here: a setting
22
+ that is locked, a limit, where a value comes from.
23
+ - To report a failure that blocks the form or section, with what to do next.
24
+
25
+ ## When not to use
26
+
27
+ - The message only confirms that something just happened ("Saved") → `Toast`.
28
+ - A short status attached to one item → `Badge`.
29
+ - An error about one field → the field's own error text (`FormControl`).
30
+ - The whole page failed to render → `ErrorFallback`.
31
+ - An explanation the reader asks for → `InfoSprinkle` or `Tooltip`.
32
+
33
+ ## Variants and what they mean
34
+
35
+ </En>
36
+
37
+ <Ko>
38
+
39
+ # Banner
40
+
41
+ 관련된 내용 바로 옆에 붙어서, 원인이 해결될 때까지 화면에 남아 있는 안내
42
+ 문구입니다.
43
+
44
+ ## 언제 쓰나요
45
+
46
+ - 되돌릴 수 없는 작업이나 곧 만료되는 항목처럼, 사용자가 하려는 일 앞에서 주의를
47
+ 줄 때.
48
+ - 잠긴 설정, 한도, 값의 출처처럼 이 화면에서 할 수 있는 일을 정하는 시스템 사실을
49
+ 알릴 때.
50
+ - 폼이나 영역 전체를 막는 실패를 알리고, 다음에 할 일을 함께 적을 때.
51
+
52
+ ## 언제 쓰지 않나요
53
+
54
+ - 방금 끝난 일을 확인만 해 준다면("저장했습니다") `Toast`를 씁니다.
55
+ - 항목 하나에 붙는 짧은 상태는 `Badge`를 씁니다.
56
+ - 입력란 하나의 오류는 그 입력란의 오류 문구(`FormControl`)로 알립니다.
57
+ - 페이지 전체를 그리지 못했다면 `ErrorFallback`을 씁니다.
58
+ - 사용자가 찾아보는 설명은 `InfoSprinkle`이나 `Tooltip`을 씁니다.
59
+
60
+ ## 변형과 뜻
61
+
62
+ </Ko>
63
+
64
+ <ArgTypes of={BannerStories} include={['variant', 'size', 'hideIcon']} />
65
+
66
+ <En>
67
+
68
+ | Variant | Means | Use for |
69
+ | --- | --- | --- |
70
+ | `info` (default) | A system fact to know before acting; nothing is wrong | Locked setting, scope, where a value comes from |
71
+ | `success` | Finished, and the result stays relevant on this screen | A connection that is now live |
72
+ | `warning` | Still works, but read this first | Irreversible step, expiring credit |
73
+ | `danger` | Failed or blocked; the reader has to act | Load failure, over a limit, submit error |
74
+ | `neutral` | A brand notice with no status | Announcements |
75
+
76
+ Use `size="sm"` inside cards, dialogs and forms; `md` (default) at the top of a
77
+ page section. Banner adds `my={2}`; pass `my={0}` when the parent already sets
78
+ the gap.
79
+
80
+ ## Do / Don't
81
+
82
+ </En>
83
+
84
+ <Ko>
85
+
86
+ | 변형 | 뜻 | 예 |
87
+ | --- | --- | --- |
88
+ | `info` (기본) | 작업 전에 알아야 할 시스템 사실이며, 문제가 있다는 뜻은 아님 | 잠긴 설정, 적용 범위, 값의 출처 |
89
+ | `success` | 끝났고, 그 결과가 이 화면에서 계속 의미가 있음 | 연결이 활성화됨 |
90
+ | `warning` | 동작은 하지만 먼저 읽어야 함 | 되돌릴 수 없는 작업, 만료 임박 크레딧 |
91
+ | `danger` | 실패했거나 막혔고, 사용자가 무언가 해야 함 | 불러오기 실패, 한도 초과, 저장 오류 |
92
+ | `neutral` | 상태가 없는 브랜드 공지 | 공지 |
93
+
94
+ 카드, 대화상자, 폼 안에서는 `size="sm"`을, 페이지 영역 맨 위에서는 기본값 `md`를
95
+ 씁니다. Banner에는 `my={2}`가 들어 있으니, 부모가 이미 간격을 정한다면
96
+ `my={0}`을 넘깁니다.
97
+
98
+ ## 이렇게 하세요 / 이렇게 하지 마세요
99
+
100
+ </Ko>
101
+
102
+ <Canvas of={BannerStories.DoWarningBeforeAction} />
103
+ <Verdict
104
+ kind="do"
105
+ en="Put a warning right above the action it is about, inside the same panel."
106
+ ko="주의 문구는 관련된 버튼 바로 위, 같은 패널 안에 둡니다."
107
+ />
108
+
109
+ <Canvas of={BannerStories.DontBannerForTransientSuccess} />
110
+ <Verdict
111
+ kind="dont"
112
+ en="Leave a success banner on the page after a save. It is out of date the moment the reader edits again. Confirm with a Toast."
113
+ ko="저장한 뒤 성공 배너를 화면에 남겨 두지 마세요. 다시 고치는 순간 맞지 않는 말이 됩니다. 확인은 Toast로 합니다."
114
+ />
115
+
116
+ <Canvas of={BannerStories.DoInfoForLockedSetting} />
117
+ <Verdict
118
+ kind="do"
119
+ en="Use info to explain why a setting cannot change. Nothing is wrong, so it is not a warning."
120
+ ko="설정을 바꿀 수 없는 이유는 info로 알립니다. 문제가 생긴 것이 아니므로 warning이 아닙니다."
121
+ />
122
+
123
+ <Canvas of={BannerStories.DontStackBanners} />
124
+ <Verdict
125
+ kind="dont"
126
+ en="Stack several banners. The reader stops reading after the first. Keep the one that blocks the next step and move the rest to where they apply."
127
+ ko="배너를 여러 개 쌓지 마세요. 사용자는 첫 번째 배너만 읽습니다. 다음 단계를 막는 배너 하나만 남기고, 나머지는 해당하는 자리로 옮기세요."
128
+ />
129
+
130
+ <Canvas of={BannerStories.DoDangerWithAlert} />
131
+ <Verdict
132
+ kind="do"
133
+ en='When a danger banner appears in response to a submit, give it role="alert" so screen readers announce it. Say what happened and what to do next.'
134
+ ko='저장 같은 동작의 결과로 나타나는 danger 배너에는 role="alert"를 붙여 화면 낭독기가 바로 읽게 합니다. 무슨 일이 있었는지와 다음에 할 일을 함께 적습니다.'
135
+ />
136
+
137
+ <En>
138
+
139
+ ## Content
140
+
141
+ - One or two sentences. Lead with what happened or what is true, then what to
142
+ do: "저장하지 못했습니다. 네트워크 연결을 확인한 뒤 다시 시도해 주세요."
143
+ - Full sentences end with a full stop. Sentence case in English.
144
+ - Numbers and dates the reader needs go in the text, not only in a link.
145
+ - Do not repeat the icon's meaning as a prefix ("경고:", "Error:"). The variant
146
+ already says it, and the words say the rest.
147
+
148
+ ## Accessibility
149
+
150
+ What Banner does for you:
151
+
152
+ - A string child renders as body text in the variant's `{status}.fg` colour,
153
+ which the contrast audit checks against `{status}.bg` in both modes
154
+ (WCAG 1.4.3).
155
+ - The icon is a decoration next to the words; the status is in the text.
156
+
157
+ What you still have to do:
158
+
159
+ - **Banner has no live-region role.** A banner that is on the page when it
160
+ loads needs none. One that appears after an action does: pass
161
+ `role="alert"` for an error, `role="status"` for anything else
162
+ (WCAG 4.1.3).
163
+ - **Words, not colour alone** (WCAG 1.4.1). If you set `hideIcon`, the text
164
+ still has to say it is a warning or an error when that matters.
165
+ - A link or button inside the banner needs a name that makes sense on its own
166
+ (WCAG 2.4.4).
167
+
168
+ ## Tokens
169
+
170
+ The table is generated from `Banner.styles.ts` and the theme.
171
+
172
+ </En>
173
+
174
+ <Ko>
175
+
176
+ ## 문구
177
+
178
+ - 한두 문장으로 씁니다. 무슨 일이 있었는지 또는 무엇이 사실인지 먼저 쓰고, 다음에 할
179
+ 일을 씁니다. 예: "저장하지 못했습니다. 네트워크 연결을 확인한 뒤 다시 시도해 주세요."
180
+ - 완전한 문장은 마침표로 끝냅니다. 영어는 문장형 대소문자를 씁니다.
181
+ - 사용자에게 필요한 숫자와 날짜는 링크 안에만 두지 말고 본문에 씁니다.
182
+ - 아이콘의 뜻을 "경고:", "오류:" 같은 머리말로 반복하지 않습니다. 변형이 이미 알려
183
+ 주고, 나머지는 문장이 전합니다.
184
+
185
+ ## 접근성
186
+
187
+ Banner가 알아서 하는 일
188
+
189
+ - 문자열을 넘기면 변형의 `{status}.fg` 색으로 본문 글자를 그립니다. 이 색은 대비
190
+ 감사에서 라이트·다크 모두 `{status}.bg` 위에서 검사합니다(WCAG 1.4.3).
191
+ - 아이콘은 문구 옆의 장식이고, 상태는 문구가 전합니다.
192
+
193
+ 직접 챙겨야 하는 일
194
+
195
+ - **Banner에는 라이브 영역 역할이 없습니다.** 페이지를 열 때부터 있는 배너는 역할이
196
+ 필요 없습니다. 어떤 동작 뒤에 나타나는 배너는 다릅니다. 오류라면 `role="alert"`,
197
+ 그 밖에는 `role="status"`를 넘깁니다(WCAG 4.1.3).
198
+ - **색만으로 알리지 않습니다**(WCAG 1.4.1). `hideIcon`을 쓴다면, 주의나 오류라는
199
+ 사실이 중요할 때 문구가 그것을 말해야 합니다.
200
+ - 배너 안의 링크나 버튼에는 그것만 읽어도 뜻이 통하는 이름을 붙입니다(WCAG 2.4.4).
201
+
202
+ ## 토큰
203
+
204
+ 아래 표는 `Banner.styles.ts`와 테마에서 자동으로 만듭니다.
205
+
206
+ </Ko>
207
+
208
+ <Canvas of={BannerStories.UsageTokens} sourceState="none" />
209
+
210
+ <En>
211
+
212
+ ## Related
213
+
214
+ - **Toast**: a passing confirmation or a result with one follow-up action.
215
+ - **Badge**: a one-to-three-word status on one item.
216
+ - **ErrorFallback**: the page or section failed to render.
217
+ - **Guidelines/Actions in feedback surfaces**: buttons and links inside a
218
+ banner.
219
+ - **Foundations/Brand & colour usage**: status colours mean status.
220
+
221
+ </En>
222
+
223
+ <Ko>
224
+
225
+ ## 관련 컴포넌트
226
+
227
+ - **Toast**: 잠깐 보이는 확인 메시지, 또는 후속 동작이 하나 있는 결과 안내.
228
+ - **Badge**: 항목 하나에 붙는 한두 단어의 상태.
229
+ - **ErrorFallback**: 페이지나 영역을 그리지 못했을 때.
230
+ - **Guidelines/Actions in feedback surfaces**: 배너 안의 버튼과 링크.
231
+ - **Foundations/Brand & colour usage**: 상태색은 상태를 뜻합니다.
232
+
233
+ </Ko>
@@ -7,10 +7,12 @@
7
7
  * emulation) to try the gestures; with a mouse the same drags work by
8
8
  * pointer.
9
9
  */
10
- import { useState } from 'react';
10
+ import { type ReactNode, useState } from 'react';
11
11
  import { Box, HStack, Stack } from '@chakra-ui/react';
12
12
  import type { Meta, StoryObj } from '@storybook/react';
13
13
 
14
+ import { T } from '../../guidelines/_components/Lang';
15
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
14
16
  import { Button } from '../Button';
15
17
  import {
16
18
  BoltIcon,
@@ -30,6 +32,8 @@ import {
30
32
  BottomSheetContent,
31
33
  BottomSheetFooter,
32
34
  BottomSheetHeader,
35
+ BottomSheetOverlay,
36
+ bottomSheetSlotRecipe,
33
37
  } from '.';
34
38
 
35
39
  const meta = {
@@ -202,3 +206,166 @@ export const LongScrollingList: Story = {
202
206
  );
203
207
  },
204
208
  };
209
+
210
+ // ───────────────────────── Usage-page specimens ─────────────────────────
211
+ // Pulled into `BottomSheet.usage.mdx` with <Canvas of={…} />. Hidden from the
212
+ // sidebar (`!dev`). Each is a real, open sheet held inside a phone-sized frame
213
+ // on the docs page: the portal is disabled, the frame's transform makes it the
214
+ // containing block for the fixed positioner and scrim, and `modal={false}`
215
+ // keeps the specimen from trapping focus or locking the page's scroll (the
216
+ // scrim is drawn with `BottomSheetOverlay` so it still looks modal).
217
+
218
+ const PhoneFrame = ({ children }: { children: ReactNode }) => (
219
+ <Box
220
+ position="relative"
221
+ w="360px"
222
+ maxW="100%"
223
+ h="420px"
224
+ mx="auto"
225
+ overflow="hidden"
226
+ borderRadius="l3"
227
+ borderWidth="1px"
228
+ borderColor="border.subtle"
229
+ bg="bg.canvas"
230
+ transform="translateZ(0)"
231
+ css={{
232
+ '& [data-scope=drawer][data-part=positioner], & [data-scope=drawer][data-part=backdrop]':
233
+ { width: '100%', height: '100%' },
234
+ }}
235
+ >
236
+ {children}
237
+ </Box>
238
+ );
239
+
240
+ const OpenSheet = ({ children }: { children: ReactNode }) => (
241
+ <PhoneFrame>
242
+ <BottomSheet
243
+ open
244
+ modal={false}
245
+ closeOnInteractOutside={false}
246
+ closeOnEscape={false}
247
+ portalProps={{ disabled: true }}
248
+ >
249
+ <BottomSheetOverlay />
250
+ <BottomSheetContent>{children}</BottomSheetContent>
251
+ </BottomSheet>
252
+ </PhoneFrame>
253
+ );
254
+
255
+ const SHORT_PALETTE = PALETTE.slice(0, 4);
256
+
257
+ export const DoPickFromList: Story = {
258
+ tags: ['!dev'],
259
+ parameters: { layout: 'padded' },
260
+ name: 'Usage / Do: a titled list to pick from',
261
+ render: () => (
262
+ <OpenSheet>
263
+ <BottomSheetHeader>노드 추가</BottomSheetHeader>
264
+ <BottomSheetCloseButton />
265
+ <BottomSheetBody>
266
+ {/* Inline: the docs page's `.sbdocs-content ul` marker rule
267
+ outranks a style prop. */}
268
+ <Stack as="ul" gap="1" style={{ listStyle: 'none' }} m="0" p="0">
269
+ {SHORT_PALETTE.map(({ icon: Icon, label, hint }) => (
270
+ <Box as="li" key={label}>
271
+ <HStack
272
+ as="button"
273
+ w="full"
274
+ gap="3"
275
+ px="3"
276
+ py="2.5"
277
+ borderRadius="l2"
278
+ textAlign="start"
279
+ >
280
+ <Icon boxSize="sm" aria-hidden />
281
+ <Stack gap="0">
282
+ <Text fontWeight="semibold">{label}</Text>
283
+ <Subtext color="fg.muted">{hint}</Subtext>
284
+ </Stack>
285
+ </HStack>
286
+ </Box>
287
+ ))}
288
+ </Stack>
289
+ </BottomSheetBody>
290
+ </OpenSheet>
291
+ ),
292
+ };
293
+
294
+ export const DontNoHeader: Story = {
295
+ tags: ['!dev'],
296
+ parameters: { layout: 'padded' },
297
+ name: "Usage / Don't: a sheet with no header",
298
+ render: () => (
299
+ <OpenSheet>
300
+ <BottomSheetBody>
301
+ <Stack gap="2" pt="2">
302
+ {SHORT_PALETTE.map(({ label }) => (
303
+ <Text key={label}>{label}</Text>
304
+ ))}
305
+ </Stack>
306
+ </BottomSheetBody>
307
+ </OpenSheet>
308
+ ),
309
+ };
310
+
311
+ export const DoFooterToApply: Story = {
312
+ tags: ['!dev'],
313
+ parameters: { layout: 'padded' },
314
+ name: 'Usage / Do: a footer when choices apply together',
315
+ render: () => (
316
+ <OpenSheet>
317
+ <BottomSheetHeader>필터</BottomSheetHeader>
318
+ <BottomSheetCloseButton />
319
+ <BottomSheetBody>
320
+ <Stack gap="2">
321
+ <Text>모델: 전체</Text>
322
+ <Text>기간: 최근 7일</Text>
323
+ <Text>상태: 완료</Text>
324
+ </Stack>
325
+ </BottomSheetBody>
326
+ <BottomSheetFooter>
327
+ <Button variant="secondary">초기화</Button>
328
+ <Button variant="primary">적용</Button>
329
+ </BottomSheetFooter>
330
+ </OpenSheet>
331
+ ),
332
+ };
333
+
334
+ const sheet = bottomSheetSlotRecipe.base ?? {};
335
+
336
+ /** Tokens each sheet part reads, from `bottomSheetSlotRecipe` in `BottomSheet.styles.ts`. */
337
+ export const UsageTokens: Story = {
338
+ tags: ['!dev'],
339
+ parameters: { layout: 'padded' },
340
+ name: 'Usage / Tokens',
341
+ render: () => (
342
+ <TokenTable
343
+ rows={[
344
+ {
345
+ token: String(sheet.content?.bg),
346
+ use: <T en="Sheet · background" ko="시트 · 배경" />,
347
+ },
348
+ {
349
+ token: String(sheet.content?.color),
350
+ use: <T en="Sheet · text" ko="시트 · 글자" />,
351
+ },
352
+ {
353
+ token: String(sheet.content?.borderColor),
354
+ use: <T en="Sheet · top edge" ko="시트 · 위 테두리" />,
355
+ },
356
+ {
357
+ token: String(sheet.grabberIndicator?.bg),
358
+ use: <T en="Grabber" ko="손잡이" />,
359
+ },
360
+ {
361
+ token: String(sheet.description?.color),
362
+ use: <T en="Description" ko="설명" />,
363
+ },
364
+ {
365
+ token: String(sheet.footer?.borderColor),
366
+ use: <T en="Footer · top rule" ko="푸터 · 위 선" />,
367
+ },
368
+ ]}
369
+ />
370
+ ),
371
+ };