@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,212 @@
1
+ # Alert · Banner
2
+
3
+ > 알림 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 토스트와 달리 화면에 머무르는 메시지. Alert는 폼 오류 · 한도 · 요금제 안내처럼 내용 옆에, Banner는 점검 · 체험 종료 · 새 버전처럼 화면 맨 위에 둬요. 테두리 없이 연한 배경으로 구분하고, 닫으면 접히듯 사라져요.
6
+
7
+ ```tsx
8
+ import { Alert, Banner } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### Alert
14
+
15
+ | prop | 타입 | 기본값 | 설명 |
16
+ | --- | --- | --- | --- |
17
+ | `tone` | `'neutral' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'info'` | 색과 기본 아이콘. |
18
+ | `title` | `ReactNode` | | 굵은 첫 줄. |
19
+ | `children` | `ReactNode` | | 본문. |
20
+ | `icon` | `ReactNode \| false` | | 아이콘을 바꾸거나 false로 숨겨요. |
21
+ | `actions` | `ReactNode` | | 버튼들. stacked면 본문 아래, inline이면 오른쪽. |
22
+ | `onClose` | `() => void` | | × 버튼을 보여주고, 접히는 애니메이션이 끝나면 불려요. |
23
+ | `layout` | `'stacked' \| 'inline'` | `'stacked'` | stacked: 액션이 본문 아래 · inline: 한 줄, 액션은 오른쪽. |
24
+ | `className` | `string` | | 알림 요소에 전달. |
25
+
26
+ ### Banner
27
+
28
+ | prop | 타입 | 기본값 | 설명 |
29
+ | --- | --- | --- | --- |
30
+ | `children` (필수) | `ReactNode` | | 메시지. |
31
+ | `tone` | `'neutral' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'info'` | 색과 기본 아이콘. |
32
+ | `action` | `ReactNode` | | 메시지 뒤 버튼 하나. |
33
+ | `onClose` | `() => void` | | × 버튼을 보여주고, 접히는 애니메이션이 끝나면 불려요. |
34
+ | `icon` | `ReactNode \| false` | | 아이콘을 바꾸거나 false로 숨겨요. |
35
+ | `className` | `string` | | 배너 요소에 전달. |
36
+
37
+ ## 예제
38
+
39
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
40
+
41
+ ### 톤
42
+
43
+ neutral · info · success · warning · danger. 톤마다 기본 아이콘이 있고, warning · danger는 role="alert"로 바로 읽혀요.
44
+
45
+ ```tsx
46
+ import { Stack, Alert } from '@iamfiro/design'
47
+
48
+ export default function Example() {
49
+ return (
50
+ <Stack gap={3} style={{ width: 480 }}>
51
+ <Alert tone="neutral">변경 사항은 자동으로 저장돼요.</Alert>
52
+ <Alert tone="info">새 대시보드가 10월 28일부터 기본으로 켜져요.</Alert>
53
+ <Alert tone="success">결제 수단이 등록됐어요.</Alert>
54
+ <Alert tone="warning">저장 공간을 90% 사용했어요.</Alert>
55
+ <Alert tone="danger">카드 승인이 거절됐어요. 다른 카드로 다시 시도해 주세요.</Alert>
56
+ </Stack>
57
+ )
58
+ }
59
+ ```
60
+
61
+ ### 제목과 액션
62
+
63
+ title로 요점을 먼저 쓰고, actions에 다음 행동 버튼을 둬요. icon으로 아이콘을 바꾸거나 false로 숨겨요.
64
+
65
+ ```tsx
66
+ import { ShieldCheck } from 'lucide-react'
67
+ import { Button, Stack, Alert } from '@iamfiro/design'
68
+
69
+ export default function Example() {
70
+ return (
71
+ <Stack gap={3} style={{ width: 480 }}>
72
+ <Alert
73
+ tone="warning"
74
+ title="이번 달 API 호출 한도에 가까워요"
75
+ actions={
76
+ <>
77
+ <Button variant="primary" size="sm">
78
+ 요금제 올리기
79
+ </Button>
80
+ <Button variant="ghost" size="sm">
81
+ 사용량 보기
82
+ </Button>
83
+ </>
84
+ }
85
+ >
86
+ 10월 31일까지 남은 호출은 1,240회예요. 한도를 넘으면 요청이 잠시 거절돼요.
87
+ </Alert>
88
+ <Alert
89
+ tone="neutral"
90
+ icon={<ShieldCheck />}
91
+ title="2단계 인증을 켜 주세요"
92
+ actions={
93
+ <Button size="sm">
94
+ 지금 설정
95
+ </Button>
96
+ }
97
+ >
98
+ 조직 관리자가 11월 1일부터 모든 멤버에게 2단계 인증을 요구해요.
99
+ </Alert>
100
+ <Alert tone="info" icon={false}>
101
+ 아이콘 없이 텍스트만 보여줄 수도 있어요.
102
+ </Alert>
103
+ </Stack>
104
+ )
105
+ }
106
+ ```
107
+
108
+ ### 한 줄 배치
109
+
110
+ layout="inline"이면 액션이 오른쪽에 붙어 한 줄로 끝나요.
111
+
112
+ ```tsx
113
+ import { Button, Stack, Alert } from '@iamfiro/design'
114
+
115
+ export default function Example() {
116
+ return (
117
+ <Stack gap={3} style={{ width: 560 }}>
118
+ <Alert tone="info" layout="inline" actions={<Button size="sm">새로고침</Button>}>
119
+ 새 버전이 배포됐어요.
120
+ </Alert>
121
+ <Alert tone="danger" layout="inline" title="동기화 실패" actions={<Button size="sm">다시 시도</Button>}>
122
+ 2분 전부터 Google Drive와 연결되지 않아요.
123
+ </Alert>
124
+ </Stack>
125
+ )
126
+ }
127
+ ```
128
+
129
+ ### 닫기
130
+
131
+ onClose를 주면 × 버튼이 생겨요. 접히는 애니메이션이 끝난 뒤 onClose가 불리니, 그때 상태에서 지우세요.
132
+
133
+ ```tsx
134
+ import { useState } from 'react'
135
+ import { RotateCcw } from 'lucide-react'
136
+ import { Button, Inline, Stack, Alert, type AlertTone } from '@iamfiro/design'
137
+
138
+ const NOTICES: Array<{ id: string; tone: AlertTone; title: string; body: string }> = [
139
+ { id: 'invite', tone: 'success', title: '초대를 보냈어요', body: '박서연님이 수락하면 알려 드릴게요.' },
140
+ { id: 'export', tone: 'info', title: '내보내기를 준비하고 있어요', body: '완료되면 minji@lumen.app으로 링크를 보내 드려요.' },
141
+ { id: 'billing', tone: 'warning', title: '결제 정보를 확인해 주세요', body: '등록된 카드가 11월에 만료돼요.' },
142
+ ]
143
+
144
+ const ALL = NOTICES.map((n) => n.id)
145
+
146
+ export default function Example() {
147
+ const [visible, setVisible] = useState(ALL)
148
+ return (
149
+ <Stack gap={3} style={{ width: 480 }}>
150
+ {NOTICES.filter((n) => visible.includes(n.id)).map((n) => (
151
+ <Alert key={n.id} tone={n.tone} title={n.title} onClose={() => setVisible((v) => v.filter((id) => id !== n.id))}>
152
+ {n.body}
153
+ </Alert>
154
+ ))}
155
+ <Inline>
156
+ <Button variant="secondary" size="sm" icon={<RotateCcw />} disabled={visible.length === ALL.length} onClick={() => setVisible(ALL)}>
157
+ 다시 보기
158
+ </Button>
159
+ </Inline>
160
+ </Stack>
161
+ )
162
+ }
163
+ ```
164
+
165
+ ### Banner
166
+
167
+ 앱이나 카드 맨 위의 가로 띠. 액션 하나와 닫기를 둘 수 있어요.
168
+
169
+ ```tsx
170
+ import { useState } from 'react'
171
+ import { RotateCcw, Wrench } from 'lucide-react'
172
+ import { Box, Button, Stack, Text, Banner, Card } from '@iamfiro/design'
173
+
174
+ export default function Example() {
175
+ const [trial, setTrial] = useState(true)
176
+ return (
177
+ <Stack gap={6} align="start">
178
+ <Card padding="none" style={{ width: 520, overflow: 'hidden' }}>
179
+ {trial && (
180
+ <Banner
181
+ tone="warning"
182
+ action={
183
+ <Button variant="ghost" size="sm">
184
+ 요금제 보기
185
+ </Button>
186
+ }
187
+ onClose={() => setTrial(false)}
188
+ >
189
+ 무료 체험이 3일 남았어요.
190
+ </Banner>
191
+ )}
192
+ <Box padding={5}>
193
+ <Stack gap={1}>
194
+ <Text variant="heading-sm">대시보드</Text>
195
+ <Text variant="body-sm" tone="secondary">
196
+ 10월 25일 기준 이번 주 방문자는 8,903명이에요.
197
+ </Text>
198
+ </Stack>
199
+ </Box>
200
+ </Card>
201
+ <Button variant="secondary" size="sm" icon={<RotateCcw />} disabled={trial} onClick={() => setTrial(true)}>
202
+ 다시 보기
203
+ </Button>
204
+ <Box radius="md" style={{ width: 520, overflow: 'hidden' }}>
205
+ <Banner tone="neutral" icon={<Wrench />}>
206
+ 10월 27일 새벽 2시부터 30분간 점검이 있어요.
207
+ </Banner>
208
+ </Box>
209
+ </Stack>
210
+ )
211
+ }
212
+ ```
@@ -0,0 +1,193 @@
1
+ # AlertDialog
2
+
3
+ > 메뉴 & 오버레이 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 되돌릴 수 없는 작업(영구 삭제, 결제, 대량 발송) 바로 앞에 한 번 더 묻는 확인 창. 버튼에는 "확인" 대신 동작 이름("삭제", "보내기")을 써요. 되돌릴 수 있는 작업(휴지통으로 이동, 보관, 옮기기)이라면 확인 창을 띄우지 말고 바로 실행한 뒤 toast.undo(제목, { onUndo, onCommit })로 "실행 취소"를 보여 주세요 — 실제 영구 처리는 onCommit에서 해요.
6
+
7
+ ```tsx
8
+ import { AlertDialog } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 되돌릴 수 없는 작업의 확인은 `AlertDialog`: 버튼에 동작 이름, 위험하면 포커스는 "취소"에서 시작, 비동기면 진행 중 잠금·실패 시 열린 채 오류 표시, 가장 위험하면 이름 입력 확인(`confirmationText`).
14
+
15
+ ## API
16
+
17
+ ### AlertDialog
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `title` (필수) | `ReactNode` | | 질문 형태의 제목. 예: "대화 기록을 삭제할까요?" |
22
+ | `description` | `ReactNode` | | 무엇이 어떻게 되는지, 되돌릴 수 있는지. |
23
+ | `confirmLabel` (필수) | `ReactNode` | | 확인 버튼 문구. 동작 이름을 쓰세요("삭제", "29,000원 결제"). |
24
+ | `onConfirm` (필수) | `() => void \| Promise<void>` | | Promise면 끝날 때까지 로딩·잠금. 던진 Error의 message가 창 안에 표시되고 창은 열린 채 남아요. |
25
+ | `tone` | `'default' \| 'danger'` | `'default'` | danger: 경고 아이콘 + 빨간 버튼 + 취소에 첫 포커스. |
26
+ | `cancelLabel` | `ReactNode` | `'취소'` | 취소 버튼 문구. |
27
+ | `confirmationText` | `string` | | 이 글자를 정확히 입력해야 확인 버튼이 켜져요(예: 프로젝트 이름). |
28
+ | `children` | `ReactNode` | | 설명 아래 추가 내용(삭제될 항목, 결제 내역 등). |
29
+ | `trigger` | `ReactElement` | | 누르면 여는 버튼. |
30
+ | `open / onOpenChange` | `boolean / (open) => void` | | 열림 상태를 밖에서 제어할 때(메뉴 항목에서 열 때 등). |
31
+ | `defaultOpen` | `boolean` | `false` | 처음 열림 상태(비제어). |
32
+
33
+ ## 예제
34
+
35
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
36
+
37
+ ### 위험한 작업
38
+
39
+ tone="danger"면 경고 아이콘과 빨간 버튼이 붙고, 포커스가 "취소"에서 시작해 Enter를 눌러도 아무것도 지워지지 않아요.
40
+
41
+ ```tsx
42
+ import { Trash2 } from 'lucide-react'
43
+ import { Button, AlertDialog, toast } from '@iamfiro/design'
44
+
45
+ export default function Example() {
46
+ return (
47
+ <AlertDialog
48
+ tone="danger"
49
+ trigger={
50
+ <Button variant="danger" icon={<Trash2 />}>
51
+ 대화 기록 삭제
52
+ </Button>
53
+ }
54
+ title="대화 기록을 모두 삭제할까요?"
55
+ description="지난 90일 동안의 대화 312개가 영구 삭제돼요. 삭제한 기록은 되돌릴 수 없어요."
56
+ confirmLabel="삭제"
57
+ onConfirm={() => {
58
+ toast.success('대화 기록을 삭제했어요')
59
+ }}
60
+ />
61
+ )
62
+ }
63
+ ```
64
+
65
+ ### 비동기 확인
66
+
67
+ onConfirm이 Promise를 돌려주면 버튼이 돌아가고 끝날 때까지 창이 잠겨요(Esc·바깥 클릭·취소 불가). 성공하면 닫히고, 오류를 던지면 열린 채 그 메시지를 보여 줘서 바로 다시 시도할 수 있어요. 두 번째 버튼은 실패하는 경우예요.
68
+
69
+ ```tsx
70
+ import { Send } from 'lucide-react'
71
+ import { Button, Inline, AlertDialog, toast } from '@iamfiro/design'
72
+
73
+ const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
74
+
75
+ async function sendNotice() {
76
+ await wait(1500)
77
+ toast.success('공지를 248명에게 보냈어요')
78
+ }
79
+
80
+ async function sendNoticeOffline() {
81
+ await wait(1500)
82
+ throw new Error('네트워크 연결이 끊겼어요. 연결을 확인하고 다시 시도해 주세요.')
83
+ }
84
+
85
+ export default function Example() {
86
+ return (
87
+ <Inline gap={2}>
88
+ <AlertDialog
89
+ trigger={<Button icon={<Send />}>공지 보내기</Button>}
90
+ title="전체 멤버에게 공지를 보낼까요?"
91
+ description="248명에게 메일과 앱 알림이 바로 발송돼요. 보낸 뒤에는 취소할 수 없어요."
92
+ confirmLabel="보내기"
93
+ onConfirm={sendNotice}
94
+ />
95
+ <AlertDialog
96
+ trigger={<Button icon={<Send />}>공지 보내기 (실패)</Button>}
97
+ title="전체 멤버에게 공지를 보낼까요?"
98
+ description="248명에게 메일과 앱 알림이 바로 발송돼요. 보낸 뒤에는 취소할 수 없어요."
99
+ confirmLabel="보내기"
100
+ onConfirm={sendNoticeOffline}
101
+ />
102
+ </Inline>
103
+ )
104
+ }
105
+ ```
106
+
107
+ ### 이름 입력 확인
108
+
109
+ 가장 위험한 작업은 confirmationText를 정확히 입력해야 버튼이 켜져요. 열리면 입력칸에 바로 포커스가 가요. children으로 함께 사라지는 것을 보여 주세요.
110
+
111
+ ```tsx
112
+ import { Trash2 } from 'lucide-react'
113
+ import { Button, Stack, Text, AlertDialog, toast } from '@iamfiro/design'
114
+
115
+ const PROJECT = 'lumen-web'
116
+
117
+ const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
118
+
119
+ export default function Example() {
120
+ return (
121
+ <AlertDialog
122
+ tone="danger"
123
+ trigger={
124
+ <Button variant="danger" icon={<Trash2 />}>
125
+ 프로젝트 삭제
126
+ </Button>
127
+ }
128
+ title="프로젝트를 영구 삭제할까요?"
129
+ description="이 작업은 되돌릴 수 없어요."
130
+ confirmationText={PROJECT}
131
+ confirmLabel="프로젝트 삭제"
132
+ onConfirm={async () => {
133
+ await wait(1200)
134
+ toast.success(`${PROJECT} 프로젝트를 삭제했어요`)
135
+ }}
136
+ >
137
+ <Stack gap={1}>
138
+ <Text variant="body-sm" tone="secondary">
139
+ 함께 삭제되는 항목
140
+ </Text>
141
+ <Text variant="body-md">배포 128개 · 환경 변수 24개 · 연결된 도메인 2개</Text>
142
+ </Stack>
143
+ </AlertDialog>
144
+ )
145
+ }
146
+ ```
147
+
148
+ ### 기본 톤
149
+
150
+ 파괴적이지 않지만 되돌리기 어려운 작업(결제 등)은 기본 톤을 써요. 검정 버튼에 포커스가 가서 Enter로 바로 진행할 수 있어요.
151
+
152
+ ```tsx
153
+ import { CreditCard } from 'lucide-react'
154
+ import { Button, Inline, Stack, Text, AlertDialog, toast } from '@iamfiro/design'
155
+
156
+ const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
157
+
158
+ export default function Example() {
159
+ return (
160
+ <AlertDialog
161
+ trigger={
162
+ <Button variant="primary" icon={<CreditCard />}>
163
+ 팀 플랜으로 업그레이드
164
+ </Button>
165
+ }
166
+ title="팀 플랜을 결제할까요?"
167
+ description="등록된 카드로 바로 결제되고, 다음 달부터 매월 11월 25일에 자동 결제돼요."
168
+ confirmLabel="29,000원 결제"
169
+ onConfirm={async () => {
170
+ await wait(1200)
171
+ toast.success('팀 플랜을 시작했어요')
172
+ }}
173
+ >
174
+ <Stack gap={2}>
175
+ <Inline justify="between">
176
+ <Text variant="body-md" tone="secondary">
177
+ 팀 플랜 · 월간
178
+ </Text>
179
+ <Text variant="body-md" numeric>
180
+ 29,000원
181
+ </Text>
182
+ </Inline>
183
+ <Inline justify="between">
184
+ <Text variant="body-md" tone="secondary">
185
+ 결제 카드
186
+ </Text>
187
+ <Text variant="body-md">신한카드 ···· 4021</Text>
188
+ </Inline>
189
+ </Stack>
190
+ </AlertDialog>
191
+ )
192
+ }
193
+ ```