@iamfiro/design 0.0.0-stage → 0.1.0

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 (264) hide show
  1. package/AGENTS.md +81 -0
  2. package/README.md +15 -2
  3. package/agents/INDEX.md +156 -0
  4. package/agents/accordion/AGENTS.md +279 -0
  5. package/agents/action-bar/AGENTS.md +90 -0
  6. package/agents/alert/AGENTS.md +212 -0
  7. package/agents/alert-dialog/AGENTS.md +193 -0
  8. package/agents/app-shell/AGENTS.md +409 -0
  9. package/agents/area-chart/AGENTS.md +183 -0
  10. package/agents/aspect-ratio/AGENTS.md +143 -0
  11. package/agents/avatar/AGENTS.md +130 -0
  12. package/agents/badge/AGENTS.md +217 -0
  13. package/agents/bar-chart/AGENTS.md +386 -0
  14. package/agents/bar-list/AGENTS.md +223 -0
  15. package/agents/brand-icon/AGENTS.md +82 -0
  16. package/agents/breadcrumb/AGENTS.md +133 -0
  17. package/agents/button/AGENTS.md +195 -0
  18. package/agents/card/AGENTS.md +141 -0
  19. package/agents/card-frame/AGENTS.md +227 -0
  20. package/agents/chat-bubble/AGENTS.md +266 -0
  21. package/agents/chat-composer/AGENTS.md +251 -0
  22. package/agents/checkbox/AGENTS.md +113 -0
  23. package/agents/code-block/AGENTS.md +144 -0
  24. package/agents/color-dot/AGENTS.md +120 -0
  25. package/agents/color-picker/AGENTS.md +224 -0
  26. package/agents/colors/AGENTS.md +168 -0
  27. package/agents/combobox/AGENTS.md +218 -0
  28. package/agents/command-menu/AGENTS.md +169 -0
  29. package/agents/comment/AGENTS.md +206 -0
  30. package/agents/context-menu/AGENTS.md +303 -0
  31. package/agents/copy-button/AGENTS.md +84 -0
  32. package/agents/count-badge/AGENTS.md +115 -0
  33. package/agents/countdown/AGENTS.md +101 -0
  34. package/agents/data-grid/AGENTS.md +460 -0
  35. package/agents/date-picker/AGENTS.md +197 -0
  36. package/agents/delta/AGENTS.md +114 -0
  37. package/agents/description-list/AGENTS.md +251 -0
  38. package/agents/dialog/AGENTS.md +391 -0
  39. package/agents/drawer/AGENTS.md +471 -0
  40. package/agents/dropdown-menu/AGENTS.md +322 -0
  41. package/agents/dropzone/AGENTS.md +116 -0
  42. package/agents/elapsed/AGENTS.md +160 -0
  43. package/agents/empty-state/AGENTS.md +203 -0
  44. package/agents/file-chip/AGENTS.md +79 -0
  45. package/agents/file-icon/AGENTS.md +66 -0
  46. package/agents/file-upload/AGENTS.md +168 -0
  47. package/agents/filter-chips/AGENTS.md +167 -0
  48. package/agents/flag/AGENTS.md +67 -0
  49. package/agents/funnel-chart/AGENTS.md +131 -0
  50. package/agents/highlight/AGENTS.md +119 -0
  51. package/agents/hover-card/AGENTS.md +271 -0
  52. package/agents/icon-stack/AGENTS.md +120 -0
  53. package/agents/icon-tile/AGENTS.md +94 -0
  54. package/agents/inline-diff/AGENTS.md +211 -0
  55. package/agents/input/AGENTS.md +261 -0
  56. package/agents/kanban/AGENTS.md +352 -0
  57. package/agents/kbd/AGENTS.md +160 -0
  58. package/agents/layout/AGENTS.md +351 -0
  59. package/agents/line-chart/AGENTS.md +393 -0
  60. package/agents/link/AGENTS.md +53 -0
  61. package/agents/list/AGENTS.md +392 -0
  62. package/agents/marker/AGENTS.md +142 -0
  63. package/agents/masked-text/AGENTS.md +127 -0
  64. package/agents/menubar/AGENTS.md +276 -0
  65. package/agents/multi-select/AGENTS.md +159 -0
  66. package/agents/navigation-menu/AGENTS.md +315 -0
  67. package/agents/notice-stack/AGENTS.md +101 -0
  68. package/agents/number-stepper/AGENTS.md +96 -0
  69. package/agents/otp-input/AGENTS.md +162 -0
  70. package/agents/pagination/AGENTS.md +189 -0
  71. package/agents/phone-input/AGENTS.md +131 -0
  72. package/agents/pie-chart/AGENTS.md +243 -0
  73. package/agents/popover/AGENTS.md +190 -0
  74. package/agents/progress/AGENTS.md +273 -0
  75. package/agents/progress-tracker/AGENTS.md +305 -0
  76. package/agents/rating/AGENTS.md +165 -0
  77. package/agents/relative-time/AGENTS.md +103 -0
  78. package/agents/resizable/AGENTS.md +390 -0
  79. package/agents/scaled-preview/AGENTS.md +111 -0
  80. package/agents/scatter-chart/AGENTS.md +160 -0
  81. package/agents/scroll-area/AGENTS.md +271 -0
  82. package/agents/search-input/AGENTS.md +105 -0
  83. package/agents/segmented-control/AGENTS.md +153 -0
  84. package/agents/select/AGENTS.md +159 -0
  85. package/agents/selector-button/AGENTS.md +122 -0
  86. package/agents/sidebar/AGENTS.md +201 -0
  87. package/agents/skeleton/AGENTS.md +166 -0
  88. package/agents/slider/AGENTS.md +181 -0
  89. package/agents/spark-chart/AGENTS.md +257 -0
  90. package/agents/sparkbar/AGENTS.md +92 -0
  91. package/agents/spinner/AGENTS.md +123 -0
  92. package/agents/split-view/AGENTS.md +290 -0
  93. package/agents/stat/AGENTS.md +138 -0
  94. package/agents/status-icon/AGENTS.md +243 -0
  95. package/agents/step-list/AGENTS.md +313 -0
  96. package/agents/table/AGENTS.md +286 -0
  97. package/agents/tabs/AGENTS.md +305 -0
  98. package/agents/tag-input/AGENTS.md +246 -0
  99. package/agents/time-picker/AGENTS.md +228 -0
  100. package/agents/timeline/AGENTS.md +1018 -0
  101. package/agents/toast/AGENTS.md +266 -0
  102. package/agents/toggle-group/AGENTS.md +216 -0
  103. package/agents/toolbar/AGENTS.md +277 -0
  104. package/agents/tooltip/AGENTS.md +154 -0
  105. package/agents/tracker/AGENTS.md +158 -0
  106. package/agents/tree-diagram/AGENTS.md +260 -0
  107. package/agents/tree-view/AGENTS.md +329 -0
  108. package/agents/typography/AGENTS.md +396 -0
  109. package/lib/index.js +17914 -0
  110. package/lib/style.css +2 -0
  111. package/lib/types/components/Accordion/Accordion.d.ts +57 -0
  112. package/lib/types/components/ActionBar/ActionBar.d.ts +24 -0
  113. package/lib/types/components/Alert/Alert.d.ts +36 -0
  114. package/lib/types/components/AppShell/AppShell.d.ts +38 -0
  115. package/lib/types/components/AreaChart/AreaChart.d.ts +17 -0
  116. package/lib/types/components/BarChart/BarChart.d.ts +57 -0
  117. package/lib/types/components/BarList/BarList.d.ts +56 -0
  118. package/lib/types/components/Breadcrumb/Breadcrumb.d.ts +15 -0
  119. package/lib/types/components/Calendar/Calendar.d.ts +34 -0
  120. package/lib/types/components/Calendar/DatePicker.d.ts +45 -0
  121. package/lib/types/components/Calendar/date.d.ts +32 -0
  122. package/lib/types/components/Card/Card.d.ts +64 -0
  123. package/lib/types/components/CardFrame/CardFrame.d.ts +15 -0
  124. package/lib/types/components/Chart/ChartParts.d.ts +38 -0
  125. package/lib/types/components/Chart/chart.d.ts +46 -0
  126. package/lib/types/components/Chart/useChartInteraction.d.ts +39 -0
  127. package/lib/types/components/ChatBubble/ChatBubble.d.ts +61 -0
  128. package/lib/types/components/ChatBubble/formatChatTime.d.ts +2 -0
  129. package/lib/types/components/ChatComposer/ChatComposer.d.ts +42 -0
  130. package/lib/types/components/CodeBlock/CodeBlock.d.ts +18 -0
  131. package/lib/types/components/CodeBlock/highlight.d.ts +10 -0
  132. package/lib/types/components/ColorPicker/ColorPicker.d.ts +61 -0
  133. package/lib/types/components/ColorPicker/color.d.ts +48 -0
  134. package/lib/types/components/ColorPicker/presets.d.ts +7 -0
  135. package/lib/types/components/Combobox/Combobox.d.ts +48 -0
  136. package/lib/types/components/CommandMenu/CommandMenu.d.ts +51 -0
  137. package/lib/types/components/Comment/Comment.d.ts +45 -0
  138. package/lib/types/components/ContextMenu/ContextMenu.d.ts +40 -0
  139. package/lib/types/components/DataGrid/DataGrid.d.ts +43 -0
  140. package/lib/types/components/DataGrid/GridPopover.d.ts +43 -0
  141. package/lib/types/components/DataGrid/anchor.d.ts +5 -0
  142. package/lib/types/components/DataGrid/model.d.ts +61 -0
  143. package/lib/types/components/DataGrid/panels.d.ts +63 -0
  144. package/lib/types/components/DataGrid/typeMeta.d.ts +6 -0
  145. package/lib/types/components/DataGrid/types.d.ts +77 -0
  146. package/lib/types/components/DescriptionList/DescriptionList.d.ts +77 -0
  147. package/lib/types/components/Dialog/AlertDialog.d.ts +26 -0
  148. package/lib/types/components/Dialog/Dialog.d.ts +42 -0
  149. package/lib/types/components/Dialog/modal.d.ts +38 -0
  150. package/lib/types/components/Drawer/Drawer.d.ts +62 -0
  151. package/lib/types/components/DropdownMenu/DropdownMenu.d.ts +97 -0
  152. package/lib/types/components/DropdownMenu/menuCore.d.ts +23 -0
  153. package/lib/types/components/Dropzone/Dropzone.d.ts +30 -0
  154. package/lib/types/components/EmptyState/EmptyState.d.ts +26 -0
  155. package/lib/types/components/FileChip/FileChip.d.ts +32 -0
  156. package/lib/types/components/FileUpload/FileUpload.d.ts +52 -0
  157. package/lib/types/components/FilterChips/FilterChips.d.ts +37 -0
  158. package/lib/types/components/FunnelChart/FunnelChart.d.ts +38 -0
  159. package/lib/types/components/FunnelChart/funnel.d.ts +25 -0
  160. package/lib/types/components/Highlight/Highlight.d.ts +35 -0
  161. package/lib/types/components/HoverCard/HoverCard.d.ts +47 -0
  162. package/lib/types/components/InlineDiff/InlineDiff.d.ts +36 -0
  163. package/lib/types/components/InlineDiff/diff.d.ts +42 -0
  164. package/lib/types/components/InlineDiff/useDiffReview.d.ts +57 -0
  165. package/lib/types/components/Kanban/Kanban.d.ts +64 -0
  166. package/lib/types/components/Kanban/KanbanCard.d.ts +35 -0
  167. package/lib/types/components/Kanban/move.d.ts +25 -0
  168. package/lib/types/components/LineChart/LineChart.d.ts +85 -0
  169. package/lib/types/components/List/List.d.ts +62 -0
  170. package/lib/types/components/Listbox/Listbox.d.ts +60 -0
  171. package/lib/types/components/Marker/Marker.d.ts +28 -0
  172. package/lib/types/components/Menubar/Menubar.d.ts +50 -0
  173. package/lib/types/components/MultiSelect/MultiSelect.d.ts +38 -0
  174. package/lib/types/components/NavigationMenu/NavigationMenu.d.ts +101 -0
  175. package/lib/types/components/NoticeStack/NoticeStack.d.ts +41 -0
  176. package/lib/types/components/NumberStepper/NumberStepper.d.ts +32 -0
  177. package/lib/types/components/OtpInput/OtpInput.d.ts +31 -0
  178. package/lib/types/components/Pagination/Pagination.d.ts +54 -0
  179. package/lib/types/components/Pagination/paginationRange.d.ts +7 -0
  180. package/lib/types/components/PhoneInput/PhoneInput.d.ts +47 -0
  181. package/lib/types/components/PieChart/PieChart.d.ts +67 -0
  182. package/lib/types/components/PieChart/arc.d.ts +26 -0
  183. package/lib/types/components/PieChart/useArcTween.d.ts +15 -0
  184. package/lib/types/components/Popover/Popover.d.ts +28 -0
  185. package/lib/types/components/ProgressTracker/ProgressTracker.d.ts +64 -0
  186. package/lib/types/components/Rating/Rating.d.ts +42 -0
  187. package/lib/types/components/Resizable/Resizable.d.ts +50 -0
  188. package/lib/types/components/Resizable/layout.d.ts +31 -0
  189. package/lib/types/components/ScaledPreview/ScaledPreview.d.ts +38 -0
  190. package/lib/types/components/ScatterChart/ScatterChart.d.ts +81 -0
  191. package/lib/types/components/ScatterChart/scatter.d.ts +14 -0
  192. package/lib/types/components/ScrollArea/ScrollArea.d.ts +34 -0
  193. package/lib/types/components/Select/Select.d.ts +39 -0
  194. package/lib/types/components/Sidebar/Sidebar.d.ts +39 -0
  195. package/lib/types/components/Skeleton/Skeleton.d.ts +47 -0
  196. package/lib/types/components/Slider/Slider.d.ts +36 -0
  197. package/lib/types/components/SparkChart/SparkChart.d.ts +55 -0
  198. package/lib/types/components/SparkChart/spark.d.ts +16 -0
  199. package/lib/types/components/Sparkbar/Sparkbar.d.ts +39 -0
  200. package/lib/types/components/SplitView/SplitView.d.ts +31 -0
  201. package/lib/types/components/Stat/Stat.d.ts +58 -0
  202. package/lib/types/components/StepList/StepList.d.ts +61 -0
  203. package/lib/types/components/Table/Table.d.ts +39 -0
  204. package/lib/types/components/Tabs/Tabs.d.ts +47 -0
  205. package/lib/types/components/TagInput/TagInput.d.ts +46 -0
  206. package/lib/types/components/TimePicker/TimePicker.d.ts +43 -0
  207. package/lib/types/components/TimePicker/time.d.ts +15 -0
  208. package/lib/types/components/Timeline/Timeline.d.ts +154 -0
  209. package/lib/types/components/Timeline/scale.d.ts +22 -0
  210. package/lib/types/components/Toast/Toaster.d.ts +19 -0
  211. package/lib/types/components/Toast/index.d.ts +4 -0
  212. package/lib/types/components/Toast/store.d.ts +75 -0
  213. package/lib/types/components/ToggleGroup/ToggleGroup.d.ts +28 -0
  214. package/lib/types/components/Toolbar/Toolbar.d.ts +70 -0
  215. package/lib/types/components/Tracker/Tracker.d.ts +43 -0
  216. package/lib/types/components/TreeDiagram/TreeDiagram.d.ts +68 -0
  217. package/lib/types/components/TreeView/TreeView.d.ts +107 -0
  218. package/lib/types/components/index.d.ts +186 -0
  219. package/lib/types/hooks/index.d.ts +17 -0
  220. package/lib/types/hooks/timing.d.ts +29 -0
  221. package/lib/types/hooks/useControllableState.d.ts +5 -0
  222. package/lib/types/hooks/useCountdown.d.ts +19 -0
  223. package/lib/types/hooks/useDigitInput.d.ts +24 -0
  224. package/lib/types/hooks/useDismiss.d.ts +3 -0
  225. package/lib/types/hooks/useElapsed.d.ts +28 -0
  226. package/lib/types/hooks/useFloating.d.ts +21 -0
  227. package/lib/types/hooks/useFocusTrap.d.ts +7 -0
  228. package/lib/types/hooks/usePresence.d.ts +8 -0
  229. package/lib/types/hooks/usePressToOpen.d.ts +20 -0
  230. package/lib/types/hooks/useScrollLock.d.ts +2 -0
  231. package/lib/types/hooks/useSelection.d.ts +29 -0
  232. package/lib/types/index.d.ts +5 -0
  233. package/lib/types/primitives/AspectRatio.d.ts +14 -0
  234. package/lib/types/primitives/BrandIcon.d.ts +12 -0
  235. package/lib/types/primitives/ColorDot.d.ts +20 -0
  236. package/lib/types/primitives/CopyButton.d.ts +12 -0
  237. package/lib/types/primitives/CountBadge.d.ts +28 -0
  238. package/lib/types/primitives/Countdown.d.ts +21 -0
  239. package/lib/types/primitives/Delta.d.ts +33 -0
  240. package/lib/types/primitives/Elapsed.d.ts +23 -0
  241. package/lib/types/primitives/FileIcon.d.ts +17 -0
  242. package/lib/types/primitives/Flag.d.ts +15 -0
  243. package/lib/types/primitives/IconStack.d.ts +27 -0
  244. package/lib/types/primitives/IconTile.d.ts +24 -0
  245. package/lib/types/primitives/Kbd.d.ts +19 -0
  246. package/lib/types/primitives/Layout.d.ts +64 -0
  247. package/lib/types/primitives/Link.d.ts +12 -0
  248. package/lib/types/primitives/MaskedText.d.ts +28 -0
  249. package/lib/types/primitives/Progress.d.ts +52 -0
  250. package/lib/types/primitives/RelativeTime.d.ts +22 -0
  251. package/lib/types/primitives/SearchInput.d.ts +8 -0
  252. package/lib/types/primitives/SelectorButton.d.ts +23 -0
  253. package/lib/types/primitives/Spinner.d.ts +15 -0
  254. package/lib/types/primitives/StatusIcon.d.ts +40 -0
  255. package/lib/types/primitives/Swatch.d.ts +11 -0
  256. package/lib/types/primitives/Tooltip.d.ts +17 -0
  257. package/lib/types/primitives/Typography.d.ts +48 -0
  258. package/lib/types/primitives/formatCountdown.d.ts +2 -0
  259. package/lib/types/primitives/formatElapsed.d.ts +8 -0
  260. package/lib/types/primitives/formatRelativeTime.d.ts +16 -0
  261. package/lib/types/primitives/hotkey.d.ts +10 -0
  262. package/lib/types/primitives/index.d.ts +188 -0
  263. package/lib/types/primitives/maskValue.d.ts +24 -0
  264. package/package.json +54 -4
@@ -0,0 +1,143 @@
1
+ # AspectRatio
2
+
3
+ > 파운데이션 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 폭은 부모를 따르고 높이는 비율로 정해지는 틀. 이미지·동영상·지도·미리보기가 불러오기 전에도 자리를 차지해 레이아웃이 밀리지 않아요. 바로 아래 자식은 틀을 꽉 채우고, 이미지는 잘라 채우거나(cover) 여백을 두고 맞춰요(contain).
6
+
7
+ ```tsx
8
+ import { AspectRatio } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### AspectRatio
14
+
15
+ div의 나머지 속성(aria-*, onClick 등)을 그대로 받아요.
16
+
17
+ | prop | 타입 | 기본값 | 설명 |
18
+ | --- | --- | --- | --- |
19
+ | `ratio` | `number \| string` | `1` | 폭 ÷ 높이. 16 / 9, '16/9', '16:9'. |
20
+ | `fit` | `'cover' \| 'contain'` | `'cover'` | 바로 아래 img · video가 틀을 채우는 방식. |
21
+ | `radius` | `'none' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'none'` | 모서리 둥글기(토큰). |
22
+ | `background` | `'none' \| 'subtle'` | `'none'` | subtle은 작은 회색 채움(#f4f4f4). 자리 표시와 contain 여백에 써요. |
23
+
24
+ ## 예제
25
+
26
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
27
+
28
+ ### 기본
29
+
30
+ ratio에 폭 ÷ 높이를 넘겨요. 16 / 9 같은 숫자나 '16/9' · '16:9' 문자열 모두 돼요.
31
+
32
+ ```tsx
33
+ import { AspectRatio, Stack, Text } from '@iamfiro/design'
34
+ import { Play } from 'lucide-react'
35
+
36
+ export default function Example() {
37
+ return (
38
+ <div style={{ width: 420 }}>
39
+ <AspectRatio ratio={16 / 9} radius="lg" background="subtle">
40
+ <Stack align="center" justify="center" gap={2}>
41
+ <Play size={28} />
42
+ <Text variant="caption" tone="secondary">
43
+ 제품 소개 영상 · 2:14
44
+ </Text>
45
+ </Stack>
46
+ </AspectRatio>
47
+ </div>
48
+ )
49
+ }
50
+ ```
51
+
52
+ ### 자주 쓰는 비율
53
+
54
+ 정사각 썸네일, 4:3 사진, 16:9 동영상, 21:9 배너. background="subtle"은 불러오기 전 자리 표시예요.
55
+
56
+ ```tsx
57
+ import { AspectRatio, Grid, Stack, Text } from '@iamfiro/design'
58
+
59
+ const RATIOS = [
60
+ { ratio: '1/1', label: '1:1', use: '프로필 · 썸네일' },
61
+ { ratio: '4/3', label: '4:3', use: '사진' },
62
+ { ratio: '16/9', label: '16:9', use: '동영상' },
63
+ { ratio: '21/9', label: '21:9', use: '배너' },
64
+ ]
65
+
66
+ export default function Example() {
67
+ return (
68
+ <Grid columns={4} gap={4} align="end" style={{ width: '100%', maxWidth: 640 }}>
69
+ {RATIOS.map((r) => (
70
+ <Stack key={r.ratio} gap={2}>
71
+ <AspectRatio ratio={r.ratio} radius="md" background="subtle">
72
+ <Stack align="center" justify="center">
73
+ <Text variant="label-md">{r.label}</Text>
74
+ </Stack>
75
+ </AspectRatio>
76
+ <Text variant="caption" tone="secondary">
77
+ {r.use}
78
+ </Text>
79
+ </Stack>
80
+ ))}
81
+ </Grid>
82
+ )
83
+ }
84
+ ```
85
+
86
+ ### 채우기 방식 (fit)
87
+
88
+ cover는 틀에 맞게 잘라 채우고, contain은 전체가 보이도록 회색 여백을 남겨요.
89
+
90
+ ```tsx
91
+ import { AspectRatio, Grid, Stack, Text } from '@iamfiro/design'
92
+ import hero from '@/assets/hero.png'
93
+
94
+ export default function Example() {
95
+ return (
96
+ <Grid columns={2} gap={4} style={{ width: '100%', maxWidth: 480 }}>
97
+ {(['cover', 'contain'] as const).map((fit) => (
98
+ <Stack key={fit} gap={2}>
99
+ <AspectRatio ratio={16 / 9} fit={fit} radius="md" background="subtle">
100
+ <img src={hero} alt="쌓인 레이어 그림" />
101
+ </AspectRatio>
102
+ <Text variant="caption" tone="secondary">
103
+ {fit}
104
+ </Text>
105
+ </Stack>
106
+ ))}
107
+ </Grid>
108
+ )
109
+ }
110
+ ```
111
+
112
+ ### 카드 미디어
113
+
114
+ CardMedia에 ratio를 주면 안에서 AspectRatio를 써요. 카드 목록의 이미지 높이가 모두 같아져요.
115
+
116
+ ```tsx
117
+ import { Card, CardHeader, CardMedia, Grid, Stack, Text } from '@iamfiro/design'
118
+
119
+ const POSTS = [
120
+ { title: '10월 디자인 리뷰 정리', author: '김민지', minutes: 4 },
121
+ { title: '새 온보딩 흐름 실험 결과', author: '이도현', minutes: 7 },
122
+ { title: '접근성 점검 체크리스트', author: '박서연', minutes: 3 },
123
+ ]
124
+
125
+ export default function Example() {
126
+ return (
127
+ <Grid columns={3} gap={4} style={{ width: '100%', maxWidth: 640 }}>
128
+ {POSTS.map((p) => (
129
+ <Card key={p.title} padding="sm" interactive>
130
+ <CardMedia ratio="4/3">
131
+ <Stack align="center" justify="center">
132
+ <Text variant="caption" tone="tertiary">
133
+ 이미지
134
+ </Text>
135
+ </Stack>
136
+ </CardMedia>
137
+ <CardHeader title={p.title} description={`${p.author} · ${p.minutes}분 분량`} />
138
+ </Card>
139
+ ))}
140
+ </Grid>
141
+ )
142
+ }
143
+ ```
@@ -0,0 +1,130 @@
1
+ # Avatar
2
+
3
+ > 아이콘 & 아바타 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 사람이나 팀을 나타내는 이름 배지. 한국어 이름(3–4글자)은 성을 빼고 이름만(김민지 → 민지), 그 밖의 이름은 이니셜로 보여요. 배경색은 이름에 따라 정해져 같은 사람은 늘 같은 색이에요.
6
+
7
+ ```tsx
8
+ import { Avatar, AvatarGroup } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 행 앞 타일: 사람은 `Avatar`, 도구·사이트·문서는 `IconTile`(회색 채움 + 아이콘/글자). 선택된 것을 보여 주고 메뉴로 바꾸는 버튼(워크스페이스·계정 전환, 드롭다운 제목)은 `SelectorButton`을 `DropdownMenu` trigger에.
14
+
15
+ ## API
16
+
17
+ ### Avatar
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `name` (필수) | `string` | | 이름. 보이는 글자, 배경색, 툴팁, 화면 읽기 이름이 모두 여기서 나와요. |
22
+ | `size` | `number` | `28` | 지름(px). |
23
+ | `square` | `boolean` | | 둥근 사각형. |
24
+ | `online` | `boolean` | | 오른쪽 아래 접속 중 점. |
25
+ | `color` | `string` | | 배경색. 생략하면 이름으로 정해요. |
26
+ | `tooltip` | `boolean \| ReactNode` | `true` | hover 시 이름 툴팁. 내용을 주면 그 내용, false면 툴팁 없음(이미 이름이 옆에 보이는 행 등). |
27
+
28
+ ### AvatarGroup
29
+
30
+ | prop | 타입 | 기본값 | 설명 |
31
+ | --- | --- | --- | --- |
32
+ | `names` (필수) | `string[]` | | 이름 목록. |
33
+ | `size` | `number` | `24` | 각 아바타 지름(px). |
34
+ | `max` | `number` | `4` | 보여 줄 최대 인원. 나머지는 +N. |
35
+
36
+ ## 예제
37
+
38
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
39
+
40
+ ### 기본
41
+
42
+ 한국어 이름, 영문 이름, 접속 중 표시(online), 팀 · 서비스용 각진 모양(square).
43
+
44
+ ```tsx
45
+ import { Avatar } from '@iamfiro/design'
46
+
47
+ export default function Example() {
48
+ return (
49
+ <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
50
+ <Avatar name="김민지" size={36} />
51
+ <Avatar name="이도현" size={36} online />
52
+ <Avatar name="남궁민수" size={36} />
53
+ <Avatar name="Sarah Kim" size={36} />
54
+ <Avatar name="Lumen" size={36} square />
55
+ </div>
56
+ )
57
+ }
58
+ ```
59
+
60
+ ### 크기 · 색
61
+
62
+ size는 px 숫자예요. color로 배경색을 직접 정할 수 있어요.
63
+
64
+ ```tsx
65
+ import { Avatar } from '@iamfiro/design'
66
+
67
+ const SIZES = [20, 24, 28, 36, 48]
68
+
69
+ export default function Example() {
70
+ return (
71
+ <div style={{ display: 'grid', gap: 16 }}>
72
+ <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
73
+ {SIZES.map((size) => (
74
+ <Avatar key={size} name="최서연" size={size} online={size >= 28} />
75
+ ))}
76
+ </div>
77
+ <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
78
+ <Avatar name="Acme Corp" size={36} square color="var(--accent)" />
79
+ <Avatar name="Lumen Labs" size={36} square color="var(--success)" />
80
+ <Avatar name="Northwind" size={36} square color="var(--n8)" />
81
+ </div>
82
+ </div>
83
+ )
84
+ }
85
+ ```
86
+
87
+ ### 이름 툴팁
88
+
89
+ 마우스를 올리면 Tooltip으로 전체 이름이 떠요(첫 툴팁은 잠깐 기다렸다가). tooltip에 내용을 주면 그걸, false면 끄고요. AvatarGroup의 +N은 가려진 사람들 이름을 보여 줘요.
90
+
91
+ ```tsx
92
+ import { Avatar, AvatarGroup, Inline } from '@iamfiro/design'
93
+
94
+ export default function Example() {
95
+ return (
96
+ <Inline gap={6}>
97
+ <Inline gap={3}>
98
+ <Avatar name="김민지" size={36} />
99
+ <Avatar name="Sarah Kim" size={36} tooltip="Sarah Kim · 디자인팀" />
100
+ <Avatar name="이도현" size={36} tooltip={false} />
101
+ </Inline>
102
+ <AvatarGroup names={['김민지', '이도현', '박서준', '최유진', '정하늘', '한지우']} size={32} />
103
+ </Inline>
104
+ )
105
+ }
106
+ ```
107
+
108
+ ### AvatarGroup
109
+
110
+ 겹쳐서 보여 주고, max를 넘는 인원은 +N으로 묶어요.
111
+
112
+ ```tsx
113
+ import { AvatarGroup, Text } from '@iamfiro/design'
114
+
115
+ const MEMBERS = ['김민지', '이도현', '최서연', '정우진', '한지수', '오세훈', '박미나']
116
+
117
+ export default function Example() {
118
+ return (
119
+ <div style={{ display: 'grid', gap: 16, justifyItems: 'start' }}>
120
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
121
+ <AvatarGroup names={MEMBERS} />
122
+ <Text variant="body-sm" tone="secondary" as="span">
123
+ {MEMBERS.length}명이 보고 있어요
124
+ </Text>
125
+ </div>
126
+ <AvatarGroup names={MEMBERS} size={32} max={3} />
127
+ </div>
128
+ )
129
+ }
130
+ ```
@@ -0,0 +1,217 @@
1
+ # Badge
2
+
3
+ > 라벨 & 배지 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 상태 · 분류 · 개수를 짧게 알려 주는 작은 라벨. 테두리 없이 연한 채움과 색 글자로 구분해요. 기본은 누를 수 없는 라벨이고, 눌러서 무언가를 여는 상태 배지만 as="button"으로 만들어요. 필터나 선택에는 FilterChip을 쓰세요.
6
+
7
+ ```tsx
8
+ import { Badge } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 진행 중 배지는 `Badge spinner`, 실시간은 `Badge pulse`, 눌러서 여는 상태 배지는 `Badge as="button" chevron`, 아주 작은 대문자 태그는 `Badge overline`.
14
+ - 제목 · 아이콘 옆 개수 원은 `CountBadge`(tone · `max` "99+" · 바뀌면 튀기). 글자가 있는 상태 라벨은 `Badge`.
15
+
16
+ ## API
17
+
18
+ ### Badge
19
+
20
+ | prop | 타입 | 기본값 | 설명 |
21
+ | --- | --- | --- | --- |
22
+ | `tone` | `'neutral' \| 'accent' \| 'success' \| 'warning' \| 'danger' \| 'info'` | `'neutral'` | 색. |
23
+ | `dot` | `boolean` | | 글자 앞 상태 점. |
24
+ | `pulse` | `boolean` | | 점이 퍼지며 깜박여요(실시간 · 진행 중). dot을 포함해요. |
25
+ | `spinner` | `boolean` | | 글자 앞 작은 Spinner. dot · icon 대신 보여요. |
26
+ | `square` | `boolean` | | 덜 둥근 모서리. |
27
+ | `icon` | `ReactNode` | | 글자 앞 아이콘. |
28
+ | `iconRight` | `ReactNode` | | 글자 뒤 아이콘. |
29
+ | `chevron` | `boolean` | | 맨 뒤 오른쪽 화살표. 보통 as="button"과 함께. |
30
+ | `size` | `'sm' \| 'md'` | `'md'` | md 22px · sm 18px. |
31
+ | `overline` | `boolean` | | 대문자 오버라인 글자의 작은 태그. |
32
+ | `as` | `'span' \| 'button'` | `'span'` | 'button'이면 누를 수 있어요(onClick, disabled). |
33
+ | `disabled` | `boolean` | | as="button"일 때 비활성. |
34
+ | `children` | `ReactNode` | | 내용. |
35
+ | `...rest` | `HTMLAttributes` | | className · style · onClick · aria-* 등은 루트 요소로 전달돼요. |
36
+
37
+ ## 예제
38
+
39
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
40
+
41
+ ### 색
42
+
43
+ neutral은 회색, 나머지는 상태색의 연한 배경 + 진한 글자예요.
44
+
45
+ ```tsx
46
+ import { Badge } from '@iamfiro/design'
47
+
48
+ export default function Example() {
49
+ return (
50
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
51
+ <Badge>초안</Badge>
52
+ <Badge tone="accent">신규</Badge>
53
+ <Badge tone="success">완료</Badge>
54
+ <Badge tone="warning">대기 중</Badge>
55
+ <Badge tone="danger">실패</Badge>
56
+ <Badge tone="info">베타</Badge>
57
+ </div>
58
+ )
59
+ }
60
+ ```
61
+
62
+ ### 상태 점
63
+
64
+ dot은 글자 앞에 작은 점을 붙여요. 목록에서 상태를 한눈에 훑을 때 좋아요.
65
+
66
+ ```tsx
67
+ import { Badge, Text, type Tone } from '@iamfiro/design'
68
+
69
+ const DEPLOYS: Array<{ branch: string; status: string; tone: Tone }> = [
70
+ { branch: 'main', status: '운영 중', tone: 'success' },
71
+ { branch: 'feat/checkout', status: '빌드 중', tone: 'info' },
72
+ { branch: 'fix/login-redirect', status: '검토 대기', tone: 'warning' },
73
+ { branch: 'chore/deps', status: '실패', tone: 'danger' },
74
+ ]
75
+
76
+ export default function Example() {
77
+ return (
78
+ <div style={{ display: 'grid', gridTemplateColumns: 'auto auto', gap: '12px 24px', alignItems: 'center', justifyContent: 'start' }}>
79
+ {DEPLOYS.map((d) => (
80
+ <div key={d.branch} style={{ display: 'contents' }}>
81
+ <Text variant="code">{d.branch}</Text>
82
+ <Badge tone={d.tone} dot>
83
+ {d.status}
84
+ </Badge>
85
+ </div>
86
+ ))}
87
+ </div>
88
+ )
89
+ }
90
+ ```
91
+
92
+ ### 진행 표시
93
+
94
+ spinner는 아직 돌아가는 일, pulse는 지금 살아 있는 것(점이 퍼지며 깜박여요), icon은 끝난 · 기다리는 상태에 써요.
95
+
96
+ ```tsx
97
+ import { Check, Clock } from 'lucide-react'
98
+ import { Badge, Inline } from '@iamfiro/design'
99
+
100
+ export default function Example() {
101
+ return (
102
+ <Inline gap={2}>
103
+ <Badge tone="info" spinner>
104
+ 배포 중
105
+ </Badge>
106
+ <Badge tone="info" pulse>
107
+ 실시간
108
+ </Badge>
109
+ <Badge tone="success" icon={<Check />}>
110
+ 완료
111
+ </Badge>
112
+ <Badge tone="warning" icon={<Clock />}>
113
+ 승인 대기
114
+ </Badge>
115
+ <Badge tone="danger" dot>
116
+ 실패
117
+ </Badge>
118
+ </Inline>
119
+ )
120
+ }
121
+ ```
122
+
123
+ ### 누를 수 있는 배지
124
+
125
+ as="button"이면 hover 채움 · 누름 · 포커스 링이 생겨요. chevron은 눌러서 무언가 열린다는 힌트예요.
126
+
127
+ ```tsx
128
+ import { useState } from 'react'
129
+ import { Clock } from 'lucide-react'
130
+ import { Badge, Inline, Text } from '@iamfiro/design'
131
+
132
+ export default function Example() {
133
+ const [opened, setOpened] = useState(0)
134
+ return (
135
+ <Inline gap={3}>
136
+ <Badge as="button" tone="warning" icon={<Clock />} chevron onClick={() => setOpened((n) => n + 1)}>
137
+ 검토 필요 2건
138
+ </Badge>
139
+ <Badge as="button" tone="info" spinner chevron onClick={() => setOpened((n) => n + 1)}>
140
+ 빌드 중
141
+ </Badge>
142
+ <Badge as="button" chevron disabled>
143
+ 권한 없음
144
+ </Badge>
145
+ <Text variant="caption" tone="tertiary" numeric>
146
+ {opened > 0 ? `${opened}번 열었어요` : '배지를 눌러 보세요'}
147
+ </Text>
148
+ </Inline>
149
+ )
150
+ }
151
+ ```
152
+
153
+ ### 크기 · 오버라인
154
+
155
+ size="sm"은 18px로 촘촘한 행 · 제목 옆에, overline은 대문자 오버라인 역할의 아주 작은 태그예요.
156
+
157
+ ```tsx
158
+ import { Badge, Heading, Inline, Stack, Text } from '@iamfiro/design'
159
+
160
+ export default function Example() {
161
+ return (
162
+ <Stack gap={4}>
163
+ <Inline gap={2}>
164
+ <Badge tone="success">기본 22px</Badge>
165
+ <Badge tone="success" size="sm">
166
+ 작게 18px
167
+ </Badge>
168
+ <Badge tone="info" size="sm" pulse>
169
+ 실시간
170
+ </Badge>
171
+ </Inline>
172
+ <Inline gap={2}>
173
+ <Heading level={4}>결제 단계</Heading>
174
+ <Badge tone="warning" overline>
175
+ Slowest
176
+ </Badge>
177
+ <Badge tone="accent" overline>
178
+ Beta
179
+ </Badge>
180
+ </Inline>
181
+ <Inline gap={2}>
182
+ <Text variant="label-sm">응답 시간 1.8초</Text>
183
+ <Badge overline>p95</Badge>
184
+ </Inline>
185
+ </Stack>
186
+ )
187
+ }
188
+ ```
189
+
190
+ ### 각진 모양 · 아이콘
191
+
192
+ square는 모서리를 줄여 버전 · 코드 같은 값에 어울려요. icon은 글자 앞에 붙어요.
193
+
194
+ ```tsx
195
+ import { Lock, Sparkles, Star } from 'lucide-react'
196
+ import { Badge } from '@iamfiro/design'
197
+
198
+ export default function Example() {
199
+ return (
200
+ <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 8 }}>
201
+ <Badge square>v2.4.0</Badge>
202
+ <Badge tone="info" square>
203
+ API
204
+ </Badge>
205
+ <Badge tone="accent" icon={<Sparkles />}>
206
+ AI 추천
207
+ </Badge>
208
+ <Badge tone="warning" icon={<Star />}>
209
+ 즐겨찾기
210
+ </Badge>
211
+ <Badge icon={<Lock />} square>
212
+ 비공개
213
+ </Badge>
214
+ </div>
215
+ )
216
+ }
217
+ ```