@iamfiro/design 0.0.0-stage → 0.3.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 (416) hide show
  1. package/AGENTS.md +82 -0
  2. package/README.md +15 -2
  3. package/agents/INDEX.md +157 -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/social-login-button/AGENTS.md +156 -0
  90. package/agents/spark-chart/AGENTS.md +257 -0
  91. package/agents/sparkbar/AGENTS.md +92 -0
  92. package/agents/spinner/AGENTS.md +123 -0
  93. package/agents/split-view/AGENTS.md +290 -0
  94. package/agents/stat/AGENTS.md +138 -0
  95. package/agents/status-icon/AGENTS.md +243 -0
  96. package/agents/step-list/AGENTS.md +313 -0
  97. package/agents/table/AGENTS.md +286 -0
  98. package/agents/tabs/AGENTS.md +305 -0
  99. package/agents/tag-input/AGENTS.md +246 -0
  100. package/agents/time-picker/AGENTS.md +228 -0
  101. package/agents/timeline/AGENTS.md +1018 -0
  102. package/agents/toast/AGENTS.md +266 -0
  103. package/agents/toggle-group/AGENTS.md +216 -0
  104. package/agents/toolbar/AGENTS.md +277 -0
  105. package/agents/tooltip/AGENTS.md +154 -0
  106. package/agents/tracker/AGENTS.md +158 -0
  107. package/agents/tree-diagram/AGENTS.md +260 -0
  108. package/agents/tree-view/AGENTS.md +329 -0
  109. package/agents/typography/AGENTS.md +396 -0
  110. package/lib/components/Accordion/Accordion2.js +135 -0
  111. package/lib/components/ActionBar/ActionBar2.js +65 -0
  112. package/lib/components/Alert/Alert2.js +131 -0
  113. package/lib/components/AppShell/AppShell2.js +94 -0
  114. package/lib/components/AreaChart/AreaChart.js +59 -0
  115. package/lib/components/BarChart/BarChart2.js +243 -0
  116. package/lib/components/BarList/BarList2.js +172 -0
  117. package/lib/components/Breadcrumb/Breadcrumb2.js +87 -0
  118. package/lib/components/Calendar/Calendar2.js +309 -0
  119. package/lib/components/Calendar/DatePicker2.js +229 -0
  120. package/lib/components/Calendar/date.js +121 -0
  121. package/lib/components/Card/Card2.js +104 -0
  122. package/lib/components/CardFrame/CardFrame2.js +72 -0
  123. package/lib/components/Chart/ChartParts.js +150 -0
  124. package/lib/components/Chart/chart2.js +96 -0
  125. package/lib/components/Chart/useChartInteraction.js +94 -0
  126. package/lib/components/ChatBubble/ChatBubble2.js +174 -0
  127. package/lib/components/ChatBubble/formatChatTime.js +53 -0
  128. package/lib/components/ChatComposer/ChatComposer2.js +153 -0
  129. package/lib/components/CodeBlock/CodeBlock2.js +93 -0
  130. package/lib/components/CodeBlock/highlight.js +114 -0
  131. package/lib/components/ColorPicker/ColorPicker2.js +610 -0
  132. package/lib/components/ColorPicker/color.js +180 -0
  133. package/lib/components/ColorPicker/presets.js +75 -0
  134. package/lib/components/Combobox/Combobox2.js +229 -0
  135. package/lib/components/CommandMenu/CommandMenu.js +267 -0
  136. package/lib/components/Comment/Comment2.js +134 -0
  137. package/lib/components/ContextMenu/ContextMenu2.js +168 -0
  138. package/lib/components/DataGrid/DataGrid2.js +1996 -0
  139. package/lib/components/DataGrid/GridPopover.js +154 -0
  140. package/lib/components/DataGrid/anchor.js +50 -0
  141. package/lib/components/DataGrid/model.js +558 -0
  142. package/lib/components/DataGrid/panels.js +703 -0
  143. package/lib/components/DataGrid/typeMeta.js +76 -0
  144. package/lib/components/DataGrid/types.js +54 -0
  145. package/lib/components/DescriptionList/DescriptionList2.js +180 -0
  146. package/lib/components/Dialog/AlertDialog.js +118 -0
  147. package/lib/components/Dialog/Dialog2.js +109 -0
  148. package/lib/components/Dialog/modal.js +92 -0
  149. package/lib/components/Drawer/Drawer2.js +244 -0
  150. package/lib/components/DropdownMenu/DropdownMenu2.js +394 -0
  151. package/lib/components/DropdownMenu/menuCore.js +63 -0
  152. package/lib/components/Dropzone/Dropzone2.js +144 -0
  153. package/lib/components/EmptyState/EmptyState2.js +72 -0
  154. package/lib/components/FileChip/FileChip2.js +118 -0
  155. package/lib/components/FileUpload/FileUpload.js +258 -0
  156. package/lib/components/FilterChips/FilterChips2.js +101 -0
  157. package/lib/components/FunnelChart/FunnelChart2.js +283 -0
  158. package/lib/components/FunnelChart/funnel.js +69 -0
  159. package/lib/components/Highlight/Highlight2.js +100 -0
  160. package/lib/components/HoverCard/HoverCard.js +134 -0
  161. package/lib/components/InlineDiff/InlineDiff2.js +215 -0
  162. package/lib/components/InlineDiff/diff.js +126 -0
  163. package/lib/components/InlineDiff/useDiffReview.js +109 -0
  164. package/lib/components/Kanban/Kanban2.js +691 -0
  165. package/lib/components/Kanban/KanbanCard.js +159 -0
  166. package/lib/components/Kanban/move.js +69 -0
  167. package/lib/components/LineChart/LineChart2.js +342 -0
  168. package/lib/components/List/List2.js +133 -0
  169. package/lib/components/Listbox/Listbox2.js +163 -0
  170. package/lib/components/Marker/Marker2.js +82 -0
  171. package/lib/components/Menubar/Menubar2.js +223 -0
  172. package/lib/components/MultiSelect/MultiSelect2.js +204 -0
  173. package/lib/components/NavigationMenu/NavigationMenu2.js +481 -0
  174. package/lib/components/NoticeStack/NoticeStack2.js +178 -0
  175. package/lib/components/NumberStepper/NumberStepper2.js +129 -0
  176. package/lib/components/OtpInput/OtpInput2.js +122 -0
  177. package/lib/components/Pagination/Pagination2.js +210 -0
  178. package/lib/components/Pagination/paginationRange.js +53 -0
  179. package/lib/components/PhoneInput/PhoneInput.js +175 -0
  180. package/lib/components/PieChart/PieChart2.js +246 -0
  181. package/lib/components/PieChart/arc.js +66 -0
  182. package/lib/components/PieChart/useArcTween.js +94 -0
  183. package/lib/components/Popover/Popover2.js +112 -0
  184. package/lib/components/ProgressTracker/ProgressTracker2.js +226 -0
  185. package/lib/components/Rating/Rating2.js +186 -0
  186. package/lib/components/Resizable/Resizable2.js +236 -0
  187. package/lib/components/Resizable/layout.js +115 -0
  188. package/lib/components/ScaledPreview/ScaledPreview2.js +100 -0
  189. package/lib/components/ScatterChart/ScatterChart2.js +356 -0
  190. package/lib/components/ScatterChart/scatter.js +83 -0
  191. package/lib/components/ScrollArea/ScrollArea2.js +218 -0
  192. package/lib/components/Select/Select2.js +153 -0
  193. package/lib/components/Sidebar/Sidebar2.js +127 -0
  194. package/lib/components/Skeleton/Skeleton2.js +91 -0
  195. package/lib/components/Slider/Slider2.js +142 -0
  196. package/lib/components/SocialLoginButton/SocialLoginButton.js +85 -0
  197. package/lib/components/SparkChart/SparkChart2.js +217 -0
  198. package/lib/components/SparkChart/spark.js +76 -0
  199. package/lib/components/Sparkbar/Sparkbar2.js +111 -0
  200. package/lib/components/SplitView/SplitView2.js +95 -0
  201. package/lib/components/Stat/Stat2.js +164 -0
  202. package/lib/components/StepList/StepList2.js +131 -0
  203. package/lib/components/Table/Table2.js +104 -0
  204. package/lib/components/Tabs/Tabs2.js +131 -0
  205. package/lib/components/TagInput/TagInput2.js +360 -0
  206. package/lib/components/TimePicker/TimePicker2.js +388 -0
  207. package/lib/components/TimePicker/time.js +83 -0
  208. package/lib/components/Timeline/Timeline2.js +369 -0
  209. package/lib/components/Timeline/scale.js +83 -0
  210. package/lib/components/Toast/Toaster.js +212 -0
  211. package/lib/components/Toast/store.js +129 -0
  212. package/lib/components/ToggleGroup/ToggleGroup2.js +125 -0
  213. package/lib/components/Toolbar/Toolbar2.js +281 -0
  214. package/lib/components/Tracker/Tracker2.js +172 -0
  215. package/lib/components/TreeDiagram/TreeDiagram2.js +223 -0
  216. package/lib/components/TreeView/TreeView2.js +284 -0
  217. package/lib/hooks/timing.js +55 -0
  218. package/lib/hooks/useControllableState.js +49 -0
  219. package/lib/hooks/useCountdown.js +80 -0
  220. package/lib/hooks/useDigitInput.js +105 -0
  221. package/lib/hooks/useDismiss.js +71 -0
  222. package/lib/hooks/useElapsed.js +83 -0
  223. package/lib/hooks/useFloating.js +70 -0
  224. package/lib/hooks/useFocusTrap.js +61 -0
  225. package/lib/hooks/usePresence.js +60 -0
  226. package/lib/hooks/usePressToOpen.js +69 -0
  227. package/lib/hooks/useScrollLock.js +70 -0
  228. package/lib/hooks/useSelection.js +68 -0
  229. package/lib/index.js +178 -0
  230. package/lib/primitives/AspectRatio2.js +80 -0
  231. package/lib/primitives/BrandIcon.js +245 -0
  232. package/lib/primitives/ColorDot2.js +70 -0
  233. package/lib/primitives/CopyButton2.js +85 -0
  234. package/lib/primitives/CountBadge2.js +78 -0
  235. package/lib/primitives/Countdown2.js +65 -0
  236. package/lib/primitives/Delta2.js +67 -0
  237. package/lib/primitives/Elapsed.js +62 -0
  238. package/lib/primitives/FileIcon2.js +125 -0
  239. package/lib/primitives/Flag2.js +263 -0
  240. package/lib/primitives/IconStack2.js +85 -0
  241. package/lib/primitives/IconTile2.js +68 -0
  242. package/lib/primitives/Kbd2.js +88 -0
  243. package/lib/primitives/Layout2.js +118 -0
  244. package/lib/primitives/Link2.js +53 -0
  245. package/lib/primitives/MaskedText2.js +120 -0
  246. package/lib/primitives/Progress2.js +137 -0
  247. package/lib/primitives/RelativeTime.js +84 -0
  248. package/lib/primitives/SearchInput2.js +84 -0
  249. package/lib/primitives/SelectorButton2.js +97 -0
  250. package/lib/primitives/Spinner2.js +98 -0
  251. package/lib/primitives/StatusIcon2.js +126 -0
  252. package/lib/primitives/Swatch2.js +79 -0
  253. package/lib/primitives/Tooltip2.js +132 -0
  254. package/lib/primitives/Typography2.js +97 -0
  255. package/lib/primitives/formatCountdown.js +51 -0
  256. package/lib/primitives/formatElapsed.js +66 -0
  257. package/lib/primitives/formatRelativeTime.js +64 -0
  258. package/lib/primitives/hotkey.js +94 -0
  259. package/lib/primitives/index.js +352 -0
  260. package/lib/primitives/maskValue.js +65 -0
  261. package/lib/style.css +2 -0
  262. package/lib/types/components/Accordion/Accordion.d.ts +57 -0
  263. package/lib/types/components/ActionBar/ActionBar.d.ts +24 -0
  264. package/lib/types/components/Alert/Alert.d.ts +36 -0
  265. package/lib/types/components/AppShell/AppShell.d.ts +38 -0
  266. package/lib/types/components/AreaChart/AreaChart.d.ts +17 -0
  267. package/lib/types/components/BarChart/BarChart.d.ts +57 -0
  268. package/lib/types/components/BarList/BarList.d.ts +56 -0
  269. package/lib/types/components/Breadcrumb/Breadcrumb.d.ts +15 -0
  270. package/lib/types/components/Calendar/Calendar.d.ts +34 -0
  271. package/lib/types/components/Calendar/DatePicker.d.ts +45 -0
  272. package/lib/types/components/Calendar/date.d.ts +32 -0
  273. package/lib/types/components/Card/Card.d.ts +64 -0
  274. package/lib/types/components/CardFrame/CardFrame.d.ts +15 -0
  275. package/lib/types/components/Chart/ChartParts.d.ts +38 -0
  276. package/lib/types/components/Chart/chart.d.ts +46 -0
  277. package/lib/types/components/Chart/useChartInteraction.d.ts +39 -0
  278. package/lib/types/components/ChatBubble/ChatBubble.d.ts +61 -0
  279. package/lib/types/components/ChatBubble/formatChatTime.d.ts +2 -0
  280. package/lib/types/components/ChatComposer/ChatComposer.d.ts +42 -0
  281. package/lib/types/components/CodeBlock/CodeBlock.d.ts +18 -0
  282. package/lib/types/components/CodeBlock/highlight.d.ts +10 -0
  283. package/lib/types/components/ColorPicker/ColorPicker.d.ts +61 -0
  284. package/lib/types/components/ColorPicker/color.d.ts +48 -0
  285. package/lib/types/components/ColorPicker/presets.d.ts +7 -0
  286. package/lib/types/components/Combobox/Combobox.d.ts +48 -0
  287. package/lib/types/components/CommandMenu/CommandMenu.d.ts +51 -0
  288. package/lib/types/components/Comment/Comment.d.ts +45 -0
  289. package/lib/types/components/ContextMenu/ContextMenu.d.ts +40 -0
  290. package/lib/types/components/DataGrid/DataGrid.d.ts +43 -0
  291. package/lib/types/components/DataGrid/GridPopover.d.ts +43 -0
  292. package/lib/types/components/DataGrid/anchor.d.ts +5 -0
  293. package/lib/types/components/DataGrid/model.d.ts +61 -0
  294. package/lib/types/components/DataGrid/panels.d.ts +63 -0
  295. package/lib/types/components/DataGrid/typeMeta.d.ts +6 -0
  296. package/lib/types/components/DataGrid/types.d.ts +77 -0
  297. package/lib/types/components/DescriptionList/DescriptionList.d.ts +77 -0
  298. package/lib/types/components/Dialog/AlertDialog.d.ts +26 -0
  299. package/lib/types/components/Dialog/Dialog.d.ts +42 -0
  300. package/lib/types/components/Dialog/modal.d.ts +38 -0
  301. package/lib/types/components/Drawer/Drawer.d.ts +62 -0
  302. package/lib/types/components/DropdownMenu/DropdownMenu.d.ts +97 -0
  303. package/lib/types/components/DropdownMenu/menuCore.d.ts +23 -0
  304. package/lib/types/components/Dropzone/Dropzone.d.ts +30 -0
  305. package/lib/types/components/EmptyState/EmptyState.d.ts +26 -0
  306. package/lib/types/components/FileChip/FileChip.d.ts +32 -0
  307. package/lib/types/components/FileUpload/FileUpload.d.ts +52 -0
  308. package/lib/types/components/FilterChips/FilterChips.d.ts +37 -0
  309. package/lib/types/components/FunnelChart/FunnelChart.d.ts +38 -0
  310. package/lib/types/components/FunnelChart/funnel.d.ts +25 -0
  311. package/lib/types/components/Highlight/Highlight.d.ts +35 -0
  312. package/lib/types/components/HoverCard/HoverCard.d.ts +47 -0
  313. package/lib/types/components/InlineDiff/InlineDiff.d.ts +36 -0
  314. package/lib/types/components/InlineDiff/diff.d.ts +42 -0
  315. package/lib/types/components/InlineDiff/useDiffReview.d.ts +57 -0
  316. package/lib/types/components/Kanban/Kanban.d.ts +64 -0
  317. package/lib/types/components/Kanban/KanbanCard.d.ts +35 -0
  318. package/lib/types/components/Kanban/move.d.ts +25 -0
  319. package/lib/types/components/LineChart/LineChart.d.ts +85 -0
  320. package/lib/types/components/List/List.d.ts +62 -0
  321. package/lib/types/components/Listbox/Listbox.d.ts +60 -0
  322. package/lib/types/components/Marker/Marker.d.ts +28 -0
  323. package/lib/types/components/Menubar/Menubar.d.ts +50 -0
  324. package/lib/types/components/MultiSelect/MultiSelect.d.ts +38 -0
  325. package/lib/types/components/NavigationMenu/NavigationMenu.d.ts +101 -0
  326. package/lib/types/components/NoticeStack/NoticeStack.d.ts +41 -0
  327. package/lib/types/components/NumberStepper/NumberStepper.d.ts +32 -0
  328. package/lib/types/components/OtpInput/OtpInput.d.ts +31 -0
  329. package/lib/types/components/Pagination/Pagination.d.ts +54 -0
  330. package/lib/types/components/Pagination/paginationRange.d.ts +7 -0
  331. package/lib/types/components/PhoneInput/PhoneInput.d.ts +47 -0
  332. package/lib/types/components/PieChart/PieChart.d.ts +67 -0
  333. package/lib/types/components/PieChart/arc.d.ts +26 -0
  334. package/lib/types/components/PieChart/useArcTween.d.ts +15 -0
  335. package/lib/types/components/Popover/Popover.d.ts +28 -0
  336. package/lib/types/components/ProgressTracker/ProgressTracker.d.ts +64 -0
  337. package/lib/types/components/Rating/Rating.d.ts +42 -0
  338. package/lib/types/components/Resizable/Resizable.d.ts +50 -0
  339. package/lib/types/components/Resizable/layout.d.ts +31 -0
  340. package/lib/types/components/ScaledPreview/ScaledPreview.d.ts +38 -0
  341. package/lib/types/components/ScatterChart/ScatterChart.d.ts +81 -0
  342. package/lib/types/components/ScatterChart/scatter.d.ts +14 -0
  343. package/lib/types/components/ScrollArea/ScrollArea.d.ts +34 -0
  344. package/lib/types/components/Select/Select.d.ts +39 -0
  345. package/lib/types/components/Sidebar/Sidebar.d.ts +39 -0
  346. package/lib/types/components/Skeleton/Skeleton.d.ts +47 -0
  347. package/lib/types/components/Slider/Slider.d.ts +36 -0
  348. package/lib/types/components/SocialLoginButton/SocialLoginButton.d.ts +10 -0
  349. package/lib/types/components/SparkChart/SparkChart.d.ts +55 -0
  350. package/lib/types/components/SparkChart/spark.d.ts +16 -0
  351. package/lib/types/components/Sparkbar/Sparkbar.d.ts +39 -0
  352. package/lib/types/components/SplitView/SplitView.d.ts +31 -0
  353. package/lib/types/components/Stat/Stat.d.ts +58 -0
  354. package/lib/types/components/StepList/StepList.d.ts +61 -0
  355. package/lib/types/components/Table/Table.d.ts +39 -0
  356. package/lib/types/components/Tabs/Tabs.d.ts +47 -0
  357. package/lib/types/components/TagInput/TagInput.d.ts +46 -0
  358. package/lib/types/components/TimePicker/TimePicker.d.ts +43 -0
  359. package/lib/types/components/TimePicker/time.d.ts +15 -0
  360. package/lib/types/components/Timeline/Timeline.d.ts +154 -0
  361. package/lib/types/components/Timeline/scale.d.ts +22 -0
  362. package/lib/types/components/Toast/Toaster.d.ts +19 -0
  363. package/lib/types/components/Toast/index.d.ts +4 -0
  364. package/lib/types/components/Toast/store.d.ts +75 -0
  365. package/lib/types/components/ToggleGroup/ToggleGroup.d.ts +28 -0
  366. package/lib/types/components/Toolbar/Toolbar.d.ts +70 -0
  367. package/lib/types/components/Tracker/Tracker.d.ts +43 -0
  368. package/lib/types/components/TreeDiagram/TreeDiagram.d.ts +68 -0
  369. package/lib/types/components/TreeView/TreeView.d.ts +107 -0
  370. package/lib/types/components/index.d.ts +188 -0
  371. package/lib/types/hooks/index.d.ts +17 -0
  372. package/lib/types/hooks/timing.d.ts +29 -0
  373. package/lib/types/hooks/useControllableState.d.ts +5 -0
  374. package/lib/types/hooks/useCountdown.d.ts +19 -0
  375. package/lib/types/hooks/useDigitInput.d.ts +24 -0
  376. package/lib/types/hooks/useDismiss.d.ts +3 -0
  377. package/lib/types/hooks/useElapsed.d.ts +28 -0
  378. package/lib/types/hooks/useFloating.d.ts +21 -0
  379. package/lib/types/hooks/useFocusTrap.d.ts +7 -0
  380. package/lib/types/hooks/usePresence.d.ts +8 -0
  381. package/lib/types/hooks/usePressToOpen.d.ts +20 -0
  382. package/lib/types/hooks/useScrollLock.d.ts +2 -0
  383. package/lib/types/hooks/useSelection.d.ts +29 -0
  384. package/lib/types/index.d.ts +5 -0
  385. package/lib/types/primitives/AspectRatio.d.ts +14 -0
  386. package/lib/types/primitives/BrandIcon.d.ts +12 -0
  387. package/lib/types/primitives/ColorDot.d.ts +20 -0
  388. package/lib/types/primitives/CopyButton.d.ts +12 -0
  389. package/lib/types/primitives/CountBadge.d.ts +28 -0
  390. package/lib/types/primitives/Countdown.d.ts +21 -0
  391. package/lib/types/primitives/Delta.d.ts +33 -0
  392. package/lib/types/primitives/Elapsed.d.ts +23 -0
  393. package/lib/types/primitives/FileIcon.d.ts +17 -0
  394. package/lib/types/primitives/Flag.d.ts +15 -0
  395. package/lib/types/primitives/IconStack.d.ts +27 -0
  396. package/lib/types/primitives/IconTile.d.ts +24 -0
  397. package/lib/types/primitives/Kbd.d.ts +19 -0
  398. package/lib/types/primitives/Layout.d.ts +64 -0
  399. package/lib/types/primitives/Link.d.ts +12 -0
  400. package/lib/types/primitives/MaskedText.d.ts +28 -0
  401. package/lib/types/primitives/Progress.d.ts +52 -0
  402. package/lib/types/primitives/RelativeTime.d.ts +22 -0
  403. package/lib/types/primitives/SearchInput.d.ts +8 -0
  404. package/lib/types/primitives/SelectorButton.d.ts +23 -0
  405. package/lib/types/primitives/Spinner.d.ts +15 -0
  406. package/lib/types/primitives/StatusIcon.d.ts +40 -0
  407. package/lib/types/primitives/Swatch.d.ts +11 -0
  408. package/lib/types/primitives/Tooltip.d.ts +17 -0
  409. package/lib/types/primitives/Typography.d.ts +48 -0
  410. package/lib/types/primitives/formatCountdown.d.ts +2 -0
  411. package/lib/types/primitives/formatElapsed.d.ts +8 -0
  412. package/lib/types/primitives/formatRelativeTime.d.ts +16 -0
  413. package/lib/types/primitives/hotkey.d.ts +10 -0
  414. package/lib/types/primitives/index.d.ts +188 -0
  415. package/lib/types/primitives/maskValue.d.ts +24 -0
  416. package/package.json +55 -4
@@ -0,0 +1,153 @@
1
+ # SegmentedControl
2
+
3
+ > 선택 컨트롤 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 몇 개의 보기 · 필터 중 하나를 고르는 컨트롤. 선택 배경이 항목 사이를 미끄러지듯 옮겨 가요. 탭을 누르거나 포커스한 뒤 ← → 키로 바꿀 수 있고, 끝에서는 반대쪽 처음으로 돌아가요.
6
+
7
+ ```tsx
8
+ import { SegmentedControl, type SegmentOption } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 탭은 `Tabs`(패널 연결). `SegmentedControl`은 같은 화면 안의 보기 전환에만.
14
+
15
+ ## API
16
+
17
+ ### SegmentedControl
18
+
19
+ role="tablist"로 렌더되고 각 항목은 role="tab"이에요. 선택된 항목만 Tab으로 포커스돼요.
20
+
21
+ | prop | 타입 | 기본값 | 설명 |
22
+ | --- | --- | --- | --- |
23
+ | `options` (필수) | `SegmentOption<T>[]` | | 항목 목록. |
24
+ | `value` (필수) | `T` | | 선택된 값. |
25
+ | `onChange` (필수) | `(value: T) => void` | | 선택이 바뀔 때(클릭, ← → 키). |
26
+ | `variant` | `'pill' \| 'underline' \| 'chip' \| 'text'` | `'pill'` | 모양. |
27
+ | `ariaLabel` | `string` | | 스크린 리더용 이름. 꼭 넣어 주세요. |
28
+
29
+ ### SegmentOption
30
+
31
+ | prop | 타입 | 기본값 | 설명 |
32
+ | --- | --- | --- | --- |
33
+ | `value` (필수) | `T extends string` | | 고유 값. |
34
+ | `label` (필수) | `ReactNode` | | 보이는 글자. |
35
+ | `icon` | `ReactNode` | | 글자 앞 아이콘. |
36
+ | `count` | `number` | | 글자 뒤 숫자. |
37
+
38
+ ## 예제
39
+
40
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
41
+
42
+ ### 기본 (pill)
43
+
44
+ 움푹 들어간 트랙 위에서 흰 선택 배경이 움직여요. value와 onChange로 제어해요.
45
+
46
+ ```tsx
47
+ import { useState } from 'react'
48
+ import { SegmentedControl } from '@iamfiro/design'
49
+
50
+ type Period = 'day' | 'week' | 'month' | 'year'
51
+
52
+ export default function Example() {
53
+ const [period, setPeriod] = useState<Period>('week')
54
+ return (
55
+ <SegmentedControl
56
+ ariaLabel="기간"
57
+ value={period}
58
+ onChange={setPeriod}
59
+ options={[
60
+ { value: 'day', label: '일간' },
61
+ { value: 'week', label: '주간' },
62
+ { value: 'month', label: '월간' },
63
+ { value: 'year', label: '연간' },
64
+ ]}
65
+ />
66
+ )
67
+ }
68
+ ```
69
+
70
+ ### 아이콘
71
+
72
+ icon은 글자 앞에 붙어요. 보기 방식 전환에 잘 어울려요.
73
+
74
+ ```tsx
75
+ import { useState } from 'react'
76
+ import { Columns3, LayoutGrid, List } from 'lucide-react'
77
+ import { SegmentedControl, type SegmentOption } from '@iamfiro/design'
78
+
79
+ type View = 'grid' | 'list' | 'board'
80
+
81
+ const VIEWS: SegmentOption<View>[] = [
82
+ { value: 'grid', label: '그리드', icon: <LayoutGrid /> },
83
+ { value: 'list', label: '리스트', icon: <List /> },
84
+ { value: 'board', label: '보드', icon: <Columns3 /> },
85
+ ]
86
+
87
+ export default function Example() {
88
+ const [view, setView] = useState<View>('grid')
89
+ return <SegmentedControl ariaLabel="보기 방식" value={view} onChange={setView} options={VIEWS} />
90
+ }
91
+ ```
92
+
93
+ ### 밑줄 탭 (underline) · 개수
94
+
95
+ 페이지 상단 탭 바. count를 주면 글자 옆에 숫자가 붙어요(tabular-nums).
96
+
97
+ ```tsx
98
+ import { useState } from 'react'
99
+ import { SegmentedControl, type SegmentOption } from '@iamfiro/design'
100
+
101
+ type Filter = 'all' | 'open' | 'review' | 'done'
102
+
103
+ const FILTERS: SegmentOption<Filter>[] = [
104
+ { value: 'all', label: '전체', count: 24 },
105
+ { value: 'open', label: '진행 중', count: 9 },
106
+ { value: 'review', label: '검토 중', count: 3 },
107
+ { value: 'done', label: '완료', count: 12 },
108
+ ]
109
+
110
+ export default function Example() {
111
+ const [filter, setFilter] = useState<Filter>('all')
112
+ return <SegmentedControl variant="underline" ariaLabel="이슈 상태" value={filter} onChange={setFilter} options={FILTERS} />
113
+ }
114
+ ```
115
+
116
+ ### 칩 (chip) · 텍스트 (text)
117
+
118
+ chip은 항목이 서로 떨어진 칩 모양, text는 배경 없이 글자 색만 바뀌어요.
119
+
120
+ ```tsx
121
+ import { useState } from 'react'
122
+ import { SegmentedControl, Text, type SegmentOption } from '@iamfiro/design'
123
+
124
+ type Section = 'overview' | 'analytics' | 'reports' | 'notifications'
125
+
126
+ const SECTIONS: SegmentOption<Section>[] = [
127
+ { value: 'overview', label: '개요' },
128
+ { value: 'analytics', label: '분석' },
129
+ { value: 'reports', label: '리포트' },
130
+ { value: 'notifications', label: '알림', count: 3 },
131
+ ]
132
+
133
+ export default function Example() {
134
+ const [chip, setChip] = useState<Section>('overview')
135
+ const [text, setText] = useState<Section>('overview')
136
+ return (
137
+ <div style={{ display: 'grid', gap: 20, justifyItems: 'start' }}>
138
+ <div style={{ display: 'grid', gap: 8 }}>
139
+ <Text variant="caption" tone="tertiary">
140
+ chip
141
+ </Text>
142
+ <SegmentedControl variant="chip" ariaLabel="대시보드" value={chip} onChange={setChip} options={SECTIONS} />
143
+ </div>
144
+ <div style={{ display: 'grid', gap: 8 }}>
145
+ <Text variant="caption" tone="tertiary">
146
+ text
147
+ </Text>
148
+ <SegmentedControl variant="text" ariaLabel="대시보드" value={text} onChange={setText} options={SECTIONS} />
149
+ </div>
150
+ </div>
151
+ )
152
+ }
153
+ ```
@@ -0,0 +1,159 @@
1
+ # Select
2
+
3
+ > 선택 컨트롤 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 목록에서 하나를 고르는 커스텀 셀렉트. 그룹·설명·아이콘·비활성 항목을 지원하고, 키보드(↑↓, Home/End, 글자 입력)로 빠르게 이동해요. 팝오버는 열리고 닫힐 때 모두 애니메이션돼요.
6
+
7
+ ```tsx
8
+ import { Select, type ListOption } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 숫자만 받는 칸(금액 · 전화번호 · 카드 번호)은 `useDigitInput`을 Input에 펼친다: 글자는 아예 안 들어가고, 쉼표 · 하이픈은 `format`으로 붙이고, 커서는 같은 숫자 뒤에 머물고, 구분자 위 Backspace는 앞 숫자를 지운다. `type="number"`는 쓰지 않는다. 전화번호는 `PhoneInput`(칸 안 `Select bare` 국가 선택 + 국기 `Flag`, 목록은 `anchorRef`로 칸 전체 폭). 국기는 이모지 대신 `Flag`(Windows에서 이모지 국기는 글자로 나온다).
14
+
15
+ ## API
16
+
17
+ ### Select
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `options` (필수) | `ListOption<V>[]` | | 선택지 목록. |
22
+ | `value` | `V \| null` | | 선택된 값(제어). null은 선택 없음. |
23
+ | `defaultValue` | `V \| null` | `null` | 처음 선택값(비제어). |
24
+ | `onValueChange` | `(value: V) => void` | | 값이 바뀔 때. |
25
+ | `open / onOpenChange` | `boolean / (open) => void` | | 열림 상태를 밖에서 제어할 때. |
26
+ | `placeholder` | `ReactNode` | `'선택하세요'` | 선택 전 문구. |
27
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 높이 36 / 44 / 52px. |
28
+ | `invalid` | `boolean` | | 오류 표시. |
29
+ | `disabled` | `boolean` | | 비활성. |
30
+ | `leading` | `ReactNode` | | 값 앞 아이콘. 생략하면 선택된 항목의 icon. |
31
+ | `renderValue` | `(option) => ReactNode` | | 트리거에 보일 내용을 직접 그릴 때. |
32
+ | `renderOption` | `(option, state) => ReactNode` | | 목록 행을 직접 그릴 때. |
33
+ | `name` | `string` | | 폼 제출용 hidden input 이름. |
34
+ | `maxHeight` | `number` | `300` | 팝오버 최대 높이. |
35
+
36
+ ### ListOption
37
+
38
+ Select · MultiSelect · Combobox가 함께 쓰는 선택지 형태.
39
+
40
+ | prop | 타입 | 기본값 | 설명 |
41
+ | --- | --- | --- | --- |
42
+ | `value` (필수) | `V extends string` | | 고유 값. |
43
+ | `label` (필수) | `string` | | 표시 이름(검색·글자 이동에도 사용). |
44
+ | `description` | `ReactNode` | | 이름 아래 보조 설명. |
45
+ | `icon` | `ReactNode` | | 앞 아이콘. |
46
+ | `group` | `string` | | 그룹 제목. 같은 그룹은 붙여 두세요. |
47
+ | `disabled` | `boolean` | | 선택 불가. |
48
+ | `keywords` | `string[]` | | Combobox 검색에 쓰는 추가 단어. |
49
+
50
+ ## 예제
51
+
52
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
53
+
54
+ ### 기본
55
+
56
+ options와 value / onValueChange만 있으면 돼요. value를 생략하면 defaultValue로 비제어 사용.
57
+
58
+ ```tsx
59
+ import { useState } from 'react'
60
+ import { Select, type ListOption } from '@iamfiro/design'
61
+
62
+ const FRUITS: ListOption[] = [
63
+ { value: 'apple', label: '사과' },
64
+ { value: 'banana', label: '바나나' },
65
+ { value: 'grape', label: '포도' },
66
+ { value: 'peach', label: '복숭아' },
67
+ ]
68
+
69
+ export default function Example() {
70
+ const [fruit, setFruit] = useState<string | null>('apple')
71
+ return (
72
+ <div style={{ width: 280 }}>
73
+ <Select options={FRUITS} value={fruit} onValueChange={setFruit} aria-label="과일" />
74
+ </div>
75
+ )
76
+ }
77
+ ```
78
+
79
+ ### 그룹 · 설명 · 비활성
80
+
81
+ 같은 group 값을 가진 항목은 제목 아래 묶여요. disabled 항목은 건너뛰고 선택할 수 없어요.
82
+
83
+ ```tsx
84
+ import { Select, type ListOption } from '@iamfiro/design'
85
+
86
+ const REGIONS: ListOption[] = [
87
+ { value: 'icn', label: '서울', description: 'icn1 · 지연 시간 가장 짧음', group: '아시아' },
88
+ { value: 'nrt', label: '도쿄', description: 'nrt1', group: '아시아' },
89
+ { value: 'sin', label: '싱가포르', description: 'sin1', group: '아시아' },
90
+ { value: 'sfo', label: '샌프란시스코', description: 'sfo1', group: '미국' },
91
+ { value: 'iad', label: '워싱턴', description: 'iad1 · 점검 중', group: '미국', disabled: true },
92
+ { value: 'fra', label: '프랑크푸르트', description: 'fra1', group: '유럽' },
93
+ ]
94
+
95
+ export default function Example() {
96
+ return (
97
+ <div style={{ width: 300 }}>
98
+ <Select options={REGIONS} defaultValue="icn" aria-label="리전" />
99
+ </div>
100
+ )
101
+ }
102
+ ```
103
+
104
+ ### 아이콘
105
+
106
+ 선택된 항목의 아이콘은 트리거에도 표시돼요.
107
+
108
+ ```tsx
109
+ import { Circle, CircleCheck, CircleDashed, CircleDot } from 'lucide-react'
110
+ import { Select, type ListOption } from '@iamfiro/design'
111
+
112
+ const STATUSES: ListOption[] = [
113
+ { value: 'todo', label: '할 일', icon: <CircleDashed /> },
114
+ { value: 'doing', label: '진행 중', icon: <CircleDot color="var(--info)" /> },
115
+ { value: 'review', label: '검토 중', icon: <Circle color="var(--warning)" /> },
116
+ { value: 'done', label: '완료', icon: <CircleCheck color="var(--success)" /> },
117
+ ]
118
+
119
+ export default function Example() {
120
+ return (
121
+ <div style={{ width: 260 }}>
122
+ <Select options={STATUSES} placeholder="상태를 선택하세요" aria-label="상태" />
123
+ </div>
124
+ )
125
+ }
126
+ ```
127
+
128
+ ### 크기와 상태
129
+
130
+ size, invalid, disabled. Field와 함께 쓰면 라벨이 자동으로 연결돼요.
131
+
132
+ ```tsx
133
+ import { Field, Select, type ListOption } from '@iamfiro/design'
134
+
135
+ const PLANS: ListOption[] = [
136
+ { value: 'starter', label: '스타터' },
137
+ { value: 'team', label: '팀' },
138
+ { value: 'enterprise', label: '엔터프라이즈' },
139
+ ]
140
+
141
+ export default function Example() {
142
+ return (
143
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 220px)', gap: 16 }}>
144
+ <Field label="작게 (sm)" htmlFor="plan-sm">
145
+ <Select id="plan-sm" size="sm" options={PLANS} defaultValue="team" />
146
+ </Field>
147
+ <Field label="크게 (lg)" htmlFor="plan-lg">
148
+ <Select id="plan-lg" size="lg" options={PLANS} defaultValue="team" />
149
+ </Field>
150
+ <Field label="오류" invalid hint="플랜을 선택해 주세요." htmlFor="plan-err">
151
+ <Select id="plan-err" options={PLANS} invalid />
152
+ </Field>
153
+ <Field label="비활성" htmlFor="plan-off">
154
+ <Select id="plan-off" options={PLANS} defaultValue="starter" disabled />
155
+ </Field>
156
+ </div>
157
+ )
158
+ }
159
+ ```
@@ -0,0 +1,122 @@
1
+ # SelectorButton
2
+
3
+ > 버튼 & 링크 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 지금 선택된 것을 보여 주고 눌러서 바꾸는 조용한 버튼. 워크스페이스 · 계정 전환, 드롭다운이 달린 페이지 제목에 써요. 앞(leading) · 이름 · 회색 설명 · chevron으로 이루어지고, DropdownMenu의 trigger에 넣으면 메뉴가 열린 동안 아래 chevron이 뒤집혀요.
6
+
7
+ ```tsx
8
+ import { SelectorButton } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 사이드바 머리 = `SelectorButton`(앱 이름) + 검색 · 접기 아이콘 버튼. 접으면(`sidebarCollapsed`) 헤더 왼쪽에 여는 버튼이 나타난다. 본문 헤더 = 왼쪽 `Breadcrumb`, 오른쪽 작은 ghost 액션.
14
+ - 행 앞 타일: 사람은 `Avatar`, 도구·사이트·문서는 `IconTile`(회색 채움 + 아이콘/글자). 선택된 것을 보여 주고 메뉴로 바꾸는 버튼(워크스페이스·계정 전환, 드롭다운 제목)은 `SelectorButton`을 `DropdownMenu` trigger에.
15
+
16
+ ## API
17
+
18
+ ### SelectorButton
19
+
20
+ 나머지 props는 <button>으로 전달돼요(ref 포함).
21
+
22
+ | prop | 타입 | 기본값 | 설명 |
23
+ | --- | --- | --- | --- |
24
+ | `label` (필수) | `ReactNode` | | 선택된 이름. 길면 말줄임돼요. |
25
+ | `description` | `ReactNode` | | 아래 회색 줄(요금제, 이메일). |
26
+ | `leading` | `ReactNode` | | 앞의 아바타 · 글자 타일 · 아이콘. |
27
+ | `chevron` | `'down' \| 'updown' \| 'right' \| 'none'` | `'down'` | down은 메뉴가 열리면 뒤집혀요. |
28
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | lg는 헤딩 크기 글자(페이지 제목). |
29
+ | `block` | `boolean` | | 부모 폭을 채우고 chevron을 끝에 붙여요. |
30
+
31
+ ## 예제
32
+
33
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
34
+
35
+ ### 워크스페이스 전환
36
+
37
+ block으로 사이드바 폭을 채우고, 글자 아바타(Avatar square)와 요금제 설명을 붙였어요. 누르는 순간 메뉴가 열려요.
38
+
39
+ ```tsx
40
+ import { useState } from 'react'
41
+ import { Plus, Settings } from 'lucide-react'
42
+ import { Avatar, SelectorButton, DropdownMenu, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator } from '@iamfiro/design'
43
+
44
+ const WORKSPACES = [
45
+ { id: 'lumen', name: '루멘 디자인팀', plan: '팀 요금제 · 멤버 12명' },
46
+ { id: 'side', name: '사이드 프로젝트', plan: '무료 · 멤버 3명' },
47
+ ]
48
+
49
+ export default function Example() {
50
+ const [current, setCurrent] = useState('lumen')
51
+ const ws = WORKSPACES.find((w) => w.id === current)!
52
+ return (
53
+ <div style={{ width: 248 }}>
54
+ <DropdownMenu
55
+ minWidth={248}
56
+ trigger={<SelectorButton block leading={<Avatar name={ws.name.slice(0, 1)} square size={28} />} label={ws.name} description={ws.plan} />}
57
+ >
58
+ <DropdownMenuLabel>워크스페이스</DropdownMenuLabel>
59
+ <DropdownMenuRadioGroup value={current} onValueChange={setCurrent}>
60
+ {WORKSPACES.map((w) => (
61
+ <DropdownMenuRadioItem key={w.id} value={w.id}>
62
+ {w.name}
63
+ </DropdownMenuRadioItem>
64
+ ))}
65
+ </DropdownMenuRadioGroup>
66
+ <DropdownMenuSeparator />
67
+ <DropdownMenuItem icon={<Plus />}>새 워크스페이스</DropdownMenuItem>
68
+ <DropdownMenuItem icon={<Settings />}>설정</DropdownMenuItem>
69
+ </DropdownMenu>
70
+ </div>
71
+ )
72
+ }
73
+ ```
74
+
75
+ ### 크기 · chevron
76
+
77
+ lg는 페이지 제목, md는 사이드바 머리 · 바닥 행, sm은 작은 행. chevron은 down · updown · right · none.
78
+
79
+ ```tsx
80
+ import { Copy, LogOut, Pencil, Settings, Trash2, UserRound } from 'lucide-react'
81
+ import { Avatar, SelectorButton, Stack, Text, DropdownMenu, DropdownMenuItem, DropdownMenuSeparator } from '@iamfiro/design'
82
+
83
+ export default function Example() {
84
+ return (
85
+ <Stack gap={6} align="start" style={{ width: 260 }}>
86
+ <Stack gap={2}>
87
+ <Text variant="caption" tone="tertiary">
88
+ size="lg" · 페이지 제목
89
+ </Text>
90
+ <DropdownMenu trigger={<SelectorButton size="lg" label="3분기 회고" />}>
91
+ <DropdownMenuItem icon={<Pencil />}>이름 바꾸기</DropdownMenuItem>
92
+ <DropdownMenuItem icon={<Copy />}>복제</DropdownMenuItem>
93
+ <DropdownMenuSeparator />
94
+ <DropdownMenuItem icon={<Trash2 />} danger>
95
+ 삭제
96
+ </DropdownMenuItem>
97
+ </DropdownMenu>
98
+ </Stack>
99
+
100
+ <Stack gap={2} style={{ alignSelf: 'stretch' }}>
101
+ <Text variant="caption" tone="tertiary">
102
+ block · 사용자 메뉴 (chevron="updown")
103
+ </Text>
104
+ <DropdownMenu align="start" minWidth={240} trigger={<SelectorButton block chevron="updown" leading={<Avatar name="김민지" size={28} />} label="김민지" />}>
105
+ <DropdownMenuItem icon={<UserRound />}>내 프로필</DropdownMenuItem>
106
+ <DropdownMenuItem icon={<Settings />}>설정</DropdownMenuItem>
107
+ <DropdownMenuSeparator />
108
+ <DropdownMenuItem icon={<LogOut />}>로그아웃</DropdownMenuItem>
109
+ </DropdownMenu>
110
+ </Stack>
111
+
112
+ <Stack gap={2}>
113
+ <Text variant="caption" tone="tertiary">
114
+ size="sm" · chevron="right" · disabled
115
+ </Text>
116
+ <SelectorButton size="sm" chevron="right" label="모든 프로젝트" />
117
+ <SelectorButton size="sm" label="권한 없음" disabled />
118
+ </Stack>
119
+ </Stack>
120
+ )
121
+ }
122
+ ```
@@ -0,0 +1,201 @@
1
+ # Sidebar
2
+
3
+ > 내비게이션 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 세로 내비게이션. 위쪽 header, 스크롤되는 그룹 목록, 아래에 고정되는 footer로 이루어져요. 그룹은 접을 수 있고, 펼치고 접을 때 실제 높이만큼 부드럽게 움직여요. 보통 AppShell의 sidebar로 써요.
6
+
7
+ ```tsx
8
+ import { Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 사이드바 footer가 남은 높이보다 크면 잘리지 않고 footer 안에서 스크롤된다(`Sidebar`). 미리보기 상자 높이는 `--shell-height`로.
14
+
15
+ ## API
16
+
17
+ ### Sidebar
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `children` (필수) | `ReactNode` | | SidebarGroup 목록. 이 영역만 스크롤돼요. |
22
+ | `header` | `ReactNode` | | 위쪽 영역(브랜드, 워크스페이스 전환). |
23
+ | `footer` | `ReactNode` | | 아래에 고정되는 영역(사용자, 설정). |
24
+ | `aria-label` | `string` | `'메뉴'` | <nav>의 접근성 이름. |
25
+ | `className` | `string` | | 루트에 붙일 클래스. |
26
+
27
+ ### SidebarGroup
28
+
29
+ Sidebar.Group으로도 쓸 수 있어요.
30
+
31
+ | prop | 타입 | 기본값 | 설명 |
32
+ | --- | --- | --- | --- |
33
+ | `children` (필수) | `ReactNode` | | SidebarItem 목록. |
34
+ | `label` | `ReactNode` | | 그룹 제목. 생략하면 제목 없이 항목만 보여요. |
35
+ | `icon` | `ReactNode` | | 제목 앞 아이콘. |
36
+ | `count` | `number` | | 제목 끝에 보이는 숫자. |
37
+ | `collapsible` | `boolean` | | 제목을 눌러 접고 펼칠 수 있게 해요. |
38
+ | `defaultOpen` | `boolean` | `true` | 처음 펼침 여부(collapsible일 때). |
39
+
40
+ ### SidebarItem
41
+
42
+ Sidebar.Item으로도 쓸 수 있어요.
43
+
44
+ | prop | 타입 | 기본값 | 설명 |
45
+ | --- | --- | --- | --- |
46
+ | `children` (필수) | `ReactNode` | | 항목 이름. 길면 말줄임돼요. |
47
+ | `href` | `string` | `'#'` | 링크 주소. |
48
+ | `onClick` | `() => void` | | 클릭 처리. 있으면 기본 링크 이동을 막아요(클라이언트 라우팅용). |
49
+ | `active` | `boolean` | | 현재 페이지(aria-current="page"). |
50
+ | `icon` | `ReactNode` | | 앞 아이콘(16px). |
51
+ | `badge` | `ReactNode` | | 끝에 붙는 배지·점·숫자. |
52
+ | `disabled` | `boolean` | | 비활성. 링크가 사라지고 눌리지 않아요. |
53
+
54
+ ## 예제
55
+
56
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
57
+
58
+ ### 기본
59
+
60
+ header에는 브랜드나 워크스페이스 전환, footer에는 사용자 정보를 넣어요. 현재 페이지 항목에 active를 주면 aria-current="page"가 붙어요.
61
+
62
+ ```tsx
63
+ import { useState } from 'react'
64
+ import { Calendar, FolderKanban, House, Inbox, Settings, Users } from 'lucide-react'
65
+ import { Avatar, Text, Card, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
66
+
67
+ export default function Example() {
68
+ const [page, setPage] = useState('home')
69
+ const item = (id: string) => ({ active: page === id, onClick: () => setPage(id) })
70
+
71
+ return (
72
+ <Card padding="none" style={{ width: 260, height: 460, overflow: 'hidden' }}>
73
+ <Sidebar
74
+ header={
75
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
76
+ <Avatar name="Lumen" square size={28} />
77
+ <Text variant="label-lg">Lumen</Text>
78
+ </div>
79
+ }
80
+ footer={
81
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
82
+ <Avatar name="김민지" online />
83
+ <div style={{ minWidth: 0 }}>
84
+ <Text variant="label-md" as="div">
85
+ 김민지
86
+ </Text>
87
+ <Text variant="caption" tone="tertiary" as="div" truncate>
88
+ minji@lumen.app
89
+ </Text>
90
+ </div>
91
+ </div>
92
+ }
93
+ >
94
+ <SidebarGroup>
95
+ <SidebarItem icon={<House />} {...item('home')}>
96
+ 홈
97
+ </SidebarItem>
98
+ <SidebarItem icon={<Inbox />} {...item('inbox')}>
99
+ 받은 편지함
100
+ </SidebarItem>
101
+ <SidebarItem icon={<Calendar />} {...item('calendar')}>
102
+ 일정
103
+ </SidebarItem>
104
+ </SidebarGroup>
105
+ <SidebarGroup label="워크스페이스">
106
+ <SidebarItem icon={<FolderKanban />} {...item('projects')}>
107
+ 프로젝트
108
+ </SidebarItem>
109
+ <SidebarItem icon={<Users />} {...item('members')}>
110
+ 멤버
111
+ </SidebarItem>
112
+ <SidebarItem icon={<Settings />} {...item('settings')}>
113
+ 설정
114
+ </SidebarItem>
115
+ </SidebarGroup>
116
+ </Sidebar>
117
+ </Card>
118
+ )
119
+ }
120
+ ```
121
+
122
+ ### 그룹 · 접기
123
+
124
+ label이 있으면 그룹 제목이 생겨요. collapsible이면 제목을 눌러 접고 펼치며, defaultOpen={false}로 접힌 채 시작해요. count는 제목 끝에 숫자로 보여요.
125
+
126
+ ```tsx
127
+ import { useState } from 'react'
128
+ import { Folder, Hash, Star } from 'lucide-react'
129
+ import { Card, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
130
+
131
+ const PROJECTS = ['웹사이트 리뉴얼', '모바일 앱 2.0', '디자인 시스템', '연말 캠페인']
132
+ const CHANNELS = ['공지', '디자인', '개발', '잡담']
133
+
134
+ export default function Example() {
135
+ const [current, setCurrent] = useState('디자인 시스템')
136
+
137
+ return (
138
+ <Card padding="none" style={{ width: 260, height: 460, overflow: 'hidden' }}>
139
+ <Sidebar>
140
+ <SidebarGroup label="즐겨찾기" icon={<Star />}>
141
+ <SidebarItem active={current === '디자인 시스템'} onClick={() => setCurrent('디자인 시스템')}>
142
+ 디자인 시스템
143
+ </SidebarItem>
144
+ </SidebarGroup>
145
+ <SidebarGroup label="프로젝트" count={PROJECTS.length} collapsible>
146
+ {PROJECTS.map((name) => (
147
+ <SidebarItem key={name} icon={<Folder />} active={current === name} onClick={() => setCurrent(name)}>
148
+ {name}
149
+ </SidebarItem>
150
+ ))}
151
+ </SidebarGroup>
152
+ <SidebarGroup label="채널" count={CHANNELS.length} collapsible defaultOpen={false}>
153
+ {CHANNELS.map((name) => (
154
+ <SidebarItem key={name} icon={<Hash />} active={current === name} onClick={() => setCurrent(name)}>
155
+ {name}
156
+ </SidebarItem>
157
+ ))}
158
+ </SidebarGroup>
159
+ </Sidebar>
160
+ </Card>
161
+ )
162
+ }
163
+ ```
164
+
165
+ ### 항목 상태
166
+
167
+ icon, 끝에 붙는 badge(Badge·점·숫자), active, disabled. 비활성 항목은 흐리게 보이고 눌리지 않아요.
168
+
169
+ ```tsx
170
+ import { useState } from 'react'
171
+ import { Archive, ChartColumn, CreditCard, Inbox, Sparkles } from 'lucide-react'
172
+ import { Badge, Card, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
173
+
174
+ export default function Example() {
175
+ const [page, setPage] = useState('inbox')
176
+
177
+ return (
178
+ <Card padding="none" style={{ width: 260, overflow: 'hidden' }}>
179
+ <Sidebar>
180
+ <SidebarGroup label="메뉴">
181
+ <SidebarItem icon={<Inbox />} badge={<Badge>12</Badge>} active={page === 'inbox'} onClick={() => setPage('inbox')}>
182
+ 받은 편지함
183
+ </SidebarItem>
184
+ <SidebarItem icon={<Sparkles />} badge={<Badge tone="accent">New</Badge>} active={page === 'ai'} onClick={() => setPage('ai')}>
185
+ AI 요약
186
+ </SidebarItem>
187
+ <SidebarItem icon={<ChartColumn />} active={page === 'reports'} onClick={() => setPage('reports')}>
188
+ 리포트
189
+ </SidebarItem>
190
+ <SidebarItem icon={<CreditCard />} badge={<Badge tone="warning" dot>결제 필요</Badge>} active={page === 'billing'} onClick={() => setPage('billing')}>
191
+ 결제
192
+ </SidebarItem>
193
+ <SidebarItem icon={<Archive />} disabled>
194
+ 보관함
195
+ </SidebarItem>
196
+ </SidebarGroup>
197
+ </Sidebar>
198
+ </Card>
199
+ )
200
+ }
201
+ ```