@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.
- package/AGENTS.md +81 -0
- package/README.md +15 -2
- package/agents/INDEX.md +156 -0
- package/agents/accordion/AGENTS.md +279 -0
- package/agents/action-bar/AGENTS.md +90 -0
- package/agents/alert/AGENTS.md +212 -0
- package/agents/alert-dialog/AGENTS.md +193 -0
- package/agents/app-shell/AGENTS.md +409 -0
- package/agents/area-chart/AGENTS.md +183 -0
- package/agents/aspect-ratio/AGENTS.md +143 -0
- package/agents/avatar/AGENTS.md +130 -0
- package/agents/badge/AGENTS.md +217 -0
- package/agents/bar-chart/AGENTS.md +386 -0
- package/agents/bar-list/AGENTS.md +223 -0
- package/agents/brand-icon/AGENTS.md +82 -0
- package/agents/breadcrumb/AGENTS.md +133 -0
- package/agents/button/AGENTS.md +195 -0
- package/agents/card/AGENTS.md +141 -0
- package/agents/card-frame/AGENTS.md +227 -0
- package/agents/chat-bubble/AGENTS.md +266 -0
- package/agents/chat-composer/AGENTS.md +251 -0
- package/agents/checkbox/AGENTS.md +113 -0
- package/agents/code-block/AGENTS.md +144 -0
- package/agents/color-dot/AGENTS.md +120 -0
- package/agents/color-picker/AGENTS.md +224 -0
- package/agents/colors/AGENTS.md +168 -0
- package/agents/combobox/AGENTS.md +218 -0
- package/agents/command-menu/AGENTS.md +169 -0
- package/agents/comment/AGENTS.md +206 -0
- package/agents/context-menu/AGENTS.md +303 -0
- package/agents/copy-button/AGENTS.md +84 -0
- package/agents/count-badge/AGENTS.md +115 -0
- package/agents/countdown/AGENTS.md +101 -0
- package/agents/data-grid/AGENTS.md +460 -0
- package/agents/date-picker/AGENTS.md +197 -0
- package/agents/delta/AGENTS.md +114 -0
- package/agents/description-list/AGENTS.md +251 -0
- package/agents/dialog/AGENTS.md +391 -0
- package/agents/drawer/AGENTS.md +471 -0
- package/agents/dropdown-menu/AGENTS.md +322 -0
- package/agents/dropzone/AGENTS.md +116 -0
- package/agents/elapsed/AGENTS.md +160 -0
- package/agents/empty-state/AGENTS.md +203 -0
- package/agents/file-chip/AGENTS.md +79 -0
- package/agents/file-icon/AGENTS.md +66 -0
- package/agents/file-upload/AGENTS.md +168 -0
- package/agents/filter-chips/AGENTS.md +167 -0
- package/agents/flag/AGENTS.md +67 -0
- package/agents/funnel-chart/AGENTS.md +131 -0
- package/agents/highlight/AGENTS.md +119 -0
- package/agents/hover-card/AGENTS.md +271 -0
- package/agents/icon-stack/AGENTS.md +120 -0
- package/agents/icon-tile/AGENTS.md +94 -0
- package/agents/inline-diff/AGENTS.md +211 -0
- package/agents/input/AGENTS.md +261 -0
- package/agents/kanban/AGENTS.md +352 -0
- package/agents/kbd/AGENTS.md +160 -0
- package/agents/layout/AGENTS.md +351 -0
- package/agents/line-chart/AGENTS.md +393 -0
- package/agents/link/AGENTS.md +53 -0
- package/agents/list/AGENTS.md +392 -0
- package/agents/marker/AGENTS.md +142 -0
- package/agents/masked-text/AGENTS.md +127 -0
- package/agents/menubar/AGENTS.md +276 -0
- package/agents/multi-select/AGENTS.md +159 -0
- package/agents/navigation-menu/AGENTS.md +315 -0
- package/agents/notice-stack/AGENTS.md +101 -0
- package/agents/number-stepper/AGENTS.md +96 -0
- package/agents/otp-input/AGENTS.md +162 -0
- package/agents/pagination/AGENTS.md +189 -0
- package/agents/phone-input/AGENTS.md +131 -0
- package/agents/pie-chart/AGENTS.md +243 -0
- package/agents/popover/AGENTS.md +190 -0
- package/agents/progress/AGENTS.md +273 -0
- package/agents/progress-tracker/AGENTS.md +305 -0
- package/agents/rating/AGENTS.md +165 -0
- package/agents/relative-time/AGENTS.md +103 -0
- package/agents/resizable/AGENTS.md +390 -0
- package/agents/scaled-preview/AGENTS.md +111 -0
- package/agents/scatter-chart/AGENTS.md +160 -0
- package/agents/scroll-area/AGENTS.md +271 -0
- package/agents/search-input/AGENTS.md +105 -0
- package/agents/segmented-control/AGENTS.md +153 -0
- package/agents/select/AGENTS.md +159 -0
- package/agents/selector-button/AGENTS.md +122 -0
- package/agents/sidebar/AGENTS.md +201 -0
- package/agents/skeleton/AGENTS.md +166 -0
- package/agents/slider/AGENTS.md +181 -0
- package/agents/spark-chart/AGENTS.md +257 -0
- package/agents/sparkbar/AGENTS.md +92 -0
- package/agents/spinner/AGENTS.md +123 -0
- package/agents/split-view/AGENTS.md +290 -0
- package/agents/stat/AGENTS.md +138 -0
- package/agents/status-icon/AGENTS.md +243 -0
- package/agents/step-list/AGENTS.md +313 -0
- package/agents/table/AGENTS.md +286 -0
- package/agents/tabs/AGENTS.md +305 -0
- package/agents/tag-input/AGENTS.md +246 -0
- package/agents/time-picker/AGENTS.md +228 -0
- package/agents/timeline/AGENTS.md +1018 -0
- package/agents/toast/AGENTS.md +266 -0
- package/agents/toggle-group/AGENTS.md +216 -0
- package/agents/toolbar/AGENTS.md +277 -0
- package/agents/tooltip/AGENTS.md +154 -0
- package/agents/tracker/AGENTS.md +158 -0
- package/agents/tree-diagram/AGENTS.md +260 -0
- package/agents/tree-view/AGENTS.md +329 -0
- package/agents/typography/AGENTS.md +396 -0
- package/lib/index.js +17914 -0
- package/lib/style.css +2 -0
- package/lib/types/components/Accordion/Accordion.d.ts +57 -0
- package/lib/types/components/ActionBar/ActionBar.d.ts +24 -0
- package/lib/types/components/Alert/Alert.d.ts +36 -0
- package/lib/types/components/AppShell/AppShell.d.ts +38 -0
- package/lib/types/components/AreaChart/AreaChart.d.ts +17 -0
- package/lib/types/components/BarChart/BarChart.d.ts +57 -0
- package/lib/types/components/BarList/BarList.d.ts +56 -0
- package/lib/types/components/Breadcrumb/Breadcrumb.d.ts +15 -0
- package/lib/types/components/Calendar/Calendar.d.ts +34 -0
- package/lib/types/components/Calendar/DatePicker.d.ts +45 -0
- package/lib/types/components/Calendar/date.d.ts +32 -0
- package/lib/types/components/Card/Card.d.ts +64 -0
- package/lib/types/components/CardFrame/CardFrame.d.ts +15 -0
- package/lib/types/components/Chart/ChartParts.d.ts +38 -0
- package/lib/types/components/Chart/chart.d.ts +46 -0
- package/lib/types/components/Chart/useChartInteraction.d.ts +39 -0
- package/lib/types/components/ChatBubble/ChatBubble.d.ts +61 -0
- package/lib/types/components/ChatBubble/formatChatTime.d.ts +2 -0
- package/lib/types/components/ChatComposer/ChatComposer.d.ts +42 -0
- package/lib/types/components/CodeBlock/CodeBlock.d.ts +18 -0
- package/lib/types/components/CodeBlock/highlight.d.ts +10 -0
- package/lib/types/components/ColorPicker/ColorPicker.d.ts +61 -0
- package/lib/types/components/ColorPicker/color.d.ts +48 -0
- package/lib/types/components/ColorPicker/presets.d.ts +7 -0
- package/lib/types/components/Combobox/Combobox.d.ts +48 -0
- package/lib/types/components/CommandMenu/CommandMenu.d.ts +51 -0
- package/lib/types/components/Comment/Comment.d.ts +45 -0
- package/lib/types/components/ContextMenu/ContextMenu.d.ts +40 -0
- package/lib/types/components/DataGrid/DataGrid.d.ts +43 -0
- package/lib/types/components/DataGrid/GridPopover.d.ts +43 -0
- package/lib/types/components/DataGrid/anchor.d.ts +5 -0
- package/lib/types/components/DataGrid/model.d.ts +61 -0
- package/lib/types/components/DataGrid/panels.d.ts +63 -0
- package/lib/types/components/DataGrid/typeMeta.d.ts +6 -0
- package/lib/types/components/DataGrid/types.d.ts +77 -0
- package/lib/types/components/DescriptionList/DescriptionList.d.ts +77 -0
- package/lib/types/components/Dialog/AlertDialog.d.ts +26 -0
- package/lib/types/components/Dialog/Dialog.d.ts +42 -0
- package/lib/types/components/Dialog/modal.d.ts +38 -0
- package/lib/types/components/Drawer/Drawer.d.ts +62 -0
- package/lib/types/components/DropdownMenu/DropdownMenu.d.ts +97 -0
- package/lib/types/components/DropdownMenu/menuCore.d.ts +23 -0
- package/lib/types/components/Dropzone/Dropzone.d.ts +30 -0
- package/lib/types/components/EmptyState/EmptyState.d.ts +26 -0
- package/lib/types/components/FileChip/FileChip.d.ts +32 -0
- package/lib/types/components/FileUpload/FileUpload.d.ts +52 -0
- package/lib/types/components/FilterChips/FilterChips.d.ts +37 -0
- package/lib/types/components/FunnelChart/FunnelChart.d.ts +38 -0
- package/lib/types/components/FunnelChart/funnel.d.ts +25 -0
- package/lib/types/components/Highlight/Highlight.d.ts +35 -0
- package/lib/types/components/HoverCard/HoverCard.d.ts +47 -0
- package/lib/types/components/InlineDiff/InlineDiff.d.ts +36 -0
- package/lib/types/components/InlineDiff/diff.d.ts +42 -0
- package/lib/types/components/InlineDiff/useDiffReview.d.ts +57 -0
- package/lib/types/components/Kanban/Kanban.d.ts +64 -0
- package/lib/types/components/Kanban/KanbanCard.d.ts +35 -0
- package/lib/types/components/Kanban/move.d.ts +25 -0
- package/lib/types/components/LineChart/LineChart.d.ts +85 -0
- package/lib/types/components/List/List.d.ts +62 -0
- package/lib/types/components/Listbox/Listbox.d.ts +60 -0
- package/lib/types/components/Marker/Marker.d.ts +28 -0
- package/lib/types/components/Menubar/Menubar.d.ts +50 -0
- package/lib/types/components/MultiSelect/MultiSelect.d.ts +38 -0
- package/lib/types/components/NavigationMenu/NavigationMenu.d.ts +101 -0
- package/lib/types/components/NoticeStack/NoticeStack.d.ts +41 -0
- package/lib/types/components/NumberStepper/NumberStepper.d.ts +32 -0
- package/lib/types/components/OtpInput/OtpInput.d.ts +31 -0
- package/lib/types/components/Pagination/Pagination.d.ts +54 -0
- package/lib/types/components/Pagination/paginationRange.d.ts +7 -0
- package/lib/types/components/PhoneInput/PhoneInput.d.ts +47 -0
- package/lib/types/components/PieChart/PieChart.d.ts +67 -0
- package/lib/types/components/PieChart/arc.d.ts +26 -0
- package/lib/types/components/PieChart/useArcTween.d.ts +15 -0
- package/lib/types/components/Popover/Popover.d.ts +28 -0
- package/lib/types/components/ProgressTracker/ProgressTracker.d.ts +64 -0
- package/lib/types/components/Rating/Rating.d.ts +42 -0
- package/lib/types/components/Resizable/Resizable.d.ts +50 -0
- package/lib/types/components/Resizable/layout.d.ts +31 -0
- package/lib/types/components/ScaledPreview/ScaledPreview.d.ts +38 -0
- package/lib/types/components/ScatterChart/ScatterChart.d.ts +81 -0
- package/lib/types/components/ScatterChart/scatter.d.ts +14 -0
- package/lib/types/components/ScrollArea/ScrollArea.d.ts +34 -0
- package/lib/types/components/Select/Select.d.ts +39 -0
- package/lib/types/components/Sidebar/Sidebar.d.ts +39 -0
- package/lib/types/components/Skeleton/Skeleton.d.ts +47 -0
- package/lib/types/components/Slider/Slider.d.ts +36 -0
- package/lib/types/components/SparkChart/SparkChart.d.ts +55 -0
- package/lib/types/components/SparkChart/spark.d.ts +16 -0
- package/lib/types/components/Sparkbar/Sparkbar.d.ts +39 -0
- package/lib/types/components/SplitView/SplitView.d.ts +31 -0
- package/lib/types/components/Stat/Stat.d.ts +58 -0
- package/lib/types/components/StepList/StepList.d.ts +61 -0
- package/lib/types/components/Table/Table.d.ts +39 -0
- package/lib/types/components/Tabs/Tabs.d.ts +47 -0
- package/lib/types/components/TagInput/TagInput.d.ts +46 -0
- package/lib/types/components/TimePicker/TimePicker.d.ts +43 -0
- package/lib/types/components/TimePicker/time.d.ts +15 -0
- package/lib/types/components/Timeline/Timeline.d.ts +154 -0
- package/lib/types/components/Timeline/scale.d.ts +22 -0
- package/lib/types/components/Toast/Toaster.d.ts +19 -0
- package/lib/types/components/Toast/index.d.ts +4 -0
- package/lib/types/components/Toast/store.d.ts +75 -0
- package/lib/types/components/ToggleGroup/ToggleGroup.d.ts +28 -0
- package/lib/types/components/Toolbar/Toolbar.d.ts +70 -0
- package/lib/types/components/Tracker/Tracker.d.ts +43 -0
- package/lib/types/components/TreeDiagram/TreeDiagram.d.ts +68 -0
- package/lib/types/components/TreeView/TreeView.d.ts +107 -0
- package/lib/types/components/index.d.ts +186 -0
- package/lib/types/hooks/index.d.ts +17 -0
- package/lib/types/hooks/timing.d.ts +29 -0
- package/lib/types/hooks/useControllableState.d.ts +5 -0
- package/lib/types/hooks/useCountdown.d.ts +19 -0
- package/lib/types/hooks/useDigitInput.d.ts +24 -0
- package/lib/types/hooks/useDismiss.d.ts +3 -0
- package/lib/types/hooks/useElapsed.d.ts +28 -0
- package/lib/types/hooks/useFloating.d.ts +21 -0
- package/lib/types/hooks/useFocusTrap.d.ts +7 -0
- package/lib/types/hooks/usePresence.d.ts +8 -0
- package/lib/types/hooks/usePressToOpen.d.ts +20 -0
- package/lib/types/hooks/useScrollLock.d.ts +2 -0
- package/lib/types/hooks/useSelection.d.ts +29 -0
- package/lib/types/index.d.ts +5 -0
- package/lib/types/primitives/AspectRatio.d.ts +14 -0
- package/lib/types/primitives/BrandIcon.d.ts +12 -0
- package/lib/types/primitives/ColorDot.d.ts +20 -0
- package/lib/types/primitives/CopyButton.d.ts +12 -0
- package/lib/types/primitives/CountBadge.d.ts +28 -0
- package/lib/types/primitives/Countdown.d.ts +21 -0
- package/lib/types/primitives/Delta.d.ts +33 -0
- package/lib/types/primitives/Elapsed.d.ts +23 -0
- package/lib/types/primitives/FileIcon.d.ts +17 -0
- package/lib/types/primitives/Flag.d.ts +15 -0
- package/lib/types/primitives/IconStack.d.ts +27 -0
- package/lib/types/primitives/IconTile.d.ts +24 -0
- package/lib/types/primitives/Kbd.d.ts +19 -0
- package/lib/types/primitives/Layout.d.ts +64 -0
- package/lib/types/primitives/Link.d.ts +12 -0
- package/lib/types/primitives/MaskedText.d.ts +28 -0
- package/lib/types/primitives/Progress.d.ts +52 -0
- package/lib/types/primitives/RelativeTime.d.ts +22 -0
- package/lib/types/primitives/SearchInput.d.ts +8 -0
- package/lib/types/primitives/SelectorButton.d.ts +23 -0
- package/lib/types/primitives/Spinner.d.ts +15 -0
- package/lib/types/primitives/StatusIcon.d.ts +40 -0
- package/lib/types/primitives/Swatch.d.ts +11 -0
- package/lib/types/primitives/Tooltip.d.ts +17 -0
- package/lib/types/primitives/Typography.d.ts +48 -0
- package/lib/types/primitives/formatCountdown.d.ts +2 -0
- package/lib/types/primitives/formatElapsed.d.ts +8 -0
- package/lib/types/primitives/formatRelativeTime.d.ts +16 -0
- package/lib/types/primitives/hotkey.d.ts +10 -0
- package/lib/types/primitives/index.d.ts +188 -0
- package/lib/types/primitives/maskValue.d.ts +24 -0
- package/package.json +54 -4
package/AGENTS.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @iamfiro/design — 에이전트 안내
|
|
2
|
+
|
|
3
|
+
React UI는 **이 디자인 시스템으로만** 만든다. 버튼 · 카드 · 입력 · 메뉴 · 모달 · 표 · 차트를 직접 만들지 않는다.
|
|
4
|
+
이미 100개가 넘는 컴포넌트가 있고, 직접 만든 UI는 여백 · 색 · 애니메이션 · 접근성이 어긋난다.
|
|
5
|
+
|
|
6
|
+
> 이 저장소에서 디자인 시스템 *자체*를 고치는 중이라면 이 문서가 아니라 `CLAUDE.md`와 `docs/COMPONENT_GUIDE.md`를 따른다.
|
|
7
|
+
|
|
8
|
+
## 설치
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @iamfiro/design
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
앱 진입점에서 CSS를 **한 번** 불러온다(토큰 · 글꼴 · 기본 스타일 포함). 알림을 쓰면 `<Toaster />`도 한 번 둔다.
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import '@iamfiro/design/style.css'
|
|
18
|
+
import { Toaster } from '@iamfiro/design'
|
|
19
|
+
|
|
20
|
+
export function App() {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<Routes />
|
|
24
|
+
<Toaster />
|
|
25
|
+
</>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
모든 것은 패키지 루트 하나에서 가져온다: `import { Button, Card, Stack } from '@iamfiro/design'`. 아이콘은 `lucide-react`.
|
|
31
|
+
|
|
32
|
+
## 작업 순서
|
|
33
|
+
|
|
34
|
+
1. 만들 화면을 필요한 조각(목록, 필터, 카드, 폼…)으로 나눈다.
|
|
35
|
+
2. 조각마다 [`agents/INDEX.md`](agents/INDEX.md)에서 맞는 컴포넌트를 찾는다.
|
|
36
|
+
3. 쓰기 전에 그 컴포넌트의 `agents/<id>/AGENTS.md`(API · 디자인 규칙 · 예제)를 읽는다. props를 추측하지 않는다.
|
|
37
|
+
4. 컴포넌트를 조립해 화면을 만든다. 배치는 `Stack` · `Inline` · `Grid`.
|
|
38
|
+
|
|
39
|
+
패키지 안 경로: `node_modules/@iamfiro/design/AGENTS.md`, `node_modules/@iamfiro/design/agents/`.
|
|
40
|
+
|
|
41
|
+
## 규칙
|
|
42
|
+
|
|
43
|
+
- **새 UI 컴포넌트 금지.** 필요한 게 목록에 없으면 기존 컴포넌트 조립으로 해결한다(`Card` + `CardHeader` + `List` + `ListItem` + `Badge`…). 조립으로도 안 되면 사용자에게 무엇이 없는지 알린다.
|
|
44
|
+
- **다른 UI 라이브러리 금지.** MUI · Chakra · shadcn/ui · Radix 스타일 컴포넌트 · Tailwind로 만든 버튼/카드를 섞지 않는다.
|
|
45
|
+
- **배치는 레이아웃 컴포넌트로.** 즉석 `<div style={{ display: 'flex' }}>` 대신 `Stack`(세로) · `Inline`(가로) · `Grid` · `Box`. 간격은 `gap={1…10}`(4px 단위)만.
|
|
46
|
+
- **글자는 `Text` · `Heading` · `Prose`로.** `font-size`를 직접 주지 않는다.
|
|
47
|
+
- **스타일을 덮어쓰지 않는다.** `ds-*` 클래스를 재정의하거나 색 · 테두리 · 그림자를 `style`로 바꾸지 않는다. variant · size · tone props로 고른다. 꼭 필요한 색은 토큰(`var(--accent)`, `var(--text-muted)`…)만.
|
|
48
|
+
- **테두리 · 회색 배경을 더하지 않는다.** 바탕은 흰색, 구분은 여백과 컴포넌트 자체 표면(`Card`)으로.
|
|
49
|
+
- **글은 자연스러운 한국어.** 버튼은 동작 이름("삭제", "저장" — "확인" X). 샘플 데이터도 한국어(김민지, "10월 25일", "2분 전").
|
|
50
|
+
- 상태 · 시간 · 숫자 조각도 있는 것을 쓴다: 상대 시간 `RelativeTime`, 증감 `Delta`, 라벨 + 숫자 `Stat`, 진행 `Progress` · `Spinner`, 빈 화면 `EmptyState`, 로딩 `Skeleton`.
|
|
51
|
+
|
|
52
|
+
## 자주 찾는 것
|
|
53
|
+
|
|
54
|
+
| 필요 | 쓸 것 |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| 앱 뼈대 · 사이드바 · 상단 경로 | `AppShell` · `Sidebar` · `Breadcrumb` |
|
|
57
|
+
| 버튼 · 아이콘 버튼 · 링크 | `Button`(`iconOnly` + `aria-label` + `Tooltip`) · `Link` |
|
|
58
|
+
| 콘텐츠 묶음 | `Card` + `CardHeader` / `CardBody` / `CardFooter` |
|
|
59
|
+
| 사람 · 파일 · 설정 행 목록 | `List` + `ListItem`(`leading` · `trailing`) + `Avatar` / `IconTile` |
|
|
60
|
+
| 폼 | `Field` + `Input` / `Textarea` / `Select` / `Combobox` / `Checkbox` / `Switch` / `DatePicker` |
|
|
61
|
+
| 보기 전환 · 탭 | 같은 화면 안 `SegmentedControl`, 패널 전환 `Tabs` |
|
|
62
|
+
| 필터 | `FilterChips` · `SearchInput` · `MultiSelect` |
|
|
63
|
+
| 메뉴 · 팝오버 · 툴팁 | `DropdownMenu` · `Popover` · `Tooltip` · `ContextMenu` · `CommandMenu` |
|
|
64
|
+
| 모달 · 서랍 | `Dialog` · `Drawer`, 되돌릴 수 없는 작업 확인은 `AlertDialog` |
|
|
65
|
+
| 알림 | 잠깐 `toast()`, 되돌릴 수 있는 작업은 확인 대신 `toast.undo()`, 화면 안 `Alert` · `Banner` |
|
|
66
|
+
| 표 | 보기만 `Table`, 편집 · 정렬 · 필터 `DataGrid`, 페이지 `Pagination` |
|
|
67
|
+
| 라벨 · 개수 · 지표 | `Badge` · `CountBadge` · `Stat` / `StatGroup` · `Delta` |
|
|
68
|
+
| 차트 | `LineChart` · `AreaChart` · `BarChart` · `PieChart` · `BarList` · `SparkChart` · `Tracker` |
|
|
69
|
+
| 대화 · 댓글 · 활동 | `ChatBubble` · `ChatComposer` · `Comment` · `StepList` · `Timeline` |
|
|
70
|
+
| 빈 상태 · 로딩 | `EmptyState` · `Skeleton` · `Spinner` |
|
|
71
|
+
|
|
72
|
+
전체 목록: [`agents/INDEX.md`](agents/INDEX.md)
|
|
73
|
+
|
|
74
|
+
## 내 프로젝트에 연결하기
|
|
75
|
+
|
|
76
|
+
사용하는 프로젝트의 `AGENTS.md`(또는 `CLAUDE.md`)에 이 줄을 넣어 두면 에이전트가 매번 여기부터 읽는다.
|
|
77
|
+
|
|
78
|
+
```md
|
|
79
|
+
UI는 `@iamfiro/design`으로만 만든다. 작업 전에 `node_modules/@iamfiro/design/AGENTS.md`를 읽고,
|
|
80
|
+
컴포넌트를 쓰기 전에 `node_modules/@iamfiro/design/agents/<id>/AGENTS.md`를 읽는다. 직접 컴포넌트를 만들지 않는다.
|
|
81
|
+
```
|
package/README.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @iamfiro/design
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lumen 디자인 시스템 — React 19 컴포넌트 · 디자인 토큰 · 훅.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @iamfiro/design
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import '@iamfiro/design/style.css'
|
|
11
|
+
import { Button, Card, CardHeader, Stack } from '@iamfiro/design'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- 에이전트(Claude Code · Codex 등) 안내: [AGENTS.md](AGENTS.md), 컴포넌트별 문서: [agents/INDEX.md](agents/INDEX.md)
|
|
15
|
+
- 문서 사이트(개발): `npm run dev` → http://localhost:5179
|
|
16
|
+
- 패키지 빌드: `npm run build:lib`, 에이전트 문서 다시 만들기: `npm run gen:agents`
|
package/agents/INDEX.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# 컴포넌트 목록
|
|
2
|
+
|
|
3
|
+
`@iamfiro/design`의 모든 컴포넌트 · 파운데이션. 만들기 전에 여기서 찾고, 쓰기 전에 `agents/<id>/AGENTS.md`를 읽는다.
|
|
4
|
+
|
|
5
|
+
## 파운데이션
|
|
6
|
+
|
|
7
|
+
- **Colors** — 모든 색은 tokens.css의 CSS 변수로만 써요. → [`agents/colors/AGENTS.md`](colors/AGENTS.md)
|
|
8
|
+
- **Typography** — 글자는 역할(role)로 골라요. → [`agents/typography/AGENTS.md`](typography/AGENTS.md)
|
|
9
|
+
- **Layout** — 여백을 손으로 맞추지 않도록 돕는 레이아웃 기본 요소. → [`agents/layout/AGENTS.md`](layout/AGENTS.md)
|
|
10
|
+
- **AspectRatio** — 폭은 부모를 따르고 높이는 비율로 정해지는 틀. → [`agents/aspect-ratio/AGENTS.md`](aspect-ratio/AGENTS.md)
|
|
11
|
+
- **ScaledPreview** — 실제 컴포넌트를 높이가 고정된 무대 가운데에 작게 줄여 보여 줘요. → [`agents/scaled-preview/AGENTS.md`](scaled-preview/AGENTS.md)
|
|
12
|
+
- **ScrollArea** — 어느 브라우저에서나 같은 스크롤바를 그리는 스크롤 영역. → [`agents/scroll-area/AGENTS.md`](scroll-area/AGENTS.md)
|
|
13
|
+
|
|
14
|
+
## 버튼 & 링크
|
|
15
|
+
|
|
16
|
+
- **Button** — 동작을 실행하는 기본 버튼. → [`agents/button/AGENTS.md`](button/AGENTS.md)
|
|
17
|
+
- **CopyButton** — value를 클립보드에 복사하는 버튼. → [`agents/copy-button/AGENTS.md`](copy-button/AGENTS.md)
|
|
18
|
+
- **SelectorButton** — 지금 선택된 것을 보여 주고 눌러서 바꾸는 조용한 버튼. → [`agents/selector-button/AGENTS.md`](selector-button/AGENTS.md)
|
|
19
|
+
- **Link** — 글 속 링크. → [`agents/link/AGENTS.md`](link/AGENTS.md)
|
|
20
|
+
- **ActionBar** — 상세 화면 · 검토 화면 아래에 붙는 동작 바. → [`agents/action-bar/AGENTS.md`](action-bar/AGENTS.md)
|
|
21
|
+
- **Toolbar** — 버튼 · 토글 · ToggleGroup · 메뉴 트리거를 한 줄로 묶는 WAI-ARIA 툴바. → [`agents/toolbar/AGENTS.md`](toolbar/AGENTS.md)
|
|
22
|
+
|
|
23
|
+
## 라벨 & 배지
|
|
24
|
+
|
|
25
|
+
- **Badge** — 상태 · 분류 · 개수를 짧게 알려 주는 작은 라벨. → [`agents/badge/AGENTS.md`](badge/AGENTS.md)
|
|
26
|
+
- **CountBadge** — 섹션 제목 · 아이콘 옆에 붙는 작은 숫자 원. → [`agents/count-badge/AGENTS.md`](count-badge/AGENTS.md)
|
|
27
|
+
- **Kbd** — 단축키를 보여주는 키캡. → [`agents/kbd/AGENTS.md`](kbd/AGENTS.md)
|
|
28
|
+
- **ColorDot** — 라벨과 시리즈·분류 색을 이어 주는 작은 색 표시. → [`agents/color-dot/AGENTS.md`](color-dot/AGENTS.md)
|
|
29
|
+
- **Flag** — 국가를 나타내는 작은 3:2 국기. → [`agents/flag/AGENTS.md`](flag/AGENTS.md)
|
|
30
|
+
- **RelativeTime** — "방금", "2분 전", "어제", "10월 25일"처럼 한국어 상대 시간을 <time dateTime>으로 보여 줘요. → [`agents/relative-time/AGENTS.md`](relative-time/AGENTS.md)
|
|
31
|
+
|
|
32
|
+
## 아이콘 & 아바타
|
|
33
|
+
|
|
34
|
+
- **Avatar** — 사람이나 팀을 나타내는 이름 배지. → [`agents/avatar/AGENTS.md`](avatar/AGENTS.md)
|
|
35
|
+
- **IconTile** — 아이콘이나 글자 하나를 담는 작은 채움 타일. → [`agents/icon-tile/AGENTS.md`](icon-tile/AGENTS.md)
|
|
36
|
+
- **IconStack** — 작은 아이콘 · 로고 2–3개를 겹쳐 한 줄로 보여 줘요. → [`agents/icon-stack/AGENTS.md`](icon-stack/AGENTS.md)
|
|
37
|
+
- **BrandIcon** — 연동 앱의 원래 색 로고. → [`agents/brand-icon/AGENTS.md`](brand-icon/AGENTS.md)
|
|
38
|
+
- **StatusIcon** — 체크리스트 · 일정 행 앞에 붙는 작은 단계 아이콘. → [`agents/status-icon/AGENTS.md`](status-icon/AGENTS.md)
|
|
39
|
+
|
|
40
|
+
## 텍스트 입력
|
|
41
|
+
|
|
42
|
+
- **Input** — 글자를 입력받는 기본 입력창과 Field · Textarea · NativeSelect. → [`agents/input/AGENTS.md`](input/AGENTS.md)
|
|
43
|
+
- **SearchInput** — 돋보기 아이콘이 붙은 검색 입력창. → [`agents/search-input/AGENTS.md`](search-input/AGENTS.md)
|
|
44
|
+
- **TagInput** — 자유롭게 친 글자를 태그로 모으는 입력 칸. → [`agents/tag-input/AGENTS.md`](tag-input/AGENTS.md)
|
|
45
|
+
- **NumberStepper** — − 숫자 + 로 작은 수(작업자 수, 좌석, 재시도 횟수)를 바꿔요. → [`agents/number-stepper/AGENTS.md`](number-stepper/AGENTS.md)
|
|
46
|
+
- **OTP Input** — 인증번호처럼 정해진 자리수의 코드를 입력하는 칸. → [`agents/otp-input/AGENTS.md`](otp-input/AGENTS.md)
|
|
47
|
+
- **PhoneInput** — 국가를 고르고 전화번호를 입력하는 칸. → [`agents/phone-input/AGENTS.md`](phone-input/AGENTS.md)
|
|
48
|
+
- **ChatComposer** — 대화형 AI 화면의 메시지 입력창. → [`agents/chat-composer/AGENTS.md`](chat-composer/AGENTS.md)
|
|
49
|
+
|
|
50
|
+
## 선택 컨트롤
|
|
51
|
+
|
|
52
|
+
- **Checkbox · Radio · Switch** — 켜고 끄는 선택 요소 세 가지. → [`agents/checkbox/AGENTS.md`](checkbox/AGENTS.md)
|
|
53
|
+
- **SegmentedControl** — 몇 개의 보기 · 필터 중 하나를 고르는 컨트롤. → [`agents/segmented-control/AGENTS.md`](segmented-control/AGENTS.md)
|
|
54
|
+
- **ToggleGroup** — 눌러서 켜고 끄는 버튼 묶음. → [`agents/toggle-group/AGENTS.md`](toggle-group/AGENTS.md)
|
|
55
|
+
- **FilterChips** — 목록을 좁히는 필터 칩. → [`agents/filter-chips/AGENTS.md`](filter-chips/AGENTS.md)
|
|
56
|
+
- **Slider** — 끌어서 값을 고르는 슬라이더. → [`agents/slider/AGENTS.md`](slider/AGENTS.md)
|
|
57
|
+
- **Select** — 목록에서 하나를 고르는 커스텀 셀렉트. → [`agents/select/AGENTS.md`](select/AGENTS.md)
|
|
58
|
+
- **MultiSelect** — 목록에서 여러 개를 고르는 셀렉트. → [`agents/multi-select/AGENTS.md`](multi-select/AGENTS.md)
|
|
59
|
+
- **Combobox** — 입력하면서 검색해 고르는 셀렉트. → [`agents/combobox/AGENTS.md`](combobox/AGENTS.md)
|
|
60
|
+
- **DatePicker · Calendar** — 날짜 입력. → [`agents/date-picker/AGENTS.md`](date-picker/AGENTS.md)
|
|
61
|
+
- **ColorPicker** — 색을 고르는 패널. → [`agents/color-picker/AGENTS.md`](color-picker/AGENTS.md)
|
|
62
|
+
- **Rating** — 별점. → [`agents/rating/AGENTS.md`](rating/AGENTS.md)
|
|
63
|
+
- **TimePicker** — 시각 입력. → [`agents/time-picker/AGENTS.md`](time-picker/AGENTS.md)
|
|
64
|
+
|
|
65
|
+
## 파일
|
|
66
|
+
|
|
67
|
+
- **FileIcon** — 파일 종류를 색 띠로 알려 주는 종이 아이콘. → [`agents/file-icon/AGENTS.md`](file-icon/AGENTS.md)
|
|
68
|
+
- **FileChip** — 첨부 파일을 작게 보여 주는 링크형 칩. → [`agents/file-chip/AGENTS.md`](file-chip/AGENTS.md)
|
|
69
|
+
- **Dropzone** — 파일을 끌어 놓거나 눌러서 고르는 영역. → [`agents/dropzone/AGENTS.md`](dropzone/AGENTS.md)
|
|
70
|
+
- **FileUpload** — 파일을 끌어 놓거나 골라서 올리고, 줄마다 → [`agents/file-upload/AGENTS.md`](file-upload/AGENTS.md)
|
|
71
|
+
|
|
72
|
+
## 메뉴 & 오버레이
|
|
73
|
+
|
|
74
|
+
- **DropdownMenu** — 버튼에서 펼쳐지는 동작 메뉴. → [`agents/dropdown-menu/AGENTS.md`](dropdown-menu/AGENTS.md)
|
|
75
|
+
- **ContextMenu** — 마우스 오른쪽 버튼을 누른 자리에서 열리는 메뉴. → [`agents/context-menu/AGENTS.md`](context-menu/AGENTS.md)
|
|
76
|
+
- **Menubar** — 데스크톱 앱처럼 파일 · 편집 · 보기 메뉴를 가로로 늘어놓은 막대. → [`agents/menubar/AGENTS.md`](menubar/AGENTS.md)
|
|
77
|
+
- **CommandMenu** — ⌘K(Windows는 Ctrl+K)로 어디서든 여는 명령 팔레트. → [`agents/command-menu/AGENTS.md`](command-menu/AGENTS.md)
|
|
78
|
+
- **Popover** — 트리거 옆에 붙어 뜨는 작은 패널. → [`agents/popover/AGENTS.md`](popover/AGENTS.md)
|
|
79
|
+
- **HoverCard** — 이름·링크·저장소 위에 잠깐 머물면 뜨는 풍부한 미리보기. → [`agents/hover-card/AGENTS.md`](hover-card/AGENTS.md)
|
|
80
|
+
- **Tooltip** — 아이콘 버튼처럼 글자가 없는 요소에 짧은 설명을 붙여요. → [`agents/tooltip/AGENTS.md`](tooltip/AGENTS.md)
|
|
81
|
+
- **Dialog** — 페이지 위에 뜨는 모달. → [`agents/dialog/AGENTS.md`](dialog/AGENTS.md)
|
|
82
|
+
- **Drawer · Sheet** — 화면 가장자리에서 미끄러져 들어오는 패널. → [`agents/drawer/AGENTS.md`](drawer/AGENTS.md)
|
|
83
|
+
- **AlertDialog** — 되돌릴 수 없는 작업(영구 삭제, 결제, 대량 발송) 바로 앞에 한 번 더 묻는 확인 창. → [`agents/alert-dialog/AGENTS.md`](alert-dialog/AGENTS.md)
|
|
84
|
+
|
|
85
|
+
## 내비게이션
|
|
86
|
+
|
|
87
|
+
- **AppShell** — 앱의 뼈대. → [`agents/app-shell/AGENTS.md`](app-shell/AGENTS.md)
|
|
88
|
+
- **Sidebar** — 세로 내비게이션. → [`agents/sidebar/AGENTS.md`](sidebar/AGENTS.md)
|
|
89
|
+
- **Breadcrumb** — 지금 페이지가 어디에 있는지 보여 주는 경로. → [`agents/breadcrumb/AGENTS.md`](breadcrumb/AGENTS.md)
|
|
90
|
+
- **Tabs** — 같은 자리에서 여러 패널을 바꿔 보여줘요. → [`agents/tabs/AGENTS.md`](tabs/AGENTS.md)
|
|
91
|
+
- **Pagination** — 긴 목록을 페이지로 나눠 이동해요. → [`agents/pagination/AGENTS.md`](pagination/AGENTS.md)
|
|
92
|
+
- **TreeView** — 단계별로 들여쓴 행을 접고 펴는 트리. → [`agents/tree-view/AGENTS.md`](tree-view/AGENTS.md)
|
|
93
|
+
- **NavigationMenu** — 사이트 헤더의 메뉴(제품 · 보안 · 요금). → [`agents/navigation-menu/AGENTS.md`](navigation-menu/AGENTS.md)
|
|
94
|
+
|
|
95
|
+
## 컨테이너
|
|
96
|
+
|
|
97
|
+
- **Card** — 관련 내용을 한 덩어리로 묶는 흰 표면. → [`agents/card/AGENTS.md`](card/AGENTS.md)
|
|
98
|
+
- **CardFrame** — 흰 Card를 옅은 회색 판으로 한 번 더 감싸는 틀. → [`agents/card-frame/AGENTS.md`](card-frame/AGENTS.md)
|
|
99
|
+
- **List** — 사람 · 파일 · 설정처럼 같은 모양의 행을 나열해요. → [`agents/list/AGENTS.md`](list/AGENTS.md)
|
|
100
|
+
- **Accordion · Collapsible** — 내용을 접었다 → [`agents/accordion/AGENTS.md`](accordion/AGENTS.md)
|
|
101
|
+
- **SplitView** — 목록 – 상세(master–detail) 두 칸 레이아웃. → [`agents/split-view/AGENTS.md`](split-view/AGENTS.md)
|
|
102
|
+
- **Resizable** — 경계를 끌어 크기를 나누는 패널 묶음. → [`agents/resizable/AGENTS.md`](resizable/AGENTS.md)
|
|
103
|
+
|
|
104
|
+
## 알림
|
|
105
|
+
|
|
106
|
+
- **Toast** — 잠깐 떠올랐다 → [`agents/toast/AGENTS.md`](toast/AGENTS.md)
|
|
107
|
+
- **Alert · Banner** — 토스트와 달리 화면에 머무르는 메시지. → [`agents/alert/AGENTS.md`](alert/AGENTS.md)
|
|
108
|
+
- **NoticeStack** — 닫을 수 있는 공지 카드 묶음(새 기능 소개, 팁, 점검 안내). → [`agents/notice-stack/AGENTS.md`](notice-stack/AGENTS.md)
|
|
109
|
+
- **EmptyState** — 보여 줄 내용이 없을 때 이유와 다음 행동을 알려 주는 자리. → [`agents/empty-state/AGENTS.md`](empty-state/AGENTS.md)
|
|
110
|
+
|
|
111
|
+
## 진행 표시
|
|
112
|
+
|
|
113
|
+
- **Progress** — 작업이 얼마나 진행됐는지 보여 주는 막대와 원형 표시. → [`agents/progress/AGENTS.md`](progress/AGENTS.md)
|
|
114
|
+
- **Spinner** — 옅은 고리 위로 호가 돌면서 늘었다 → [`agents/spinner/AGENTS.md`](spinner/AGENTS.md)
|
|
115
|
+
- **Skeleton** — 내용이 들어올 자리를 미리 보여 주는 회색 자리 표시. → [`agents/skeleton/AGENTS.md`](skeleton/AGENTS.md)
|
|
116
|
+
- **ProgressTracker** — 온보딩 체크리스트 카드. → [`agents/progress-tracker/AGENTS.md`](progress-tracker/AGENTS.md)
|
|
117
|
+
- **StepList** — 단계를 세로로 이어 보여 주는 읽기 전용 타임라인. → [`agents/step-list/AGENTS.md`](step-list/AGENTS.md)
|
|
118
|
+
- **Countdown** — 남은 시간을 "8초" · "1:05"처럼 글자로 보여 줘요. → [`agents/countdown/AGENTS.md`](countdown/AGENTS.md)
|
|
119
|
+
- **Elapsed** — 시작한 뒤 지난 시간을 "17:40" · "17분 40초"처럼 글자로 올려 세요. → [`agents/elapsed/AGENTS.md`](elapsed/AGENTS.md)
|
|
120
|
+
|
|
121
|
+
## 텍스트 & 코드
|
|
122
|
+
|
|
123
|
+
- **Highlight** — 글 속 일부를 연한 상태색 배경으로 표시해요(warning · accent · danger). → [`agents/highlight/AGENTS.md`](highlight/AGENTS.md)
|
|
124
|
+
- **MaskedText** — 계좌번호 · IBAN · 키처럼 민감한 값을 양 끝만 보이고 가운데는 점 묶음으로 가려요("DE89 •••• 3000"). → [`agents/masked-text/AGENTS.md`](masked-text/AGENTS.md)
|
|
125
|
+
- **CodeBlock** — 읽기 전용 코드 블록. → [`agents/code-block/AGENTS.md`](code-block/AGENTS.md)
|
|
126
|
+
- **InlineDiff** — 글 속 변경 내용(추적된 변경)을 그대로 보여 줘요. → [`agents/inline-diff/AGENTS.md`](inline-diff/AGENTS.md)
|
|
127
|
+
|
|
128
|
+
## 데이터 표시
|
|
129
|
+
|
|
130
|
+
- **Table** — 격자선 없는 데이터 표. → [`agents/table/AGENTS.md`](table/AGENTS.md)
|
|
131
|
+
- **DataGrid** — Notion 데이터베이스처럼 타입이 있는 속성과 보기(정렬·필터·그룹·검색)를, Google Sheets·Numbers처럼 범위 선택·키보드 편집·복사/붙여넣기·채우기 핸들을 갖춘 표. → [`agents/data-grid/AGENTS.md`](data-grid/AGENTS.md)
|
|
132
|
+
- **Kanban** — 열 사이로 카드를 끌어 옮기는 보드. → [`agents/kanban/AGENTS.md`](kanban/AGENTS.md)
|
|
133
|
+
- **DescriptionList** — 라벨 · 값 쌍을 진짜 <dl>로 보여 줘요. → [`agents/description-list/AGENTS.md`](description-list/AGENTS.md)
|
|
134
|
+
- **Stat** — 라벨과 숫자 하나. → [`agents/stat/AGENTS.md`](stat/AGENTS.md)
|
|
135
|
+
- **Delta** — 이전 · 목표와 비교한 증감을 부호와 함께 보여 줘요. → [`agents/delta/AGENTS.md`](delta/AGENTS.md)
|
|
136
|
+
- **Tracker** — 하루(또는 한 시간)에 한 칸씩 상태를 색으로 늘어놓은 기록 띠. → [`agents/tracker/AGENTS.md`](tracker/AGENTS.md)
|
|
137
|
+
- **TreeDiagram** — 조직도 · 작업 분해처럼 위계를 상자와 연결선으로 그려요. → [`agents/tree-diagram/AGENTS.md`](tree-diagram/AGENTS.md)
|
|
138
|
+
|
|
139
|
+
## 대화 & 활동
|
|
140
|
+
|
|
141
|
+
- **Comment** — 댓글 · 토론의 메시지 한 개. → [`agents/comment/AGENTS.md`](comment/AGENTS.md)
|
|
142
|
+
- **ChatBubble** — 채팅 메시지 한 개를 채워진 말풍선으로 보여 줘요. → [`agents/chat-bubble/AGENTS.md`](chat-bubble/AGENTS.md)
|
|
143
|
+
- **Marker** — 대화 · 활동 기록 사이에 끼는 이벤트 한 줄. → [`agents/marker/AGENTS.md`](marker/AGENTS.md)
|
|
144
|
+
- **Timeline** — 숫자 구간(초, 분, 시각)을 가로 위치로 옮겨 그리는 시간 축. → [`agents/timeline/AGENTS.md`](timeline/AGENTS.md)
|
|
145
|
+
|
|
146
|
+
## 차트
|
|
147
|
+
|
|
148
|
+
- **LineChart** — 여러 시리즈의 추이를 비교하는 선 차트. → [`agents/line-chart/AGENTS.md`](line-chart/AGENTS.md)
|
|
149
|
+
- **AreaChart** — 양의 크기와 구성을 함께 보여 주는 영역 차트. → [`agents/area-chart/AGENTS.md`](area-chart/AGENTS.md)
|
|
150
|
+
- **BarChart** — 항목끼리 크기를 비교하는 막대 차트. → [`agents/bar-chart/AGENTS.md`](bar-chart/AGENTS.md)
|
|
151
|
+
- **PieChart** — 전체 중 각 부분의 비율을 보여주는 도넛·원 차트. → [`agents/pie-chart/AGENTS.md`](pie-chart/AGENTS.md)
|
|
152
|
+
- **ScatterChart** — 두 값의 관계를 점으로 보여주는 산점도. → [`agents/scatter-chart/AGENTS.md`](scatter-chart/AGENTS.md)
|
|
153
|
+
- **FunnelChart** — 단계별 전환을 보여주는 퍼널 차트. → [`agents/funnel-chart/AGENTS.md`](funnel-chart/AGENTS.md)
|
|
154
|
+
- **BarList** — 많이 본 페이지 · 유입 경로 · 국가처럼 순위를 매긴 가로 막대 목록. → [`agents/bar-list/AGENTS.md`](bar-list/AGENTS.md)
|
|
155
|
+
- **SparkChart** — 축 없이 흐름만 보여 주는 아주 작은 차트. → [`agents/spark-chart/AGENTS.md`](spark-chart/AGENTS.md)
|
|
156
|
+
- **Sparkbar** — 축 없이 막대만 늘어놓은 작은 막대 줄. → [`agents/sparkbar/AGENTS.md`](sparkbar/AGENTS.md)
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Accordion · Collapsible
|
|
2
|
+
|
|
3
|
+
> 컨테이너 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
|
|
4
|
+
|
|
5
|
+
내용을 접었다 펴는 섹션. Collapsible은 하나짜리, Accordion은 여러 개를 묶어 하나만 또는 여러 개를 열어 둬요. 실제 높이만큼 부드럽게 펼쳐지고, 헤더 사이를 ↑ ↓ · Home / End로 이동해요.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Accordion, AccordionItem, Collapsible } from '@iamfiro/design'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 디자인 규칙
|
|
12
|
+
|
|
13
|
+
- 접고 펴는 영역(Accordion, Sidebar 그룹)은 `grid-template-rows: 0fr ↔ 1fr`로 실제 높이까지 애니메이션. 글 안의 작은 상태 줄·"자세히" 토글은 새로 만들지 말고 `Collapsible variant="inline"`.
|
|
14
|
+
|
|
15
|
+
## API
|
|
16
|
+
|
|
17
|
+
### Accordion
|
|
18
|
+
|
|
19
|
+
| prop | 타입 | 기본값 | 설명 |
|
|
20
|
+
| --- | --- | --- | --- |
|
|
21
|
+
| `type` (필수) | `'single' \| 'multiple'` | | 하나만 열기 / 여러 개 열기. |
|
|
22
|
+
| `value` | `string \| null / string[]` | | 열린 항목(제어). single이면 값 하나, multiple이면 배열. |
|
|
23
|
+
| `defaultValue` | `string \| null / string[]` | | 처음 열린 항목(비제어). |
|
|
24
|
+
| `onValueChange` | `(value) => void` | | 열린 항목이 바뀔 때. |
|
|
25
|
+
| `required` | `boolean` | | single 전용. 열린 항목을 다시 눌러도 닫히지 않아요. |
|
|
26
|
+
| `variant` | `'plain' \| 'separated' \| 'filled'` | `'plain'` | plain: 여백으로 구분 · separated: 항목마다 흰 카드 · filled: 열린 항목이 옅은 회색 판 위에(카드 안 그룹 체크리스트). |
|
|
27
|
+
| `className` | `string` | | 바깥 요소에 전달. |
|
|
28
|
+
|
|
29
|
+
### AccordionItem
|
|
30
|
+
|
|
31
|
+
Accordion.Item으로도 쓸 수 있어요.
|
|
32
|
+
|
|
33
|
+
| prop | 타입 | 기본값 | 설명 |
|
|
34
|
+
| --- | --- | --- | --- |
|
|
35
|
+
| `value` (필수) | `string` | | 항목 고유 값. |
|
|
36
|
+
| `title` (필수) | `ReactNode` | | 헤더 제목. |
|
|
37
|
+
| `children` (필수) | `ReactNode` | | 펼쳐질 내용. |
|
|
38
|
+
| `description` | `ReactNode` | | 제목 아래 회색 설명. |
|
|
39
|
+
| `icon` | `ReactNode` | | 제목 앞 아이콘. |
|
|
40
|
+
| `disabled` | `boolean` | | 비활성. 열리지 않아요. |
|
|
41
|
+
| `flush` | `boolean` | | 내용 좌우 여백을 없애요. 안에 List를 넣으면 행 여백(12px)이 filled 제목과 왼쪽 끝을 맞춰요. |
|
|
42
|
+
|
|
43
|
+
### Collapsible
|
|
44
|
+
|
|
45
|
+
| prop | 타입 | 기본값 | 설명 |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `label` (필수) | `ReactNode` | | 항상 보이는 헤더(토글 버튼 안). |
|
|
48
|
+
| `children` (필수) | `ReactNode` | | 펼쳐질 내용. |
|
|
49
|
+
| `open` | `boolean` | | 열림 상태(제어). |
|
|
50
|
+
| `defaultOpen` | `boolean` | `false` | 처음 열림 상태(비제어). |
|
|
51
|
+
| `onOpenChange` | `(open: boolean) => void` | | 열리거나 닫힐 때. |
|
|
52
|
+
| `description` | `ReactNode` | | 헤더 아래 설명. |
|
|
53
|
+
| `icon` | `ReactNode` | | 헤더 앞 아이콘. |
|
|
54
|
+
| `disabled` | `boolean` | | 비활성. |
|
|
55
|
+
| `variant` | `'default' \| 'inline'` | `'default'` | default: 폭을 채우는 헤더 행 · inline: 글자 크기만 한 작은 토글(제목 요소가 아닌 div). |
|
|
56
|
+
| `iconTone` | `'default' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'default'` | 앞 아이콘 색. |
|
|
57
|
+
| `className` | `string` | | 바깥 요소에 전달. |
|
|
58
|
+
|
|
59
|
+
## 예제
|
|
60
|
+
|
|
61
|
+
예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
|
|
62
|
+
|
|
63
|
+
### 하나만 열기 (FAQ)
|
|
64
|
+
|
|
65
|
+
type="single"은 하나를 열면 나머지가 닫혀요. required를 주면 열린 항목을 다시 눌러도 모두 닫히지는 않아요.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Box, Text, Accordion, AccordionItem } from '@iamfiro/design'
|
|
69
|
+
|
|
70
|
+
const FAQ = [
|
|
71
|
+
{ value: 'refund', q: '환불은 어떻게 받나요?', a: '결제일로부터 14일 안에 설정 › 결제에서 환불을 요청하면 3영업일 안에 처리돼요.' },
|
|
72
|
+
{ value: 'seats', q: '멤버를 추가하면 요금이 바로 바뀌나요?', a: '추가한 날부터 남은 기간만큼 일할 계산돼 다음 결제에 함께 청구돼요.' },
|
|
73
|
+
{ value: 'export', q: '데이터를 내보낼 수 있나요?', a: '모든 요금제에서 CSV와 JSON으로 내보낼 수 있어요. 큰 파일은 완료되면 이메일로 링크를 보내 드려요.' },
|
|
74
|
+
{ value: 'cancel', q: '해지하면 데이터는 어떻게 되나요?', a: '해지 후 30일 동안 보관되고, 그 안에 다시 구독하면 그대로 복구돼요.' },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
export default function Example() {
|
|
78
|
+
return (
|
|
79
|
+
<Box style={{ width: 520 }}>
|
|
80
|
+
<Accordion type="single" defaultValue="refund">
|
|
81
|
+
{FAQ.map((item) => (
|
|
82
|
+
<AccordionItem key={item.value} value={item.value} title={item.q}>
|
|
83
|
+
<Text variant="body-sm" tone="secondary">
|
|
84
|
+
{item.a}
|
|
85
|
+
</Text>
|
|
86
|
+
</AccordionItem>
|
|
87
|
+
))}
|
|
88
|
+
</Accordion>
|
|
89
|
+
</Box>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 여러 개 열기
|
|
95
|
+
|
|
96
|
+
type="multiple"은 여러 항목을 함께 열어 둬요. value / onValueChange로 제어하면 모두 펼치기 · 접기도 만들 수 있어요.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { useState } from 'react'
|
|
100
|
+
import { Button, Inline, Stack, Text, Accordion, AccordionItem } from '@iamfiro/design'
|
|
101
|
+
|
|
102
|
+
const SECTIONS = [
|
|
103
|
+
{ value: 'scope', title: '범위', body: '랜딩 페이지, 가격 페이지, 온보딩 3단계를 새 디자인 시스템으로 옮겨요.' },
|
|
104
|
+
{ value: 'schedule', title: '일정', body: '10월 28일 디자인 확정, 11월 4일 개발 완료, 11월 7일 출시.' },
|
|
105
|
+
{ value: 'owners', title: '담당자', body: '디자인 김민지 · 프론트엔드 이도현 · QA 박서연.' },
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
const ALL = SECTIONS.map((s) => s.value)
|
|
109
|
+
|
|
110
|
+
export default function Example() {
|
|
111
|
+
const [open, setOpen] = useState<string[]>(['scope'])
|
|
112
|
+
const allOpen = open.length === ALL.length
|
|
113
|
+
return (
|
|
114
|
+
<Stack gap={3} style={{ width: 520 }}>
|
|
115
|
+
<Inline justify="between">
|
|
116
|
+
<Text variant="label-md">출시 계획</Text>
|
|
117
|
+
<Button variant="ghost" size="sm" onClick={() => setOpen(allOpen ? [] : ALL)}>
|
|
118
|
+
{allOpen ? '모두 접기' : '모두 펼치기'}
|
|
119
|
+
</Button>
|
|
120
|
+
</Inline>
|
|
121
|
+
<Accordion type="multiple" value={open} onValueChange={setOpen}>
|
|
122
|
+
{SECTIONS.map((s) => (
|
|
123
|
+
<AccordionItem key={s.value} value={s.value} title={s.title}>
|
|
124
|
+
<Text variant="body-sm" tone="secondary">
|
|
125
|
+
{s.body}
|
|
126
|
+
</Text>
|
|
127
|
+
</AccordionItem>
|
|
128
|
+
))}
|
|
129
|
+
</Accordion>
|
|
130
|
+
</Stack>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 카드형
|
|
136
|
+
|
|
137
|
+
variant="separated"는 항목마다 흰 카드에 올려요. icon과 description으로 헤더를 풍부하게. disabled 항목은 열리지 않아요.
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { Bell, CreditCard, Lock, Users } from 'lucide-react'
|
|
141
|
+
import { Box, Switch, Stack, Text, Accordion, AccordionItem } from '@iamfiro/design'
|
|
142
|
+
|
|
143
|
+
export default function Example() {
|
|
144
|
+
return (
|
|
145
|
+
<Box style={{ width: 520 }}>
|
|
146
|
+
<Accordion type="single" variant="separated" defaultValue="notifications">
|
|
147
|
+
<AccordionItem value="notifications" icon={<Bell />} title="알림" description="이메일 · 푸시 · 요약 메일">
|
|
148
|
+
<Stack gap={3}>
|
|
149
|
+
<Switch label="멘션되면 푸시 알림" defaultChecked />
|
|
150
|
+
<Switch label="매주 월요일 요약 메일" />
|
|
151
|
+
</Stack>
|
|
152
|
+
</AccordionItem>
|
|
153
|
+
<AccordionItem value="members" icon={<Users />} title="멤버" description="6명 · 관리자 2명">
|
|
154
|
+
<Text variant="body-sm" tone="secondary">
|
|
155
|
+
김민지님과 이도현님이 관리자예요. 역할은 멤버 페이지에서 바꿀 수 있어요.
|
|
156
|
+
</Text>
|
|
157
|
+
</AccordionItem>
|
|
158
|
+
<AccordionItem value="billing" icon={<CreditCard />} title="결제" description="팀 요금제 · 다음 결제 11월 1일">
|
|
159
|
+
<Text variant="body-sm" tone="secondary">
|
|
160
|
+
신한카드 •••• 4821로 매월 1일에 결제돼요.
|
|
161
|
+
</Text>
|
|
162
|
+
</AccordionItem>
|
|
163
|
+
<AccordionItem value="sso" icon={<Lock />} title="SSO" description="엔터프라이즈 요금제에서 쓸 수 있어요" disabled>
|
|
164
|
+
SAML 설정
|
|
165
|
+
</AccordionItem>
|
|
166
|
+
</Accordion>
|
|
167
|
+
</Box>
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 회색 판 (variant="filled")
|
|
173
|
+
|
|
174
|
+
열린 항목이 옅은 회색 판 위에 놓여요. 카드 안에서 그룹을 나눌 때(ProgressTracker groups). flush 항목 안의 List 행은 제목과 왼쪽 끝이 맞고, ListItem variant="raised"면 회색 판 위에서도 hover가 보여요.
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { CalendarDays, CreditCard, Users } from 'lucide-react'
|
|
178
|
+
import { Box, Accordion, AccordionItem, Card, List, ListItem } from '@iamfiro/design'
|
|
179
|
+
|
|
180
|
+
export default function Example() {
|
|
181
|
+
return (
|
|
182
|
+
<Card style={{ width: 360 }}>
|
|
183
|
+
{/* 4px 안쪽에 회색 판, 판 안의 12px 여백이 카드의 16px 왼쪽 끝과 맞아요. */}
|
|
184
|
+
<Box padding={1}>
|
|
185
|
+
<Accordion type="single" defaultValue="team" variant="filled">
|
|
186
|
+
<AccordionItem value="team" title="팀 설정" flush>
|
|
187
|
+
<List aria-label="팀 설정">
|
|
188
|
+
<ListItem variant="raised" leading={<Users />} title="멤버 관리" description="김민지 외 5명" onClick={() => {}} />
|
|
189
|
+
<ListItem variant="raised" leading={<CalendarDays />} title="근무 일정" description="평일 9시 – 18시" onClick={() => {}} />
|
|
190
|
+
</List>
|
|
191
|
+
</AccordionItem>
|
|
192
|
+
<AccordionItem value="billing" title="결제" flush>
|
|
193
|
+
<List aria-label="결제">
|
|
194
|
+
<ListItem variant="raised" leading={<CreditCard />} title="결제 수단" description="법인 카드 · 끝자리 2048" onClick={() => {}} />
|
|
195
|
+
</List>
|
|
196
|
+
</AccordionItem>
|
|
197
|
+
<AccordionItem value="notice" title="공지">
|
|
198
|
+
새 공지는 매주 월요일 오전에 올라와요. 지난 공지는 보관함에서 다시 볼 수 있어요.
|
|
199
|
+
</AccordionItem>
|
|
200
|
+
</Accordion>
|
|
201
|
+
</Box>
|
|
202
|
+
</Card>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Collapsible
|
|
208
|
+
|
|
209
|
+
섹션 하나만 접을 때. open / onOpenChange로 제어하거나 defaultOpen으로 비제어.
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
import { useState } from 'react'
|
|
213
|
+
import { Settings2 } from 'lucide-react'
|
|
214
|
+
import { Button, Field, Inline, Input, Stack, Switch, Collapsible } from '@iamfiro/design'
|
|
215
|
+
|
|
216
|
+
export default function Example() {
|
|
217
|
+
const [advanced, setAdvanced] = useState(false)
|
|
218
|
+
return (
|
|
219
|
+
<Stack as="form" gap={5} style={{ width: 440 }} onSubmit={(e) => e.preventDefault()}>
|
|
220
|
+
<Field label="웹훅 URL" htmlFor="hook-url">
|
|
221
|
+
<Input id="hook-url" placeholder="https://example.com/hooks/lumen" />
|
|
222
|
+
</Field>
|
|
223
|
+
<Collapsible
|
|
224
|
+
icon={<Settings2 />}
|
|
225
|
+
label="고급 설정"
|
|
226
|
+
description={advanced ? undefined : '재시도 · 타임아웃 · 서명'}
|
|
227
|
+
open={advanced}
|
|
228
|
+
onOpenChange={setAdvanced}
|
|
229
|
+
>
|
|
230
|
+
<Stack gap={4}>
|
|
231
|
+
<Field label="타임아웃 (초)" htmlFor="hook-timeout">
|
|
232
|
+
<Input id="hook-timeout" type="number" defaultValue={10} />
|
|
233
|
+
</Field>
|
|
234
|
+
<Switch label="실패하면 3번까지 다시 보내기" defaultChecked />
|
|
235
|
+
<Switch label="요청에 서명 헤더 붙이기" />
|
|
236
|
+
</Stack>
|
|
237
|
+
</Collapsible>
|
|
238
|
+
<Inline justify="end">
|
|
239
|
+
<Button variant="primary" type="submit">
|
|
240
|
+
저장
|
|
241
|
+
</Button>
|
|
242
|
+
</Inline>
|
|
243
|
+
</Stack>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 인라인 상태 줄 (variant="inline")
|
|
249
|
+
|
|
250
|
+
글자 크기만 한 작은 토글(아이콘 + 라벨 + 회전하는 chevron). 메시지 아래 "수정 완료" 같은 상태 줄이나 "자세히 보기"에 써요. iconTone으로 아이콘 색을 정하고, 펼치면 실제 높이만큼 부드럽게 열려요.
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import { CircleAlert, CircleCheck, ListTree } from 'lucide-react'
|
|
254
|
+
import { Stack, Text, Collapsible } from '@iamfiro/design'
|
|
255
|
+
|
|
256
|
+
export default function Example() {
|
|
257
|
+
return (
|
|
258
|
+
<Stack gap={4} style={{ width: 360 }}>
|
|
259
|
+
<Stack gap={1}>
|
|
260
|
+
<Text variant="body-md">소개 문단을 두 문장으로 줄였어요.</Text>
|
|
261
|
+
<Collapsible variant="inline" icon={<CircleCheck />} iconTone="success" label="수정 완료" defaultOpen>
|
|
262
|
+
3문장 → 2문장 · 128자 줄임 · 맞춤법 2곳 고침
|
|
263
|
+
</Collapsible>
|
|
264
|
+
</Stack>
|
|
265
|
+
<Stack gap={1}>
|
|
266
|
+
<Text variant="body-md">첨부한 표 일부를 읽지 못했어요.</Text>
|
|
267
|
+
<Collapsible variant="inline" icon={<CircleAlert />} iconTone="warning" label="2개 항목 건너뜀">
|
|
268
|
+
3행과 7행의 날짜 형식이 달라요. 2026-10-25처럼 맞춰 다시 올려 주세요.
|
|
269
|
+
</Collapsible>
|
|
270
|
+
</Stack>
|
|
271
|
+
<Collapsible variant="inline" icon={<ListTree />} label="자세히 보기">
|
|
272
|
+
<Text variant="body-sm" tone="secondary">
|
|
273
|
+
아이콘이 없으면 내용은 왼쪽 끝에, 있으면 라벨과 같은 선에 맞춰져요.
|
|
274
|
+
</Text>
|
|
275
|
+
</Collapsible>
|
|
276
|
+
</Stack>
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
```
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# ActionBar
|
|
2
|
+
|
|
3
|
+
> 버튼 & 링크 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
|
|
4
|
+
|
|
5
|
+
상세 화면 · 검토 화면 아래에 붙는 동작 바. 흰 바탕에 위쪽으로 옅은 그림자만 있고 선은 없어요. 스크롤되는 영역 안에서 아래에 붙어 있고(sticky), 단축키 힌트가 있는 Button(shortcut · hotkey)을 모아 둬요. pending이면 안의 버튼과 단축키가 한꺼번에 잠겨요.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { ActionBar } from '@iamfiro/design'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 디자인 규칙
|
|
12
|
+
|
|
13
|
+
- 단축키가 있는 버튼은 `Button shortcut`(힌트만) + `hotkey`(듣기: 입력 중 글자 키 · IME 조합 · 비활성은 무시). 여러 개는 `ActionBar`(흰 바탕 + 위 그림자, `pending`이면 fieldset으로 한꺼번에 잠금).
|
|
14
|
+
|
|
15
|
+
## API
|
|
16
|
+
|
|
17
|
+
### ActionBar
|
|
18
|
+
|
|
19
|
+
| prop | 타입 | 기본값 | 설명 |
|
|
20
|
+
| --- | --- | --- | --- |
|
|
21
|
+
| `children` (필수) | `ReactNode` | | 보통 shortcut이 있는 Button들. |
|
|
22
|
+
| `align` | `'start' \| 'center' \| 'end' \| 'between'` | `'center'` | 버튼 정렬. between은 두 묶음을 양 끝으로. |
|
|
23
|
+
| `sticky` | `boolean` | `true` | 스크롤 영역의 아래에 붙어 있어요. |
|
|
24
|
+
| `pending` | `boolean` | | 처리 중. 안의 모든 컨트롤을 비활성 fieldset으로 한꺼번에 잠가요(단축키 포함, aria-busy). |
|
|
25
|
+
| `aria-label` | `string` | | 동작 묶음의 이름(예: "요청 처리"). |
|
|
26
|
+
| `className / style` | `string / CSSProperties` | | 바깥 요소에 전달. |
|
|
27
|
+
|
|
28
|
+
## 예제
|
|
29
|
+
|
|
30
|
+
예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
|
|
31
|
+
|
|
32
|
+
### 검토 동작 + 처리 중 잠금
|
|
33
|
+
|
|
34
|
+
승인 A · 수정 E · 거절 R · 건너뛰기 S. 누르거나 키를 누르면 처리하는 동안(pending) 모든 버튼과 단축키가 잠기고, 끝나면 다음 요청으로 넘어가요.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { useEffect, useState } from 'react'
|
|
38
|
+
import { Check, ChevronsRight, Pencil, X } from 'lucide-react'
|
|
39
|
+
import { Box, Button, Stack, Text, ActionBar, Card, toast } from '@iamfiro/design'
|
|
40
|
+
|
|
41
|
+
const REQUESTS = ['10월 법인 카드 정산', '이도현 님 계정 권한 요청', '협력사 계약서 검토']
|
|
42
|
+
|
|
43
|
+
export default function Example() {
|
|
44
|
+
const [index, setIndex] = useState(0)
|
|
45
|
+
const [pending, setPending] = useState<string | null>(null)
|
|
46
|
+
|
|
47
|
+
// 데모용 처리: 0.8초 뒤 다음 요청으로 넘어가요. 그동안 버튼과 단축키가 함께 잠겨요.
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!pending) return
|
|
50
|
+
const id = window.setTimeout(() => {
|
|
51
|
+
toast.success(`${pending} 처리했어요`)
|
|
52
|
+
setPending(null)
|
|
53
|
+
setIndex((i) => (i + 1) % REQUESTS.length)
|
|
54
|
+
}, 800)
|
|
55
|
+
return () => window.clearTimeout(id)
|
|
56
|
+
}, [pending])
|
|
57
|
+
|
|
58
|
+
const act = (label: string) => () => setPending(label)
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Card padding="none" style={{ width: 520 }}>
|
|
62
|
+
<Box padding={5}>
|
|
63
|
+
<Stack gap={1}>
|
|
64
|
+
<Text variant="caption" tone="tertiary">
|
|
65
|
+
승인 요청 {index + 1} / {REQUESTS.length}
|
|
66
|
+
</Text>
|
|
67
|
+
<Text variant="heading-sm">{REQUESTS[index]}</Text>
|
|
68
|
+
<Text variant="body-sm" tone="secondary">
|
|
69
|
+
김민지 님이 2분 전에 보냈어요. A · E · R · S 키로도 처리할 수 있어요.
|
|
70
|
+
</Text>
|
|
71
|
+
</Stack>
|
|
72
|
+
</Box>
|
|
73
|
+
<ActionBar pending={pending !== null} aria-label="요청 처리">
|
|
74
|
+
<Button variant="primary" icon={<Check />} shortcut="A" hotkey loading={pending === '승인'} onClick={act('승인')}>
|
|
75
|
+
승인
|
|
76
|
+
</Button>
|
|
77
|
+
<Button variant="ghost" icon={<Pencil />} shortcut="E" hotkey onClick={act('수정')}>
|
|
78
|
+
수정
|
|
79
|
+
</Button>
|
|
80
|
+
<Button variant="ghost" icon={<X />} shortcut="R" hotkey onClick={act('거절')}>
|
|
81
|
+
거절
|
|
82
|
+
</Button>
|
|
83
|
+
<Button variant="ghost" icon={<ChevronsRight />} shortcut="S" hotkey onClick={act('건너뛰기')}>
|
|
84
|
+
건너뛰기
|
|
85
|
+
</Button>
|
|
86
|
+
</ActionBar>
|
|
87
|
+
</Card>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
```
|