@mindlogic-ai/logician-ui 5.0.0-alpha.2 → 5.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/Badge.js +5 -3
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Badge/Badge.mjs +5 -3
- package/dist/components/Badge/Badge.mjs.map +1 -1
- package/dist/components/Badge/Badge.types.d.ts +7 -5
- package/dist/components/Badge/Badge.types.d.ts.map +1 -1
- package/dist/components/Banner/Banner.types.d.ts +24 -1
- package/dist/components/Banner/Banner.types.d.ts.map +1 -1
- package/dist/components/Card/Card.types.d.ts +12 -0
- package/dist/components/Card/Card.types.d.ts.map +1 -1
- package/dist/components/ColorMode/ColorModeToggle.d.ts +7 -2
- package/dist/components/ColorMode/ColorModeToggle.d.ts.map +1 -1
- package/dist/components/ColorMode/ColorModeToggle.js +8 -3
- package/dist/components/ColorMode/ColorModeToggle.js.map +1 -1
- package/dist/components/ColorMode/ColorModeToggle.mjs +8 -3
- package/dist/components/ColorMode/ColorModeToggle.mjs.map +1 -1
- package/dist/components/Confetti/Confetti.types.d.ts +5 -1
- package/dist/components/Confetti/Confetti.types.d.ts.map +1 -1
- package/dist/components/Confetti/confettiColors.d.ts +5 -5
- package/dist/components/Confetti/confettiColors.js +5 -5
- package/dist/components/Confetti/confettiColors.mjs +5 -5
- package/dist/components/ErrorFallback/ErrorFallback.types.d.ts +6 -0
- package/dist/components/ErrorFallback/ErrorFallback.types.d.ts.map +1 -1
- package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts +4 -1
- package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts.map +1 -1
- package/dist/components/LineGraph/LineGraph.d.ts.map +1 -1
- package/dist/components/LineGraph/LineGraph.js +4 -5
- package/dist/components/LineGraph/LineGraph.js.map +1 -1
- package/dist/components/LineGraph/LineGraph.mjs +5 -6
- package/dist/components/LineGraph/LineGraph.mjs.map +1 -1
- package/dist/components/LineGraph/LineGraph.types.d.ts +12 -2
- package/dist/components/LineGraph/LineGraph.types.d.ts.map +1 -1
- package/dist/components/LineGraph/seriesColors.d.ts +12 -8
- package/dist/components/LineGraph/seriesColors.d.ts.map +1 -1
- package/dist/components/LineGraph/seriesColors.js +8 -7
- package/dist/components/LineGraph/seriesColors.js.map +1 -1
- package/dist/components/LineGraph/seriesColors.mjs +8 -7
- package/dist/components/LineGraph/seriesColors.mjs.map +1 -1
- package/dist/components/Masonry/Masonry.types.d.ts +8 -3
- package/dist/components/Masonry/Masonry.types.d.ts.map +1 -1
- package/dist/components/Menu/MenuItem.types.d.ts +8 -0
- package/dist/components/Menu/MenuItem.types.d.ts.map +1 -1
- package/dist/components/Modal/ModalCloseButton.d.ts +1 -1
- package/dist/components/Modal/ModalCloseButton.js +1 -1
- package/dist/components/Modal/ModalCloseButton.mjs +1 -1
- package/dist/components/Pagination/Pagination.d.ts +11 -10
- package/dist/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.js +11 -10
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/Pagination.mjs +11 -10
- package/dist/components/Pagination/Pagination.mjs.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.types.d.ts +9 -0
- package/dist/components/ProgressBar/ProgressBar.types.d.ts.map +1 -1
- package/dist/components/RadialProgress/RadialProgress.types.d.ts +21 -1
- package/dist/components/RadialProgress/RadialProgress.types.d.ts.map +1 -1
- package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts +8 -0
- package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.js +6 -7
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.mjs +6 -7
- package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
- package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts +2 -0
- package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts.map +1 -1
- package/dist/components/Toast/Toast.styles.d.ts +6 -2
- package/dist/components/Toast/Toast.styles.d.ts.map +1 -1
- package/dist/components/Toast/Toast.styles.js +18 -10
- package/dist/components/Toast/Toast.styles.js.map +1 -1
- package/dist/components/Toast/Toast.styles.mjs +18 -10
- package/dist/components/Toast/Toast.styles.mjs.map +1 -1
- package/dist/theme/colors.d.ts +2 -2
- package/dist/theme/colors.d.ts.map +1 -1
- package/dist/theme/colors.js +22 -2
- package/dist/theme/colors.js.map +1 -1
- package/dist/theme/colors.mjs +23 -3
- package/dist/theme/colors.mjs.map +1 -1
- package/dist/theme/palette.generated.d.ts +98 -0
- package/dist/theme/palette.generated.d.ts.map +1 -1
- package/dist/theme/palette.generated.js +99 -0
- package/dist/theme/palette.generated.js.map +1 -1
- package/dist/theme/palette.generated.mjs +99 -1
- package/dist/theme/palette.generated.mjs.map +1 -1
- package/dist/theme/paletteSwatches.d.ts +20 -0
- package/dist/theme/paletteSwatches.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.stories.tsx +85 -0
- package/src/components/Accordion/Accordion.usage.mdx +200 -0
- package/src/components/Appear/Appear.usage.mdx +107 -0
- package/src/components/Avatar/Avatar.stories.tsx +71 -1
- package/src/components/Avatar/Avatar.usage.mdx +166 -0
- package/src/components/Badge/Badge.stories.tsx +193 -3
- package/src/components/Badge/Badge.tsx +5 -3
- package/src/components/Badge/Badge.types.ts +7 -5
- package/src/components/Badge/Badge.usage.mdx +265 -0
- package/src/components/Banner/Banner.stories.tsx +152 -2
- package/src/components/Banner/Banner.types.ts +30 -1
- package/src/components/Banner/Banner.usage.mdx +233 -0
- package/src/components/BottomSheet/BottomSheet.stories.tsx +168 -1
- package/src/components/BottomSheet/BottomSheet.usage.mdx +216 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +59 -0
- package/src/components/Breadcrumb/Breadcrumb.usage.mdx +181 -0
- package/src/components/Button/Button.stories.tsx +263 -3
- package/src/components/Button/Button.usage.mdx +342 -0
- package/src/components/Card/Card.stories.tsx +106 -0
- package/src/components/Card/Card.types.ts +12 -0
- package/src/components/Card/Card.usage.mdx +216 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +140 -13
- package/src/components/Checkbox/Checkbox.usage.mdx +214 -0
- package/src/components/Chip/Chip.usage.mdx +78 -0
- package/src/components/Code/Code.stories.tsx +60 -0
- package/src/components/Code/Code.usage.mdx +187 -0
- package/src/components/CodeTabs/CodeTabs.stories.tsx +53 -0
- package/src/components/CodeTabs/CodeTabs.usage.mdx +176 -0
- package/src/components/Collapsible/Collapsible.stories.tsx +58 -0
- package/src/components/Collapsible/Collapsible.usage.mdx +173 -0
- package/src/components/ColorMode/ColorMode.stories.tsx +50 -0
- package/src/components/ColorMode/ColorMode.usage.mdx +135 -0
- package/src/components/ColorMode/ColorModeToggle.tsx +10 -3
- package/src/components/Confetti/Confetti.types.ts +5 -1
- package/src/components/Confetti/Confetti.usage.mdx +111 -0
- package/src/components/Confetti/confettiColors.ts +5 -5
- package/src/components/Container/Container.stories.tsx +32 -0
- package/src/components/Container/Container.usage.mdx +130 -0
- package/src/components/CopyableCode/CopyableCode.stories.tsx +62 -0
- package/src/components/CopyableCode/CopyableCode.usage.mdx +168 -0
- package/src/components/CountBadge/CountBadge.stories.tsx +69 -0
- package/src/components/CountBadge/CountBadge.usage.mdx +215 -0
- package/src/components/CountUp/CountUp.usage.mdx +107 -0
- package/src/components/DatePicker/DatePicker.usage.mdx +177 -0
- package/src/components/DatePicker/RangeDatePicker.stories.tsx +87 -3
- package/src/components/ErrorFallback/ErrorFallback.types.ts +6 -0
- package/src/components/ErrorFallback/ErrorFallback.usage.mdx +127 -0
- package/src/components/ExpandableText/ExpandableText.stories.tsx +55 -0
- package/src/components/ExpandableText/ExpandableText.usage.mdx +176 -0
- package/src/components/FileInput/FileInput.stories.tsx +38 -1
- package/src/components/FileInput/FileInput.usage.mdx +178 -0
- package/src/components/FileItem/FileItem.stories.tsx +71 -0
- package/src/components/FileItem/FileItem.usage.mdx +180 -0
- package/src/components/FileList/FileList.stories.tsx +25 -0
- package/src/components/FileList/FileList.usage.mdx +165 -0
- package/src/components/FlyTo/FlyTo.usage.mdx +99 -0
- package/src/components/Form/Form.stories.tsx +149 -0
- package/src/components/Form/Form.usage.mdx +201 -0
- package/src/components/Form/FormModalFooter/FormModalFooter.types.ts +4 -1
- package/src/components/FormControl/FormControl.stories.tsx +35 -0
- package/src/components/FormControl/FormControl.usage.mdx +128 -0
- package/src/components/FormIntegration/FormIntegration.usage.mdx +158 -0
- package/src/components/FormLabel/FormLabel.stories.tsx +71 -0
- package/src/components/FormLabel/FormLabel.usage.mdx +125 -0
- package/src/components/Icon/Icon.stories.tsx +61 -1
- package/src/components/Icon/Icon.usage.mdx +158 -0
- package/src/components/IconButton/IconButton.stories.tsx +209 -5
- package/src/components/IconButton/IconButton.usage.mdx +273 -0
- package/src/components/InfoSprinkle/InfoSprinkle.stories.tsx +77 -1
- package/src/components/InfoSprinkle/InfoSprinkle.usage.mdx +189 -0
- package/src/components/InlineCode/InlineCode.stories.tsx +75 -0
- package/src/components/InlineCode/InlineCode.usage.mdx +142 -0
- package/src/components/Input/Input.stories.tsx +180 -0
- package/src/components/Input/Input.usage.mdx +278 -0
- package/src/components/LineGraph/LineGraph.stories.tsx +112 -0
- package/src/components/LineGraph/LineGraph.tsx +4 -5
- package/src/components/LineGraph/LineGraph.types.ts +12 -2
- package/src/components/LineGraph/LineGraph.usage.mdx +186 -0
- package/src/components/LineGraph/seriesColors.test.ts +11 -10
- package/src/components/LineGraph/seriesColors.ts +18 -16
- package/src/components/Loaders/Loaders.stories.tsx +93 -0
- package/src/components/Loaders/Loaders.usage.mdx +180 -0
- package/src/components/LogicianProvider/LogicianProvider.usage.mdx +98 -0
- package/src/components/Markdown/Markdown.stories.tsx +53 -0
- package/src/components/Markdown/Markdown.usage.mdx +182 -0
- package/src/components/Masonry/Masonry.stories.tsx +63 -1
- package/src/components/Masonry/Masonry.types.ts +8 -3
- package/src/components/Masonry/Masonry.usage.mdx +142 -0
- package/src/components/MaxLengthIndicator/MaxLengthIndicator.stories.tsx +57 -0
- package/src/components/MaxLengthIndicator/MaxLengthIndicator.usage.mdx +125 -0
- package/src/components/Menu/Menu.stories.tsx +146 -2
- package/src/components/Menu/Menu.usage.mdx +230 -0
- package/src/components/Menu/MenuItem.types.ts +8 -0
- package/src/components/Modal/Modal.stories.tsx +177 -1
- package/src/components/Modal/Modal.usage.mdx +262 -0
- package/src/components/Modal/ModalCloseButton.tsx +1 -1
- package/src/components/MonthPicker/MonthPicker.stories.tsx +30 -0
- package/src/components/MonthPicker/MonthPicker.usage.mdx +191 -0
- package/src/components/Pagination/Pagination.stories.tsx +90 -1
- package/src/components/Pagination/Pagination.tsx +11 -10
- package/src/components/Pagination/Pagination.usage.mdx +186 -0
- package/src/components/PasswordInput/PasswordInput.stories.tsx +51 -0
- package/src/components/PasswordInput/PasswordInput.usage.mdx +193 -0
- package/src/components/PinInput/PinInput.stories.tsx +91 -0
- package/src/components/PinInput/PinInput.usage.mdx +194 -0
- package/src/components/Popover/Popover.stories.tsx +104 -1
- package/src/components/Popover/Popover.usage.mdx +197 -0
- package/src/components/ProgressBar/ProgressBar.stories.tsx +92 -1
- package/src/components/ProgressBar/ProgressBar.types.ts +9 -0
- package/src/components/ProgressBar/ProgressBar.usage.mdx +210 -0
- package/src/components/Pulse/Pulse.usage.mdx +102 -0
- package/src/components/RadialProgress/RadialProgress.stories.tsx +74 -1
- package/src/components/RadialProgress/RadialProgress.types.ts +21 -1
- package/src/components/RadialProgress/RadialProgress.usage.mdx +153 -0
- package/src/components/Radio/Radio.stories.tsx +119 -0
- package/src/components/Radio/Radio.usage.mdx +187 -0
- package/src/components/Reveal/Reveal.usage.mdx +105 -0
- package/src/components/ScaledContext/ScaledContext.usage.mdx +111 -0
- package/src/components/SeeMoreButton/SeeMoreButton.stories.tsx +146 -2
- package/src/components/SeeMoreButton/SeeMoreButton.types.ts +8 -0
- package/src/components/SeeMoreButton/SeeMoreButton.usage.mdx +213 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +69 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +6 -7
- package/src/components/SegmentedControl/SegmentedControl.usage.mdx +209 -0
- package/src/components/SegmentedProgressBar/SegmentedProgressBar.stories.tsx +54 -0
- package/src/components/SegmentedProgressBar/SegmentedProgressBar.types.ts +2 -0
- package/src/components/SegmentedProgressBar/SegmentedProgressBar.usage.mdx +145 -0
- package/src/components/Select/Select.stories.tsx +209 -1
- package/src/components/Select/Select.usage.mdx +278 -0
- package/src/components/Shake/Shake.usage.mdx +107 -0
- package/src/components/Slider/Slider.stories.tsx +116 -0
- package/src/components/Slider/Slider.usage.mdx +179 -0
- package/src/components/Spinner/Spinner.stories.tsx +64 -0
- package/src/components/Spinner/Spinner.usage.mdx +136 -0
- package/src/components/SwapTransition/SwapTransition.usage.mdx +102 -0
- package/src/components/Switch/Switch.stories.tsx +131 -6
- package/src/components/Switch/Switch.usage.mdx +199 -0
- package/src/components/Table/Table.stories.tsx +159 -1
- package/src/components/Table/Table.usage.mdx +235 -0
- package/src/components/Tabs/Tabs.stories.tsx +86 -0
- package/src/components/Tabs/Tabs.usage.mdx +219 -0
- package/src/components/Tag/Tag.stories.tsx +181 -4
- package/src/components/Tag/Tag.usage.mdx +257 -0
- package/src/components/Textarea/Textarea.stories.tsx +113 -0
- package/src/components/Textarea/Textarea.usage.mdx +186 -0
- package/src/components/Toast/Toast.stories.tsx +185 -3
- package/src/components/Toast/Toast.styles.ts +18 -10
- package/src/components/Toast/Toast.usage.mdx +265 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +86 -1
- package/src/components/Tooltip/Tooltip.usage.mdx +211 -0
- package/src/components/Tree/Tree.stories.tsx +89 -0
- package/src/components/Tree/Tree.usage.mdx +207 -0
- package/src/components/Typography/Typography.stories.tsx +117 -0
- package/src/components/Typography/Typography.usage.mdx +251 -0
- package/src/components/Workflow/Workflow.usage.mdx +199 -0
- package/src/components/noRawScales.test.ts +5 -1
- package/src/foundations/BrandColour.mdx +364 -0
- package/src/foundations/BrandColour.stories.tsx +334 -0
- package/src/guidelines/ComponentPageTemplate.mdx +84 -0
- package/src/guidelines/FeedbackActions.mdx +162 -23
- package/src/guidelines/_components/Lang.tsx +175 -0
- package/src/guidelines/_components/TokenTable.tsx +136 -0
- package/src/theme/BazePalette.stories.tsx +111 -1
- package/src/theme/Palette.stories.tsx +2 -2
- package/src/theme/SemanticTokens.mdx +75 -16
- package/src/theme/claude.md +15 -9
- package/src/theme/colors.ts +33 -3
- package/src/theme/contrast.test.ts +32 -0
- package/src/theme/palette.generated.ts +99 -0
- package/src/theme/paletteSwatches.ts +35 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Canvas, Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
|
|
4
|
+
import * as ContainerStories from './Container.stories';
|
|
5
|
+
|
|
6
|
+
<Meta of={ContainerStories} name="Usage" />
|
|
7
|
+
|
|
8
|
+
<LangToggle />
|
|
9
|
+
|
|
10
|
+
<En>
|
|
11
|
+
|
|
12
|
+
# Container
|
|
13
|
+
|
|
14
|
+
The centred page column. It is Chakra's `Container` plus a responsive
|
|
15
|
+
`minWidth`: the largest theme breakpoint that still leaves a 10% gutter on
|
|
16
|
+
each side of the **window**, recomputed on resize. `disableResponsive` turns
|
|
17
|
+
that off.
|
|
18
|
+
|
|
19
|
+
## When to use
|
|
20
|
+
|
|
21
|
+
- Once per page, around the main content, so pages share the same width.
|
|
22
|
+
|
|
23
|
+
## When not to use
|
|
24
|
+
|
|
25
|
+
- Inside a card, a modal, a drawer or a sidebar → `Box` or `Stack` with a
|
|
26
|
+
`maxW`. The width comes from the window, not the parent, so it overflows a
|
|
27
|
+
narrow box.
|
|
28
|
+
- To centre a small block → `Flex` / `Center`.
|
|
29
|
+
|
|
30
|
+
## Do / Don't
|
|
31
|
+
|
|
32
|
+
</En>
|
|
33
|
+
|
|
34
|
+
<Ko>
|
|
35
|
+
|
|
36
|
+
# Container
|
|
37
|
+
|
|
38
|
+
가운데 정렬된 페이지 열입니다. Chakra의 `Container`에 반응형 `minWidth`를 더했습니다.
|
|
39
|
+
**창** 양쪽에 10% 여백을 남기는 가장 큰 테마 중단점 값을 쓰고, 창 크기가 바뀌면 다시
|
|
40
|
+
계산합니다. `disableResponsive`로 끌 수 있습니다.
|
|
41
|
+
|
|
42
|
+
## 언제 쓰나요
|
|
43
|
+
|
|
44
|
+
- 페이지마다 한 번, 본문을 감싸서 페이지들의 너비를 맞출 때.
|
|
45
|
+
|
|
46
|
+
## 언제 쓰지 않나요
|
|
47
|
+
|
|
48
|
+
- 카드, 모달, 서랍, 사이드바 안에서는 `maxW`를 준 `Box`나 `Stack`을 씁니다. 너비가
|
|
49
|
+
부모가 아니라 창에서 정해지므로 좁은 상자 밖으로 넘칩니다.
|
|
50
|
+
- 작은 블록을 가운데 두려면 `Flex` / `Center`를 씁니다.
|
|
51
|
+
|
|
52
|
+
## 이렇게 하세요 / 이렇게 하지 마세요
|
|
53
|
+
|
|
54
|
+
</Ko>
|
|
55
|
+
|
|
56
|
+
<Canvas of={ContainerStories.DoPageLandmark} />
|
|
57
|
+
<Verdict
|
|
58
|
+
kind="do"
|
|
59
|
+
en="Use one Container for the page column and render it as the main landmark (as='main')."
|
|
60
|
+
ko="페이지 열에 Container 하나를 쓰고, 본문 랜드마크로 그립니다(as='main')."
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<Canvas of={ContainerStories.DontInsideACard} />
|
|
64
|
+
<Verdict
|
|
65
|
+
kind="dont"
|
|
66
|
+
en="Put a Container inside a narrow box. Its minimum width follows the window and spills out of the card."
|
|
67
|
+
ko="좁은 상자 안에 Container를 넣지 마세요. 최소 너비가 창을 따르므로 카드 밖으로 넘칩니다."
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<En>
|
|
71
|
+
|
|
72
|
+
## Accessibility
|
|
73
|
+
|
|
74
|
+
What Container does for you:
|
|
75
|
+
|
|
76
|
+
- `as` changes the element and its props, so the page column can be a
|
|
77
|
+
landmark: `as="main"`, `as="section"`, `as="nav"`.
|
|
78
|
+
|
|
79
|
+
What you still have to do:
|
|
80
|
+
|
|
81
|
+
- **Mark the main content** with `as="main"` once per page, so "skip to
|
|
82
|
+
content" and landmark navigation work (WCAG 1.3.1, 2.4.1).
|
|
83
|
+
- The `minWidth` is set after mount, from the window. Check pages at 320px
|
|
84
|
+
wide and at 400% zoom for sideways scrolling (WCAG 1.4.10).
|
|
85
|
+
|
|
86
|
+
## Tokens
|
|
87
|
+
|
|
88
|
+
Container sets no colour tokens.
|
|
89
|
+
|
|
90
|
+
</En>
|
|
91
|
+
|
|
92
|
+
<Ko>
|
|
93
|
+
|
|
94
|
+
## 접근성
|
|
95
|
+
|
|
96
|
+
Container가 알아서 하는 일
|
|
97
|
+
|
|
98
|
+
- `as`가 요소와 그 속성을 함께 바꾸므로 페이지 열을 랜드마크로 만들 수 있습니다:
|
|
99
|
+
`as="main"`, `as="section"`, `as="nav"`.
|
|
100
|
+
|
|
101
|
+
직접 챙겨야 하는 일
|
|
102
|
+
|
|
103
|
+
- **본문을 표시합니다.** 페이지마다 한 번 `as="main"`을 써야 "본문 바로가기"와
|
|
104
|
+
랜드마크 이동이 동작합니다(WCAG 1.3.1, 2.4.1).
|
|
105
|
+
- `minWidth`는 화면에 그려진 뒤 창 크기로 정해집니다. 폭 320px과 400% 확대에서 가로
|
|
106
|
+
스크롤이 생기지 않는지 확인합니다(WCAG 1.4.10).
|
|
107
|
+
|
|
108
|
+
## 토큰
|
|
109
|
+
|
|
110
|
+
Container는 색 토큰을 쓰지 않습니다.
|
|
111
|
+
|
|
112
|
+
</Ko>
|
|
113
|
+
|
|
114
|
+
<En>
|
|
115
|
+
|
|
116
|
+
## Related
|
|
117
|
+
|
|
118
|
+
- **Masonry**: a multi-column layout inside the page.
|
|
119
|
+
- **Card**: a bounded block inside the page.
|
|
120
|
+
|
|
121
|
+
</En>
|
|
122
|
+
|
|
123
|
+
<Ko>
|
|
124
|
+
|
|
125
|
+
## 관련 컴포넌트
|
|
126
|
+
|
|
127
|
+
- **Masonry**: 페이지 안의 여러 열 레이아웃.
|
|
128
|
+
- **Card**: 페이지 안의 경계 있는 블록.
|
|
129
|
+
|
|
130
|
+
</Ko>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
|
|
3
|
+
import { T } from '../../guidelines/_components/Lang';
|
|
4
|
+
import { TokenTable } from '../../guidelines/_components/TokenTable';
|
|
3
5
|
import { CopyableCode } from './CopyableCode';
|
|
4
6
|
import { CopyableCodeProps } from './CopyableCode.types';
|
|
5
7
|
|
|
@@ -20,3 +22,63 @@ export default meta;
|
|
|
20
22
|
type Story = StoryObj<typeof CopyableCode>;
|
|
21
23
|
|
|
22
24
|
export const Basic: Story = {};
|
|
25
|
+
|
|
26
|
+
// ───────────────────────── Usage-page specimens ─────────────────────────
|
|
27
|
+
// Pulled into `CopyableCode.usage.mdx` with <Canvas of={…} />. Hidden from
|
|
28
|
+
// the sidebar (`!dev`); `tags` is written out on each story because the
|
|
29
|
+
// indexer reads CSF statically.
|
|
30
|
+
|
|
31
|
+
/** CopyableCode does not touch the clipboard; the caller's `onCopy` does. */
|
|
32
|
+
const copy = (text: string) => () => {
|
|
33
|
+
void navigator.clipboard?.writeText(text);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const ENDPOINT = 'https://api.example.com/v1/chat/completions';
|
|
37
|
+
|
|
38
|
+
export const DoOneLineValue: Story = {
|
|
39
|
+
tags: ['!dev'],
|
|
40
|
+
parameters: { layout: 'padded' },
|
|
41
|
+
name: 'Usage / Do: one line the user pastes somewhere else',
|
|
42
|
+
args: { children: ENDPOINT, onCopy: copy(ENDPOINT) },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const SCRIPT = `import OpenAI from 'openai';
|
|
46
|
+
const client = new OpenAI({ baseURL: '${ENDPOINT}' });
|
|
47
|
+
const res = await client.chat.completions.create({ model: 'gpt-4o' });`;
|
|
48
|
+
|
|
49
|
+
export const DontMultiLine: Story = {
|
|
50
|
+
tags: ['!dev'],
|
|
51
|
+
parameters: { layout: 'padded' },
|
|
52
|
+
name: "Usage / Don't: a multi-line snippet",
|
|
53
|
+
args: { children: SCRIPT, onCopy: copy(SCRIPT) },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const UsageTokens: Story = {
|
|
57
|
+
tags: ['!dev'],
|
|
58
|
+
parameters: { layout: 'padded' },
|
|
59
|
+
name: 'Usage / Tokens',
|
|
60
|
+
render: () => (
|
|
61
|
+
<TokenTable
|
|
62
|
+
rows={[
|
|
63
|
+
{
|
|
64
|
+
token: 'bg.surface',
|
|
65
|
+
use: (
|
|
66
|
+
<T
|
|
67
|
+
en="Card surface and the fade under the button"
|
|
68
|
+
ko="카드 바탕과 버튼 아래 흐려지는 부분"
|
|
69
|
+
/>
|
|
70
|
+
),
|
|
71
|
+
},
|
|
72
|
+
{ token: 'border.subtle', use: <T en="Card border" ko="카드 테두리" /> },
|
|
73
|
+
{
|
|
74
|
+
token: 'primary.main',
|
|
75
|
+
use: <T en="Copy button (primary)" ko="복사 버튼(primary)" />,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
token: 'fg.onPrimary',
|
|
79
|
+
use: <T en="Copy button label" ko="복사 버튼 글자" />,
|
|
80
|
+
},
|
|
81
|
+
]}
|
|
82
|
+
/>
|
|
83
|
+
),
|
|
84
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Canvas, Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
|
|
4
|
+
import * as CopyableCodeStories from './CopyableCode.stories';
|
|
5
|
+
|
|
6
|
+
<Meta of={CopyableCodeStories} name="Usage" />
|
|
7
|
+
|
|
8
|
+
<LangToggle />
|
|
9
|
+
|
|
10
|
+
<En>
|
|
11
|
+
|
|
12
|
+
# CopyableCode
|
|
13
|
+
|
|
14
|
+
One line of code or a value in a card, with a 복사 button that confirms
|
|
15
|
+
itself (the icon becomes a check and the label becomes 복사 완료 for 1.6
|
|
16
|
+
seconds). FactChat uses it for model IDs and endpoints on the developer page.
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- A single value the user copies and pastes elsewhere: an endpoint, a model
|
|
21
|
+
ID, an embed URL.
|
|
22
|
+
|
|
23
|
+
## When not to use
|
|
24
|
+
|
|
25
|
+
- Several lines → `Code` with `onCopy`. CopyableCode renders on one line
|
|
26
|
+
(`white-space: nowrap`), so line breaks are lost.
|
|
27
|
+
- A value inside a sentence → `InlineCode`.
|
|
28
|
+
- A secret shown once (a new API key) → still fine, but say in the text that
|
|
29
|
+
it will not be shown again.
|
|
30
|
+
|
|
31
|
+
## Props
|
|
32
|
+
|
|
33
|
+
| Prop | Means |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `children` | The value shown. |
|
|
36
|
+
| `onCopy` | **Required, and it does the copying.** CopyableCode does not write to the clipboard; your handler must call `navigator.clipboard.writeText`. The button confirms when clicked either way. |
|
|
37
|
+
| `containerProps` | Props for the outer `Flex` (width, margins). |
|
|
38
|
+
|
|
39
|
+
## Do / Don't
|
|
40
|
+
|
|
41
|
+
</En>
|
|
42
|
+
|
|
43
|
+
<Ko>
|
|
44
|
+
|
|
45
|
+
# CopyableCode
|
|
46
|
+
|
|
47
|
+
카드 안에 코드 한 줄이나 값을 보여 주고 '복사' 버튼을 붙인 컴포넌트입니다. 버튼을
|
|
48
|
+
누르면 1.6초 동안 아이콘이 체크로, 글자가 '복사 완료'로 바뀌어 스스로 확인해 줍니다.
|
|
49
|
+
FactChat은 개발자 페이지의 모델 ID와 엔드포인트에 씁니다.
|
|
50
|
+
|
|
51
|
+
## 언제 쓰나요
|
|
52
|
+
|
|
53
|
+
- 사용자가 복사해서 다른 곳에 붙여 넣는 값 하나: 엔드포인트, 모델 ID, 임베드 URL.
|
|
54
|
+
|
|
55
|
+
## 언제 쓰지 않나요
|
|
56
|
+
|
|
57
|
+
- 여러 줄이라면 `onCopy`를 준 `Code`를 씁니다. CopyableCode는 한 줄로
|
|
58
|
+
그리므로(`white-space: nowrap`) 줄바꿈이 사라집니다.
|
|
59
|
+
- 문장 안의 값은 `InlineCode`를 씁니다.
|
|
60
|
+
- 한 번만 보여 주는 비밀 값(새 API 키)에도 쓸 수 있지만, 다시 볼 수 없다는 점을 본문에
|
|
61
|
+
적습니다.
|
|
62
|
+
|
|
63
|
+
## 속성
|
|
64
|
+
|
|
65
|
+
| 속성 | 뜻 |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `children` | 보여 줄 값. |
|
|
68
|
+
| `onCopy` | **필수이며, 복사는 이 함수가 합니다.** CopyableCode는 클립보드에 쓰지 않으므로 넘긴 함수에서 `navigator.clipboard.writeText`를 불러야 합니다. 버튼의 확인 표시는 어느 경우에나 나타납니다. |
|
|
69
|
+
| `containerProps` | 바깥 `Flex`에 넘길 속성(너비, 여백). |
|
|
70
|
+
|
|
71
|
+
## 이렇게 하세요 / 이렇게 하지 마세요
|
|
72
|
+
|
|
73
|
+
</Ko>
|
|
74
|
+
|
|
75
|
+
<Canvas of={CopyableCodeStories.DoOneLineValue} />
|
|
76
|
+
<Verdict
|
|
77
|
+
kind="do"
|
|
78
|
+
en="Use it for one value, and write it to the clipboard in onCopy."
|
|
79
|
+
ko="값 하나에 쓰고, onCopy에서 클립보드에 씁니다."
|
|
80
|
+
/>
|
|
81
|
+
|
|
82
|
+
<Canvas of={CopyableCodeStories.DontMultiLine} />
|
|
83
|
+
<Verdict
|
|
84
|
+
kind="dont"
|
|
85
|
+
en="Use it for a multi-line snippet. The lines run together and scroll sideways under the button. Use Code with onCopy."
|
|
86
|
+
ko="여러 줄 코드에 쓰지 마세요. 줄이 하나로 이어지고 버튼 아래로 가로 스크롤됩니다. onCopy를 준 Code를 씁니다."
|
|
87
|
+
/>
|
|
88
|
+
|
|
89
|
+
<En>
|
|
90
|
+
|
|
91
|
+
## Content
|
|
92
|
+
|
|
93
|
+
- Show the exact value, nothing around it: no quotes, no "URL:".
|
|
94
|
+
- Put the label in the text above (모델 ID, 엔드포인트).
|
|
95
|
+
|
|
96
|
+
## Accessibility
|
|
97
|
+
|
|
98
|
+
What CopyableCode does for you:
|
|
99
|
+
|
|
100
|
+
- The button is a real `Button` with a visible, translated label, so its name
|
|
101
|
+
matches what is shown (WCAG 2.5.3, 4.1.2).
|
|
102
|
+
- Only one label is exposed at a time (the other is `aria-hidden`), and the
|
|
103
|
+
button keeps its width when the label changes.
|
|
104
|
+
|
|
105
|
+
What you still have to do:
|
|
106
|
+
|
|
107
|
+
- **Copy for real.** If `onCopy` does nothing, the button still says 복사
|
|
108
|
+
완료 and tells the user something false.
|
|
109
|
+
- The confirmation is visual only; there is no live region. If the copy
|
|
110
|
+
result matters (a key shown once), also announce it, for example with a
|
|
111
|
+
`Toast` (WCAG 4.1.3).
|
|
112
|
+
- A long value scrolls sideways under a fade. Make sure the start of the
|
|
113
|
+
value is the part that identifies it.
|
|
114
|
+
|
|
115
|
+
## Tokens
|
|
116
|
+
|
|
117
|
+
</En>
|
|
118
|
+
|
|
119
|
+
<Ko>
|
|
120
|
+
|
|
121
|
+
## 문구
|
|
122
|
+
|
|
123
|
+
- 값만 정확히 보여 줍니다. 따옴표나 "URL:" 같은 말을 붙이지 않습니다.
|
|
124
|
+
- 라벨(모델 ID, 엔드포인트)은 위 본문에 씁니다.
|
|
125
|
+
|
|
126
|
+
## 접근성
|
|
127
|
+
|
|
128
|
+
CopyableCode가 알아서 하는 일
|
|
129
|
+
|
|
130
|
+
- 버튼은 번역된 글자가 보이는 실제 `Button`이라, 보이는 글자와 읽히는 이름이
|
|
131
|
+
같습니다(WCAG 2.5.3, 4.1.2).
|
|
132
|
+
- 한 번에 한 글자만 노출되고(다른 하나는 `aria-hidden`), 글자가 바뀌어도 버튼 너비가
|
|
133
|
+
그대로입니다.
|
|
134
|
+
|
|
135
|
+
직접 챙겨야 하는 일
|
|
136
|
+
|
|
137
|
+
- **실제로 복사합니다.** `onCopy`가 아무것도 하지 않아도 버튼은 '복사 완료'를 띄우므로
|
|
138
|
+
사용자에게 사실이 아닌 것을 알리게 됩니다.
|
|
139
|
+
- 확인 표시는 화면에만 나타나고 라이브 영역이 없습니다. 복사 결과가 중요하다면(한 번만
|
|
140
|
+
보여 주는 키 등) `Toast` 같은 방법으로도 알립니다(WCAG 4.1.3).
|
|
141
|
+
- 긴 값은 흐려지는 부분 아래로 가로 스크롤됩니다. 값의 앞부분만 보고도 무엇인지 알 수
|
|
142
|
+
있게 합니다.
|
|
143
|
+
|
|
144
|
+
## 토큰
|
|
145
|
+
|
|
146
|
+
</Ko>
|
|
147
|
+
|
|
148
|
+
<Canvas of={CopyableCodeStories.UsageTokens} sourceState="none" />
|
|
149
|
+
|
|
150
|
+
<En>
|
|
151
|
+
|
|
152
|
+
## Related
|
|
153
|
+
|
|
154
|
+
- **Code**: multi-line snippets with a copy button.
|
|
155
|
+
- **InlineCode**: a value inside a sentence.
|
|
156
|
+
- **Toast**: announce a copy result that matters.
|
|
157
|
+
|
|
158
|
+
</En>
|
|
159
|
+
|
|
160
|
+
<Ko>
|
|
161
|
+
|
|
162
|
+
## 관련 컴포넌트
|
|
163
|
+
|
|
164
|
+
- **Code**: 복사 버튼이 있는 여러 줄 코드.
|
|
165
|
+
- **InlineCode**: 문장 안의 값.
|
|
166
|
+
- **Toast**: 중요한 복사 결과를 알릴 때.
|
|
167
|
+
|
|
168
|
+
</Ko>
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Flex, HStack, Text } from '@chakra-ui/react';
|
|
2
2
|
import { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
|
|
4
|
+
import { T } from '../../guidelines/_components/Lang';
|
|
5
|
+
import { TokenTable } from '../../guidelines/_components/TokenTable';
|
|
4
6
|
import { BellIcon } from '../Icon';
|
|
5
7
|
import { IconButton } from '../IconButton';
|
|
6
8
|
import { CountBadge } from '.';
|
|
9
|
+
import { countBadgeBaseStyles } from './CountBadge.styles';
|
|
7
10
|
|
|
8
11
|
const meta = {
|
|
9
12
|
title: 'Components/CountBadge',
|
|
@@ -107,3 +110,69 @@ export const OnIconButton: Story = {
|
|
|
107
110
|
);
|
|
108
111
|
},
|
|
109
112
|
};
|
|
113
|
+
|
|
114
|
+
// ───────────────────────── Usage-page specimens ─────────────────────────
|
|
115
|
+
// Pulled into `CountBadge.usage.mdx` with <Canvas of={…} />. Hidden from the
|
|
116
|
+
// sidebar (`!dev`); `tags` is written on each story because the indexer reads
|
|
117
|
+
// CSF statically.
|
|
118
|
+
|
|
119
|
+
const FOLDERS = [
|
|
120
|
+
{ name: '연구 자료', files: 128 },
|
|
121
|
+
{ name: '수업 자료', files: 42 },
|
|
122
|
+
{ name: '행정 문서', files: 7 },
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
export const DontCountForTotals: Story = {
|
|
126
|
+
tags: ['!dev'],
|
|
127
|
+
parameters: { layout: 'padded' },
|
|
128
|
+
name: "Usage / Don't: a count badge for a total",
|
|
129
|
+
render: () => (
|
|
130
|
+
<Flex direction="column" gap={2} w="240px">
|
|
131
|
+
{FOLDERS.map((folder) => (
|
|
132
|
+
<HStack key={folder.name} justify="space-between">
|
|
133
|
+
<Text>{folder.name}</Text>
|
|
134
|
+
<CountBadge count={folder.files} />
|
|
135
|
+
</HStack>
|
|
136
|
+
))}
|
|
137
|
+
</Flex>
|
|
138
|
+
),
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const DoTotalsAsText: Story = {
|
|
142
|
+
tags: ['!dev'],
|
|
143
|
+
parameters: { layout: 'padded' },
|
|
144
|
+
name: 'Usage / Do: totals as plain text',
|
|
145
|
+
render: () => (
|
|
146
|
+
<Flex direction="column" gap={2} w="240px">
|
|
147
|
+
{FOLDERS.map((folder) => (
|
|
148
|
+
<HStack key={folder.name} justify="space-between">
|
|
149
|
+
<Text>{folder.name}</Text>
|
|
150
|
+
<Text textStyle="subtext" color="fg.muted">
|
|
151
|
+
파일 {folder.files}개
|
|
152
|
+
</Text>
|
|
153
|
+
</HStack>
|
|
154
|
+
))}
|
|
155
|
+
</Flex>
|
|
156
|
+
),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/** Tokens the badge reads, from `CountBadge.styles.ts` and the theme. */
|
|
160
|
+
export const UsageTokens: Story = {
|
|
161
|
+
tags: ['!dev'],
|
|
162
|
+
parameters: { layout: 'padded' },
|
|
163
|
+
name: 'Usage / Tokens',
|
|
164
|
+
render: () => (
|
|
165
|
+
<TokenTable
|
|
166
|
+
rows={[
|
|
167
|
+
{
|
|
168
|
+
token: countBadgeBaseStyles.bgColor as string,
|
|
169
|
+
use: <T en="fill (number and dot)" ko="바탕(숫자, 점)" />,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
token: countBadgeBaseStyles.color as string,
|
|
173
|
+
use: <T en="number" ko="숫자" />,
|
|
174
|
+
},
|
|
175
|
+
]}
|
|
176
|
+
/>
|
|
177
|
+
),
|
|
178
|
+
};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
|
|
4
|
+
import * as CountBadgeStories from './CountBadge.stories';
|
|
5
|
+
|
|
6
|
+
<Meta of={CountBadgeStories} name="Usage" />
|
|
7
|
+
|
|
8
|
+
<LangToggle />
|
|
9
|
+
|
|
10
|
+
<En>
|
|
11
|
+
|
|
12
|
+
# CountBadge
|
|
13
|
+
|
|
14
|
+
A small coral-red count of things that are waiting for the reader: unread
|
|
15
|
+
messages, new notifications.
|
|
16
|
+
|
|
17
|
+
## When to use
|
|
18
|
+
|
|
19
|
+
- An unread or pending count next to a nav item, a tab or a list row.
|
|
20
|
+
- On an icon-only button, such as the notification bell.
|
|
21
|
+
- `dot` when there is something new but the number does not matter.
|
|
22
|
+
|
|
23
|
+
## When not to use
|
|
24
|
+
|
|
25
|
+
- A total or a quantity (파일 128개, 멤버 42명) → plain text. Coral says "this
|
|
26
|
+
needs you"; a total does not.
|
|
27
|
+
- A status or a label → `Badge`.
|
|
28
|
+
- Something the reader can select or remove → `Tag`.
|
|
29
|
+
|
|
30
|
+
## Variants and what they mean
|
|
31
|
+
|
|
32
|
+
</En>
|
|
33
|
+
|
|
34
|
+
<Ko>
|
|
35
|
+
|
|
36
|
+
# CountBadge
|
|
37
|
+
|
|
38
|
+
읽지 않은 메시지나 새 알림처럼 사용자를 기다리는 항목의 개수를 보여 주는 작은
|
|
39
|
+
코럴 레드 배지입니다.
|
|
40
|
+
|
|
41
|
+
## 언제 쓰나요
|
|
42
|
+
|
|
43
|
+
- 메뉴 항목, 탭, 목록 행 옆에 읽지 않았거나 처리할 항목의 개수를 보여 줄 때.
|
|
44
|
+
- 알림 종 같은 아이콘 버튼 위에 개수를 올릴 때.
|
|
45
|
+
- 새 소식이 있다는 것만 중요하고 개수는 중요하지 않을 때는 `dot`을 씁니다.
|
|
46
|
+
|
|
47
|
+
## 언제 쓰지 않나요
|
|
48
|
+
|
|
49
|
+
- 전체 개수나 수량(파일 128개, 멤버 42명)은 일반 글자로 씁니다. 코럴은 "확인이
|
|
50
|
+
필요함"이라는 뜻인데, 전체 개수에는 그런 뜻이 없습니다.
|
|
51
|
+
- 상태나 라벨은 `Badge`를 씁니다.
|
|
52
|
+
- 사용자가 고르거나 지울 수 있다면 `Tag`를 씁니다.
|
|
53
|
+
|
|
54
|
+
## 변형과 뜻
|
|
55
|
+
|
|
56
|
+
</Ko>
|
|
57
|
+
|
|
58
|
+
<ArgTypes of={CountBadgeStories} include={['count', 'max', 'dot', 'showZero', 'label', 'size']} />
|
|
59
|
+
|
|
60
|
+
<En>
|
|
61
|
+
|
|
62
|
+
| Form | Shows | Notes |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| Number (default) | `count`, capped at `max` (99 → `99+`) | Renders nothing for 0 unless `showZero` |
|
|
65
|
+
| `dot` | A circle with no number | Hidden from assistive tech unless it has a `label`; with a `count` of 0 it disappears |
|
|
66
|
+
|
|
67
|
+
Sizes `sm` / `md` (default) / `lg` are 16 / 18 / 22 px tall. Digits are
|
|
68
|
+
tabular, so the badge does not change width as the number changes.
|
|
69
|
+
|
|
70
|
+
## Do / Don't
|
|
71
|
+
|
|
72
|
+
</En>
|
|
73
|
+
|
|
74
|
+
<Ko>
|
|
75
|
+
|
|
76
|
+
| 형태 | 보이는 것 | 참고 |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| 숫자(기본) | `count`, `max`에서 잘림(99 → `99+`) | `showZero`가 없으면 0일 때 아무것도 그리지 않음 |
|
|
79
|
+
| `dot` | 숫자 없는 점 | `label`이 없으면 보조 기술에서 숨겨짐. `count`가 0이면 사라짐 |
|
|
80
|
+
|
|
81
|
+
크기 `sm` / `md`(기본) / `lg`의 높이는 16 / 18 / 22px입니다. 숫자 폭이 고정되어 있어
|
|
82
|
+
숫자가 바뀌어도 배지 폭이 흔들리지 않습니다.
|
|
83
|
+
|
|
84
|
+
## 이렇게 하세요 / 이렇게 하지 마세요
|
|
85
|
+
|
|
86
|
+
</Ko>
|
|
87
|
+
|
|
88
|
+
<Canvas of={CountBadgeStories.InContext} />
|
|
89
|
+
<Verdict
|
|
90
|
+
kind="do"
|
|
91
|
+
en="Next to a nav item, give the badge a label that says what it counts. The screen reader hears 읽지 않은 메시지 12개 instead of a bare 12."
|
|
92
|
+
ko="메뉴 항목 옆에서는 무엇의 개수인지 알려 주는 label을 붙입니다. 화면 낭독기는 '12' 대신 '읽지 않은 메시지 12개'라고 읽습니다."
|
|
93
|
+
/>
|
|
94
|
+
|
|
95
|
+
<Canvas of={CountBadgeStories.OnIconButton} />
|
|
96
|
+
<Verdict
|
|
97
|
+
kind="do"
|
|
98
|
+
en="On an icon-only button, put the count in the button's aria-label and leave the badge unlabelled. The button's aria-label replaces everything inside it."
|
|
99
|
+
ko="아이콘 버튼에서는 개수를 버튼의 aria-label에 넣고 배지에는 label을 달지 않습니다. 버튼의 aria-label이 안에 든 내용을 모두 대신합니다."
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
<Canvas of={CountBadgeStories.DontCountForTotals} />
|
|
103
|
+
<Verdict
|
|
104
|
+
kind="dont"
|
|
105
|
+
en="Use a count badge for totals. Three coral badges in a list read as three things that need attention."
|
|
106
|
+
ko="전체 개수에 CountBadge를 쓰지 마세요. 목록에 코럴 배지가 세 개 있으면 확인할 일이 세 가지 있는 것처럼 읽힙니다."
|
|
107
|
+
/>
|
|
108
|
+
|
|
109
|
+
<Canvas of={CountBadgeStories.DoTotalsAsText} />
|
|
110
|
+
<Verdict
|
|
111
|
+
kind="do"
|
|
112
|
+
en="Write totals as muted text with the unit."
|
|
113
|
+
ko="전체 개수는 단위를 붙여 흐린 글자로 씁니다."
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
<En>
|
|
117
|
+
|
|
118
|
+
## Content
|
|
119
|
+
|
|
120
|
+
- Numbers only; the unit and meaning go in `label` or the surrounding text.
|
|
121
|
+
- Keep the default `max` of 99 unless the exact number above it matters to the
|
|
122
|
+
reader.
|
|
123
|
+
- Write `label` as a complete phrase with the full number: "읽지 않은 알림
|
|
124
|
+
120개", even when the badge shows `99+`.
|
|
125
|
+
|
|
126
|
+
## Accessibility
|
|
127
|
+
|
|
128
|
+
What CountBadge does for you:
|
|
129
|
+
|
|
130
|
+
- With a `label`, the visible number is hidden from assistive tech and the
|
|
131
|
+
label is read instead, so `99+` is announced as the real count.
|
|
132
|
+
- A `dot` without a `label` is `aria-hidden`; with one it is an `img` with that
|
|
133
|
+
name.
|
|
134
|
+
- It renders as a `<span>`, so it is valid inside a button or link
|
|
135
|
+
(`ACCESSIBILITY.md` §5, KWCAG 5.4.1.1).
|
|
136
|
+
- `count.fg` on `count.bg` passes the contrast audit in both modes
|
|
137
|
+
(WCAG 1.4.3).
|
|
138
|
+
|
|
139
|
+
What you still have to do:
|
|
140
|
+
|
|
141
|
+
- **Give it a `label` when the number alone makes no sense**, in a nav item or a
|
|
142
|
+
list row (WCAG 1.1.1).
|
|
143
|
+
- **On an icon-only button, put the count in the button's `aria-label`**
|
|
144
|
+
(WCAG 4.1.2). A `label` on the badge there is never announced.
|
|
145
|
+
- The badge does not announce changes. If a new count matters while the reader
|
|
146
|
+
is on the page, announce it through a polite live region (`role="status"`)
|
|
147
|
+
as well (WCAG 4.1.3).
|
|
148
|
+
|
|
149
|
+
## Tokens
|
|
150
|
+
|
|
151
|
+
The table is generated from `CountBadge.styles.ts` and the theme.
|
|
152
|
+
|
|
153
|
+
</En>
|
|
154
|
+
|
|
155
|
+
<Ko>
|
|
156
|
+
|
|
157
|
+
## 문구
|
|
158
|
+
|
|
159
|
+
- 숫자만 씁니다. 단위와 뜻은 `label`이나 주변 글자에 담습니다.
|
|
160
|
+
- 99보다 큰 정확한 숫자가 사용자에게 중요하지 않다면 기본 `max` 99를 그대로 둡니다.
|
|
161
|
+
- `label`은 실제 숫자를 넣은 완전한 구절로 씁니다. 배지에 `99+`가 보여도 "읽지 않은
|
|
162
|
+
알림 120개"라고 씁니다.
|
|
163
|
+
|
|
164
|
+
## 접근성
|
|
165
|
+
|
|
166
|
+
CountBadge가 알아서 하는 일
|
|
167
|
+
|
|
168
|
+
- `label`이 있으면 보이는 숫자는 보조 기술에서 숨기고 label을 대신 읽습니다. 그래서
|
|
169
|
+
`99+`가 실제 개수로 읽힙니다.
|
|
170
|
+
- `label`이 없는 `dot`은 `aria-hidden`이고, label이 있으면 그 이름을 가진 `img`가
|
|
171
|
+
됩니다.
|
|
172
|
+
- `<span>`으로 그려지므로 버튼이나 링크 안에 넣어도 됩니다(`ACCESSIBILITY.md` §5,
|
|
173
|
+
KWCAG 5.4.1.1).
|
|
174
|
+
- `count.bg` 위의 `count.fg`는 라이트·다크 모두 대비 감사를 통과합니다(WCAG 1.4.3).
|
|
175
|
+
|
|
176
|
+
직접 챙겨야 하는 일
|
|
177
|
+
|
|
178
|
+
- **숫자만으로 뜻이 통하지 않는다면 `label`을 붙입니다.** 메뉴 항목이나 목록 행 옆이
|
|
179
|
+
그렇습니다(WCAG 1.1.1).
|
|
180
|
+
- **아이콘 버튼에서는 개수를 버튼의 `aria-label`에 넣습니다**(WCAG 4.1.2). 그 자리에서
|
|
181
|
+
배지의 `label`은 읽히지 않습니다.
|
|
182
|
+
- 배지는 숫자가 바뀌어도 알려 주지 않습니다. 사용자가 화면을 보는 동안 새 개수가
|
|
183
|
+
중요하다면, 공손한 라이브 영역(`role="status"`)으로도 알립니다(WCAG 4.1.3).
|
|
184
|
+
|
|
185
|
+
## 토큰
|
|
186
|
+
|
|
187
|
+
아래 표는 `CountBadge.styles.ts`와 테마에서 자동으로 만듭니다.
|
|
188
|
+
|
|
189
|
+
</Ko>
|
|
190
|
+
|
|
191
|
+
<Canvas of={CountBadgeStories.UsageTokens} sourceState="none" />
|
|
192
|
+
|
|
193
|
+
<En>
|
|
194
|
+
|
|
195
|
+
## Related
|
|
196
|
+
|
|
197
|
+
- **Badge**: a status or an attribute.
|
|
198
|
+
- **Tag**: a label the reader can select or remove.
|
|
199
|
+
- **IconButton**: where the bell and its count live.
|
|
200
|
+
- **Foundations/Brand & colour usage**: coral only for send, run, the
|
|
201
|
+
AI-working mark and counts.
|
|
202
|
+
|
|
203
|
+
</En>
|
|
204
|
+
|
|
205
|
+
<Ko>
|
|
206
|
+
|
|
207
|
+
## 관련 컴포넌트
|
|
208
|
+
|
|
209
|
+
- **Badge**: 상태나 속성.
|
|
210
|
+
- **Tag**: 사용자가 고르거나 지울 수 있는 라벨.
|
|
211
|
+
- **IconButton**: 알림 종과 그 개수가 놓이는 곳.
|
|
212
|
+
- **Foundations/Brand & colour usage**: 코럴은 전송, 실행, AI 작업 표시, 개수에만
|
|
213
|
+
씁니다.
|
|
214
|
+
|
|
215
|
+
</Ko>
|