@nexus-cross/design-system 1.0.4-beta.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cursor-rules/nexus-project-setup.mdc +167 -145
- package/cursor-rules/nexus-ui-api.mdc +894 -311
- package/cursor-rules/nexus-ui-components.mdc +179 -91
- package/dist/accordion.js +7 -7
- package/dist/accordion.mjs +2 -2
- package/dist/alert.d.mts +17 -0
- package/dist/alert.d.ts +17 -0
- package/dist/alert.js +16 -0
- package/dist/alert.mjs +3 -0
- package/dist/avatar.js +4 -4
- package/dist/avatar.mjs +2 -2
- package/dist/badge.d.mts +18 -0
- package/dist/badge.d.ts +18 -0
- package/dist/badge.js +16 -0
- package/dist/badge.mjs +3 -0
- package/dist/breadcrumb.d.mts +15 -0
- package/dist/breadcrumb.d.ts +15 -0
- package/dist/breadcrumb.js +12 -0
- package/dist/breadcrumb.mjs +3 -0
- package/dist/button.js +4 -4
- package/dist/button.mjs +2 -2
- package/dist/carousel.js +8 -8
- package/dist/carousel.mjs +2 -2
- package/dist/checkbox.js +5 -5
- package/dist/checkbox.mjs +2 -2
- package/dist/chip.d.mts +1 -1
- package/dist/chip.d.ts +1 -1
- package/dist/chip.js +4 -4
- package/dist/chip.mjs +2 -2
- package/dist/chunks/{chunk-5TBXVD56.js → chunk-2MC7XJSE.js} +16 -6
- package/dist/chunks/chunk-2N2EPBO4.js +120 -0
- package/dist/chunks/{chunk-BEA727LO.mjs → chunk-2RPRCWKV.mjs} +57 -26
- package/dist/chunks/chunk-2UPGFY6E.mjs +76 -0
- package/dist/chunks/{chunk-5I2VRWWU.js → chunk-2ZXDXO4I.js} +32 -38
- package/dist/chunks/{chunk-RLP3U52D.mjs → chunk-33UFQJIO.mjs} +22 -40
- package/dist/chunks/{chunk-AOVU67NI.mjs → chunk-3HHJORN7.mjs} +23 -25
- package/dist/chunks/{chunk-TWHDXCKR.js → chunk-3PCNRCTB.js} +8 -8
- package/dist/chunks/chunk-3ZWN66YH.js +53 -0
- package/dist/chunks/chunk-4ENXP7WH.js +224 -0
- package/dist/chunks/{chunk-YEGPB7A7.js → chunk-5JHJNN2K.js} +4 -4
- package/dist/chunks/chunk-5PQ3UCKF.js +99 -0
- package/dist/chunks/chunk-6BWOKTVQ.mjs +87 -0
- package/dist/chunks/chunk-6DBRL6NA.mjs +81 -0
- package/dist/chunks/{chunk-C3E7CSKG.mjs → chunk-6FMDO6TT.mjs} +7 -8
- package/dist/chunks/{chunk-76CY4STF.js → chunk-7G65JBTN.js} +34 -66
- package/dist/chunks/{chunk-GMIGQ5VP.mjs → chunk-ADO7PDLY.mjs} +15 -35
- package/dist/chunks/{chunk-ZINDMFOI.js → chunk-AFSEYJZT.js} +24 -32
- package/dist/chunks/chunk-B5O6W3Z4.mjs +73 -0
- package/dist/chunks/{chunk-6FHK6CBR.js → chunk-B6G5TJRO.js} +7 -8
- package/dist/chunks/chunk-BBLBTOP4.js +205 -0
- package/dist/chunks/{chunk-5XVEYVYA.js → chunk-BLGQHR3M.js} +5 -8
- package/dist/chunks/{chunk-LVTD2UQN.mjs → chunk-BPUQ2CO2.mjs} +2 -2
- package/dist/chunks/{chunk-AWBGWBFS.js → chunk-BSZ2LN6E.js} +21 -27
- package/dist/chunks/chunk-C2DSAJTL.js +109 -0
- package/dist/chunks/{chunk-KWPIEHD2.mjs → chunk-CA3SOLI3.mjs} +1 -1
- package/dist/chunks/{chunk-MPKRXMCJ.js → chunk-CSJDDREF.js} +7 -10
- package/dist/chunks/chunk-CUTMLBC3.mjs +86 -0
- package/dist/chunks/chunk-CV4GMFWP.js +174 -0
- package/dist/chunks/{chunk-SXLMI7CZ.mjs → chunk-CWMLTXOH.mjs} +162 -234
- package/dist/chunks/chunk-CZC76ZD5.js +10 -0
- package/dist/chunks/chunk-DICN6GKE.js +99 -0
- package/dist/chunks/{chunk-TLTEUIBY.js → chunk-DLFV7ZZV.js} +4 -4
- package/dist/chunks/chunk-DO6VK2QQ.mjs +108 -0
- package/dist/chunks/chunk-DYPPVXQF.js +143 -0
- package/dist/chunks/{chunk-GQP7IXH2.mjs → chunk-ECVAVQUY.mjs} +23 -31
- package/dist/chunks/{chunk-3CHRUKSJ.mjs → chunk-EHAUUUWB.mjs} +3 -3
- package/dist/chunks/chunk-EJY7IVSK.mjs +31 -0
- package/dist/chunks/{chunk-G4XJG7XI.js → chunk-EVOOTSY5.js} +3 -10
- package/dist/chunks/chunk-FUIBYZZ4.mjs +98 -0
- package/dist/chunks/{chunk-VH5FF6DZ.mjs → chunk-GX6GSWX3.mjs} +7 -7
- package/dist/chunks/chunk-H2G5FMRN.mjs +75 -0
- package/dist/chunks/chunk-H2V7RHYV.mjs +120 -0
- package/dist/chunks/{chunk-DDMZSNTG.js → chunk-HFBTS42N.js} +168 -240
- package/dist/chunks/{chunk-OGUTGD4J.mjs → chunk-HNLI646G.mjs} +71 -39
- package/dist/chunks/{chunk-C6H2UNOX.js → chunk-IE4DGLMH.js} +13 -21
- package/dist/chunks/{chunk-U76LT5GE.js → chunk-IOSIQLZL.js} +2 -2
- package/dist/chunks/{chunk-ZCMKIB5U.js → chunk-J5ZKGPBY.js} +33 -41
- package/dist/chunks/{chunk-JUZHWKGS.mjs → chunk-K2TBLM3F.mjs} +6 -12
- package/dist/chunks/chunk-KZ7S5VN2.js +7 -0
- package/dist/chunks/{chunk-FHPHDK3O.mjs → chunk-LI7SFBUQ.mjs} +4 -4
- package/dist/chunks/{chunk-7OEK2KX3.mjs → chunk-LMMON5AU.mjs} +4 -4
- package/dist/chunks/{chunk-6DZVNFVY.js → chunk-LOQXCHKL.js} +4 -12
- package/dist/chunks/{chunk-377KBJQG.js → chunk-MA2VCCIY.js} +19 -22
- package/dist/chunks/chunk-MCKOWMLS.mjs +8 -0
- package/dist/chunks/chunk-MMCA33FW.mjs +85 -0
- package/dist/chunks/{chunk-TR5JBBEA.mjs → chunk-MRRKW5QN.mjs} +31 -39
- package/dist/chunks/{chunk-76K6KXCT.js → chunk-NFIPQZ4O.js} +1 -1
- package/dist/chunks/chunk-NZHK76R3.js +109 -0
- package/dist/chunks/{chunk-I7YJB2F5.js → chunk-OMN5YQCE.js} +3 -3
- package/dist/chunks/{chunk-B7UU3FSS.mjs → chunk-P2T72N62.mjs} +4 -7
- package/dist/chunks/chunk-P3DZKXG4.js +116 -0
- package/dist/chunks/chunk-P73MEU7N.mjs +150 -0
- package/dist/chunks/chunk-PDJTSQOC.js +59 -0
- package/dist/chunks/{chunk-RXVYL4AU.js → chunk-PEIEVKD5.js} +7 -13
- package/dist/chunks/chunk-PI464222.mjs +5 -0
- package/dist/chunks/{chunk-IJG7J2VU.mjs → chunk-QZ4QR3XV.mjs} +30 -36
- package/dist/chunks/{chunk-6NTASYZO.js → chunk-RS3SBY3I.js} +61 -30
- package/dist/chunks/{chunk-AKIBUO5A.mjs → chunk-RX5UKRYK.mjs} +19 -26
- package/dist/chunks/chunk-S2GMEC43.js +109 -0
- package/dist/chunks/{chunk-WJ2OVQD3.mjs → chunk-SGNRVYYQ.mjs} +19 -25
- package/dist/chunks/{chunk-IB5UCYQY.mjs → chunk-SJMCPSVH.mjs} +15 -5
- package/dist/chunks/chunk-UKRU46PH.mjs +182 -0
- package/dist/chunks/{chunk-WNFJ4NJN.mjs → chunk-ULGYTBCT.mjs} +3 -11
- package/dist/chunks/{chunk-TXYYBJBQ.js → chunk-VGO4Z2WH.js} +73 -41
- package/dist/chunks/{chunk-LBKBCI2K.mjs → chunk-VIGRCJAE.mjs} +3 -10
- package/dist/chunks/chunk-VVXQZ4XH.mjs +93 -0
- package/dist/chunks/{chunk-Z7OKV6NW.mjs → chunk-W4GG5A7K.mjs} +12 -20
- package/dist/chunks/chunk-WGGBE4ZD.mjs +201 -0
- package/dist/chunks/{chunk-WSWD5ZUJ.js → chunk-WKCXACMZ.js} +20 -27
- package/dist/chunks/{chunk-GSLIY6WW.js → chunk-X2SHTVZQ.js} +17 -37
- package/dist/chunks/chunk-X3CTJ7TD.js +108 -0
- package/dist/chunks/{chunk-U6KOUYWX.mjs → chunk-XG6QG65W.mjs} +7 -10
- package/dist/chunks/chunk-XGIJZ3NZ.js +160 -0
- package/dist/chunks/chunk-YB5ZKHVB.js +64 -0
- package/dist/chunks/{chunk-Q7H6LCNN.js → chunk-YCG4FZC3.js} +23 -25
- package/dist/chunks/{chunk-JZ3PWHKS.mjs → chunk-YLO4UKSC.mjs} +18 -21
- package/dist/chunks/chunk-YO5MSDPX.mjs +36 -0
- package/dist/chunks/{chunk-Q2TMXHPK.js → chunk-YZV6FWE7.js} +25 -43
- package/dist/chunks/chunk-ZI4LN2B2.js +96 -0
- package/dist/chunks/chunk-ZU4AWAFT.mjs +137 -0
- package/dist/chunks/chunk-ZWSIIGA3.mjs +58 -0
- package/dist/countdown.js +4 -4
- package/dist/countdown.mjs +2 -2
- package/dist/counter.js +2 -2
- package/dist/counter.mjs +1 -1
- package/dist/data-list.js +5 -5
- package/dist/data-list.mjs +4 -4
- package/dist/date-picker.d.mts +17 -0
- package/dist/date-picker.d.ts +17 -0
- package/dist/date-picker.js +12 -0
- package/dist/date-picker.mjs +3 -0
- package/dist/divider.js +4 -4
- package/dist/divider.mjs +2 -2
- package/dist/drawer.d.mts +1 -1
- package/dist/drawer.d.ts +1 -1
- package/dist/drawer.js +11 -11
- package/dist/drawer.mjs +2 -2
- package/dist/dropdown-menu.d.mts +30 -0
- package/dist/dropdown-menu.d.ts +30 -0
- package/dist/dropdown-menu.js +32 -0
- package/dist/dropdown-menu.mjs +3 -0
- package/dist/ellipsis.js +3 -3
- package/dist/ellipsis.mjs +2 -2
- package/dist/empty-state.d.mts +16 -0
- package/dist/empty-state.d.ts +16 -0
- package/dist/empty-state.js +16 -0
- package/dist/empty-state.mjs +3 -0
- package/dist/error-boundary.d.mts +1 -1
- package/dist/error-boundary.d.ts +1 -1
- package/dist/error-boundary.js +2 -2
- package/dist/error-boundary.mjs +1 -1
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +322 -200
- package/dist/index.mjs +49 -35
- package/dist/infinite-scroll.js +3 -3
- package/dist/infinite-scroll.mjs +2 -2
- package/dist/marquee.js +3 -3
- package/dist/marquee.mjs +2 -2
- package/dist/modal/index.js +13 -13
- package/dist/modal/index.mjs +4 -4
- package/dist/number-input.d.mts +1 -1
- package/dist/number-input.d.ts +1 -1
- package/dist/number-input.js +5 -5
- package/dist/number-input.mjs +2 -2
- package/dist/nx-image.d.mts +13 -0
- package/dist/nx-image.d.ts +13 -0
- package/dist/nx-image.js +12 -0
- package/dist/nx-image.mjs +3 -0
- package/dist/pagination.d.mts +1 -0
- package/dist/pagination.d.ts +1 -0
- package/dist/pagination.js +5 -5
- package/dist/pagination.mjs +2 -2
- package/dist/popover.d.mts +1 -1
- package/dist/popover.d.ts +1 -1
- package/dist/popover.js +8 -8
- package/dist/popover.mjs +2 -2
- package/dist/price-input.d.mts +36 -0
- package/dist/price-input.d.ts +36 -0
- package/dist/price-input.js +16 -0
- package/dist/price-input.mjs +3 -0
- package/dist/progress.d.mts +18 -0
- package/dist/progress.d.ts +18 -0
- package/dist/progress.js +16 -0
- package/dist/progress.mjs +3 -0
- package/dist/radio-group.js +6 -6
- package/dist/radio-group.mjs +2 -2
- package/dist/schemas/_all.json +2356 -404
- package/dist/schemas/accordion.json +14 -11
- package/dist/schemas/alert.json +49 -0
- package/dist/schemas/avatar.json +13 -7
- package/dist/schemas/badge.json +76 -0
- package/dist/schemas/breadcrumb.json +47 -0
- package/dist/schemas/button.json +27 -9
- package/dist/schemas/carousel.json +10 -4
- package/dist/schemas/carouselButton.json +20 -0
- package/dist/schemas/carouselDots.json +17 -0
- package/dist/schemas/carouselSlide.json +20 -0
- package/dist/schemas/checkBox.json +33 -8
- package/dist/schemas/chip.json +15 -6
- package/dist/schemas/clientOnly.json +19 -0
- package/dist/schemas/countdown.json +10 -7
- package/dist/schemas/counter.json +15 -9
- package/dist/schemas/dataList.json +10 -10
- package/dist/schemas/datePicker.json +56 -0
- package/dist/schemas/divider.json +8 -5
- package/dist/schemas/drawer.json +24 -2
- package/dist/schemas/drawerClose.json +24 -0
- package/dist/schemas/drawerContent.json +9 -6
- package/dist/schemas/drawerDescription.json +20 -0
- package/dist/schemas/drawerTitle.json +20 -0
- package/dist/schemas/drawerTrigger.json +24 -0
- package/dist/schemas/dropdownMenu.json +83 -0
- package/dist/schemas/ellipsis.json +17 -7
- package/dist/schemas/emptyState.json +44 -0
- package/dist/schemas/errorBoundary.json +22 -0
- package/dist/schemas/infiniteScroll.json +18 -9
- package/dist/schemas/marquee.json +12 -6
- package/dist/schemas/modalCall.json +81 -3
- package/dist/schemas/modalTemplate.json +67 -14
- package/dist/schemas/numberInput.json +42 -12
- package/dist/schemas/nxImage.json +56 -0
- package/dist/schemas/pagination.json +13 -6
- package/dist/schemas/popover.json +18 -9
- package/dist/schemas/priceInput.json +104 -0
- package/dist/schemas/progress.json +63 -0
- package/dist/schemas/radioGroup.json +19 -9
- package/dist/schemas/radioItem.json +12 -5
- package/dist/schemas/select.json +15 -9
- package/dist/schemas/selectItem.json +7 -4
- package/dist/schemas/skeleton.json +12 -6
- package/dist/schemas/slider.json +78 -0
- package/dist/schemas/spinner.json +11 -4
- package/dist/schemas/stepper.json +73 -0
- package/dist/schemas/switch.json +23 -5
- package/dist/schemas/tab.json +17 -14
- package/dist/schemas/table.json +75 -0
- package/dist/schemas/tableRow.json +32 -0
- package/dist/schemas/tagInput.json +70 -0
- package/dist/schemas/tdColumn.json +107 -0
- package/dist/schemas/textArea.json +72 -7
- package/dist/schemas/textInput.json +72 -10
- package/dist/schemas/themeProvider.json +65 -0
- package/dist/schemas/toastOptions.json +81 -0
- package/dist/schemas/toaster.json +76 -0
- package/dist/schemas/toggleGroup.json +88 -0
- package/dist/schemas/tooltip.json +12 -9
- package/dist/schemas/virtualGrid.json +22 -11
- package/dist/schemas/virtualList.json +14 -8
- package/dist/schemas.d.mts +1360 -81
- package/dist/schemas.d.ts +1360 -81
- package/dist/schemas.js +725 -273
- package/dist/schemas.mjs +698 -273
- package/dist/select.js +6 -6
- package/dist/select.mjs +2 -2
- package/dist/skeleton.js +3 -3
- package/dist/skeleton.mjs +2 -2
- package/dist/slider.d.mts +20 -0
- package/dist/slider.d.ts +20 -0
- package/dist/slider.js +16 -0
- package/dist/slider.mjs +3 -0
- package/dist/spinner.js +3 -3
- package/dist/spinner.mjs +2 -2
- package/dist/stepper.d.mts +20 -0
- package/dist/stepper.d.ts +20 -0
- package/dist/stepper.js +16 -0
- package/dist/stepper.mjs +3 -0
- package/dist/styles/layer.d.mts +3 -0
- package/dist/styles/layer.d.ts +3 -0
- package/dist/styles/layer.js +18 -0
- package/dist/styles/layer.mjs +16 -0
- package/dist/styles.css +3872 -2
- package/dist/styles.js +2 -5
- package/dist/styles.layered.css +3875 -0
- package/dist/styles.mjs +1 -4
- package/dist/switch.js +4 -4
- package/dist/switch.mjs +2 -2
- package/dist/tab.js +5 -5
- package/dist/tab.mjs +2 -2
- package/dist/table.d.mts +2 -2
- package/dist/table.d.ts +2 -2
- package/dist/table.js +9 -9
- package/dist/table.mjs +3 -3
- package/dist/tag-input.d.mts +21 -0
- package/dist/tag-input.d.ts +21 -0
- package/dist/tag-input.js +16 -0
- package/dist/tag-input.mjs +3 -0
- package/dist/text-area.d.mts +5 -1
- package/dist/text-area.d.ts +5 -1
- package/dist/text-area.js +4 -4
- package/dist/text-area.mjs +2 -2
- package/dist/text-input.d.mts +5 -1
- package/dist/text-input.d.ts +5 -1
- package/dist/text-input.js +4 -4
- package/dist/text-input.mjs +2 -2
- package/dist/toast.js +5 -5
- package/dist/toast.mjs +2 -2
- package/dist/toggle-group.d.mts +36 -0
- package/dist/toggle-group.d.ts +36 -0
- package/dist/toggle-group.js +16 -0
- package/dist/toggle-group.mjs +3 -0
- package/dist/tooltip.js +5 -5
- package/dist/tooltip.mjs +2 -2
- package/dist/utils/cn.d.mts +0 -10
- package/dist/utils/cn.d.ts +0 -10
- package/dist/utils/cn.js +2 -2
- package/dist/utils/cn.mjs +1 -1
- package/dist/virtual-scroll.js +4 -4
- package/dist/virtual-scroll.mjs +2 -2
- package/package.json +90 -17
- package/scripts/setup-cursor-rules.cjs +6 -6
- package/dist/chunks/chunk-7MT3QYE6.js +0 -92
- package/dist/chunks/chunk-FA2OPP3U.mjs +0 -140
- package/dist/chunks/chunk-FKZI2HTI.js +0 -104
- package/dist/chunks/chunk-NCQDOPBR.mjs +0 -86
- package/dist/chunks/chunk-NTN55ZIX.mjs +0 -113
- package/dist/chunks/chunk-Q7GQVAYY.js +0 -88
- package/dist/chunks/chunk-QJNQCLMV.js +0 -25
- package/dist/chunks/chunk-UDQXLI5Y.mjs +0 -81
- package/dist/chunks/chunk-UR6JOKVB.mjs +0 -65
- package/dist/chunks/chunk-WVIEIRK2.js +0 -136
- package/dist/chunks/chunk-XALPBGSC.mjs +0 -23
- package/dist/schemas/typography.json +0 -70
- package/dist/typography.d.mts +0 -19
- package/dist/typography.d.ts +0 -19
- package/dist/typography.js +0 -102
- package/dist/typography.mjs +0 -79
|
@@ -1,41 +1,57 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "@nexus-cross/design-system
|
|
2
|
+
description: "@nexus-cross/design-system component API reference — props and usage examples for all shared components"
|
|
3
3
|
globs: "**/*.tsx,**/*.jsx,**/*.ts"
|
|
4
4
|
alwaysApply: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# @nexus-cross/design-system — Component API Reference
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
All components are imported from `@nexus-cross/design-system`.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Button
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Interactive button. semantic(color) x variant(style) 2-axis system. Rendering element changeable via asChild.
|
|
16
16
|
|
|
17
17
|
| Prop | Type | Default | Description |
|
|
18
18
|
|---|---|---|---|
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
19
|
+
| `semantic` | `'primary'` \| `'secondary'` \| `'normal'` \| `'danger'` | `"primary"` | Color theme (primary=main, secondary=sub, normal=neutral, danger=danger) |
|
|
20
|
+
| `variant` | `'contained'` \| `'outlined'` \| `'subtle'` \| `'ghost'` | `"contained"` | Visual style (contained=filled, outlined=border, subtle=light bg, ghost=transparent) |
|
|
21
|
+
| `size` | `'xl'` \| `'lg'` \| `'md'` \| `'sm'` | `"md"` | Size |
|
|
22
|
+
| `radius` | `'default'` \| `'circle'` | `"default"` | Corner radius (default=size-based radius, circle=pill shape) |
|
|
23
|
+
| `asChild` | `boolean` | - | If true, renders as child element (Slot pattern) |
|
|
24
|
+
| `detectDoubleClick` | `boolean` | - | Prevent double click within 500ms |
|
|
25
|
+
| `disabled` | `boolean` | - | Disabled (auto aria-disabled) |
|
|
26
|
+
| `children` | `ReactNode` | - | Button content (ReactNode) |
|
|
27
|
+
| `onClick` | `ReactNode` | - | Click event handler |
|
|
28
|
+
| `type` | `'button'` \| `'submit'` \| `'reset'` | - | HTML button type (default: button) |
|
|
29
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
30
|
+
| `className` | `string` | - | Style override |
|
|
31
|
+
|
|
32
|
+
2-axis variant: semantic (color) × variant (style). sizes: xl, lg, md, sm. radius: default, circle.
|
|
25
33
|
|
|
26
34
|
```tsx
|
|
27
|
-
|
|
35
|
+
// Default (primary + contained)
|
|
36
|
+
<Button>Confirm</Button>
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
// semantic × variant combinations
|
|
39
|
+
<Button semantic="primary" variant="contained" size="lg">Primary Contained</Button>
|
|
40
|
+
<Button semantic="secondary" variant="outlined" size="md">Secondary Outlined</Button>
|
|
41
|
+
<Button semantic="normal" variant="subtle" size="sm">Normal Subtle</Button>
|
|
42
|
+
<Button semantic="danger" variant="ghost">Danger Ghost</Button>
|
|
30
43
|
|
|
31
|
-
//
|
|
44
|
+
// Pill shape (radius="circle")
|
|
45
|
+
<Button semantic="primary" variant="contained" radius="circle">Pill</Button>
|
|
46
|
+
|
|
47
|
+
// Loading state
|
|
32
48
|
<Button disabled>
|
|
33
|
-
<Spinner size={16} />
|
|
49
|
+
<Spinner size={16} /> Processing...
|
|
34
50
|
</Button>
|
|
35
51
|
|
|
36
|
-
// <a>
|
|
37
|
-
<Button asChild variant="ghost">
|
|
38
|
-
<a href="/settings"
|
|
52
|
+
// Render as <a> tag
|
|
53
|
+
<Button asChild semantic="normal" variant="ghost">
|
|
54
|
+
<a href="/settings">Settings</a>
|
|
39
55
|
</Button>
|
|
40
56
|
```
|
|
41
57
|
|
|
@@ -43,42 +59,95 @@ alwaysApply: false
|
|
|
43
59
|
|
|
44
60
|
## TextInput
|
|
45
61
|
|
|
46
|
-
|
|
62
|
+
Text input field. Supports label, description, prefix/suffix icons, clearable, character counter.
|
|
47
63
|
|
|
48
64
|
| Prop | Type | Default | Description |
|
|
49
65
|
|---|---|---|---|
|
|
50
|
-
| `size` | `'
|
|
51
|
-
| `error` | `boolean` |
|
|
52
|
-
| `prefixIcon` | `ReactNode` | - |
|
|
53
|
-
| `suffixIcon` | `ReactNode` | - |
|
|
54
|
-
| `
|
|
66
|
+
| `size` | `'md'` \| `'lg'` \| `'xl'` | `"md"` | Size |
|
|
67
|
+
| `error` | `boolean` | - | Error state (auto aria-invalid) |
|
|
68
|
+
| `prefixIcon` | `ReactNode` | - | Prefix icon (ReactNode) |
|
|
69
|
+
| `suffixIcon` | `ReactNode` | - | Suffix icon (ReactNode) |
|
|
70
|
+
| `label` | `ReactNode` | - | Label above input field (ReactNode) |
|
|
71
|
+
| `description` | `ReactNode` | - | Description below input field (ReactNode, red on error) |
|
|
72
|
+
| `showCount` | `boolean` | - | Show character count (requires maxLength) |
|
|
73
|
+
| `maxLength` | `number` | - | Maximum character count |
|
|
74
|
+
| `clearable` | `boolean` | - | Clear input via X button |
|
|
75
|
+
| `placeholder` | `string` | - | Placeholder |
|
|
76
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
77
|
+
| `readOnly` | `boolean` | - | Read-only |
|
|
78
|
+
| `value` | `string` | - | Input value (controlled mode) |
|
|
79
|
+
| `defaultValue` | `string` | - | Initial value (uncontrolled mode) |
|
|
80
|
+
| `type` | `string` | - | Input type (text, password, email, url, etc.) |
|
|
81
|
+
| `name` | `string` | - | Form field name |
|
|
82
|
+
| `id` | `string` | - | Element ID (for label htmlFor binding) |
|
|
83
|
+
| `autoFocus` | `boolean` | - | Auto focus |
|
|
84
|
+
| `autoComplete` | `string` | - | Autocomplete hint (on, off, email, etc.) |
|
|
85
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: string) => void |
|
|
86
|
+
| `onChange` | `ReactNode` | - | Native change event handler |
|
|
87
|
+
| `onBlur` | `ReactNode` | - | Blur callback |
|
|
88
|
+
| `onFocus` | `ReactNode` | - | Focus callback |
|
|
89
|
+
| `className` | `string` | - | Style override |
|
|
55
90
|
|
|
56
91
|
```tsx
|
|
57
|
-
<TextInput placeholder="
|
|
92
|
+
<TextInput placeholder="Email" size="md" />
|
|
58
93
|
|
|
59
94
|
<TextInput
|
|
60
|
-
|
|
95
|
+
label="Email"
|
|
96
|
+
description="Enter your email address"
|
|
97
|
+
placeholder="example@email.com"
|
|
98
|
+
clearable
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<TextInput
|
|
102
|
+
label="Search"
|
|
61
103
|
prefixIcon={<SearchIcon />}
|
|
104
|
+
clearable
|
|
62
105
|
onValueChange={(v) => setQuery(v)}
|
|
63
106
|
/>
|
|
107
|
+
|
|
108
|
+
<TextInput
|
|
109
|
+
label="Nickname"
|
|
110
|
+
description="2-20 characters"
|
|
111
|
+
showCount
|
|
112
|
+
maxLength={20}
|
|
113
|
+
clearable
|
|
114
|
+
error
|
|
115
|
+
/>
|
|
64
116
|
```
|
|
65
117
|
|
|
66
118
|
---
|
|
67
119
|
|
|
68
120
|
## TextArea
|
|
69
121
|
|
|
70
|
-
|
|
122
|
+
Multi-line text input with label, description, character counter, and resize modes.
|
|
71
123
|
|
|
72
124
|
| Prop | Type | Default | Description |
|
|
73
125
|
|---|---|---|---|
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
126
|
+
| `label` | `string` | - | Label text above the textarea |
|
|
127
|
+
| `description` | `string` | - | Helper/error description below the textarea |
|
|
128
|
+
| `size` | `'lg'` \| `'md'` | - | Font size variant (lg: 16px, md: 14px) |
|
|
129
|
+
| `resize` | `'default'` \| `'auto'` \| `'none'` | - | Resize mode (default: manual, auto: auto-grow, none: fixed) |
|
|
130
|
+
| `error` | `boolean` | - | Error state (auto aria-invalid) |
|
|
131
|
+
| `showCount` | `boolean` | - | Show character count (requires maxLength) |
|
|
132
|
+
| `maxLength` | `number` | - | Maximum character count |
|
|
133
|
+
| `placeholder` | `string` | - | Placeholder |
|
|
134
|
+
| `rows` | `number` | - | Visible row count |
|
|
135
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
136
|
+
| `readOnly` | `boolean` | - | Read-only |
|
|
137
|
+
| `value` | `string` | - | Input value (controlled mode) |
|
|
138
|
+
| `defaultValue` | `string` | - | Initial value (uncontrolled mode) |
|
|
139
|
+
| `name` | `string` | - | Form field name |
|
|
140
|
+
| `id` | `string` | - | Element ID |
|
|
141
|
+
| `autoFocus` | `boolean` | - | Auto focus |
|
|
142
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: string) => void |
|
|
143
|
+
| `onChange` | `ReactNode` | - | Native change event handler |
|
|
144
|
+
| `onBlur` | `ReactNode` | - | Blur callback |
|
|
145
|
+
| `onFocus` | `ReactNode` | - | Focus callback |
|
|
146
|
+
| `className` | `string` | - | Style override |
|
|
78
147
|
|
|
79
148
|
```tsx
|
|
80
149
|
<TextArea
|
|
81
|
-
placeholder="
|
|
150
|
+
placeholder="Enter your content"
|
|
82
151
|
maxLength={500}
|
|
83
152
|
showCount
|
|
84
153
|
rows={4}
|
|
@@ -89,23 +158,37 @@ alwaysApply: false
|
|
|
89
158
|
|
|
90
159
|
## Select
|
|
91
160
|
|
|
92
|
-
|
|
161
|
+
Dropdown select. Based on Radix Select. Used with SelectItem.
|
|
93
162
|
|
|
94
163
|
| Prop | Type | Default | Description |
|
|
95
164
|
|---|---|---|---|
|
|
96
|
-
| `value` | `string` | - |
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `displayComponent` | `ReactNode` | - |
|
|
165
|
+
| `value` | `string` | - | Selected value |
|
|
166
|
+
| `placeholder` | `string` | - | Placeholder |
|
|
167
|
+
| `variant` | `'default'` \| `'outline'` | `"default"` | Trigger style |
|
|
168
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` \| `'full'` | `"full"` | Width |
|
|
169
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
170
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: string) => void |
|
|
171
|
+
| `displayComponent` | `ReactNode` | - | Custom display in trigger (ReactNode) |
|
|
172
|
+
| `children` | `ReactNode` | - | SelectItem list (ReactNode, required) |
|
|
173
|
+
| `className` | `string` | - | Wrapper style |
|
|
174
|
+
| `triggerClassName` | `string` | - | Trigger style override |
|
|
175
|
+
|
|
176
|
+
### SelectItem
|
|
177
|
+
|
|
178
|
+
Individual option within Select.
|
|
179
|
+
|
|
180
|
+
| Prop | Type | Default | Description |
|
|
181
|
+
|---|---|---|---|
|
|
182
|
+
| `value` | `string` | - | Item value |
|
|
183
|
+
| `children` | `ReactNode` | - | Item content (ReactNode, required) |
|
|
184
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
185
|
+
| `className` | `string` | - | Style override |
|
|
103
186
|
|
|
104
187
|
```tsx
|
|
105
|
-
<Select value={lang} onValueChange={setLang} placeholder="
|
|
106
|
-
<SelectItem value="ko"
|
|
188
|
+
<Select value={lang} onValueChange={setLang} placeholder="Select language">
|
|
189
|
+
<SelectItem value="ko">Korean</SelectItem>
|
|
107
190
|
<SelectItem value="en">English</SelectItem>
|
|
108
|
-
<SelectItem value="ja"
|
|
191
|
+
<SelectItem value="ja">Japanese</SelectItem>
|
|
109
192
|
</Select>
|
|
110
193
|
```
|
|
111
194
|
|
|
@@ -113,22 +196,30 @@ alwaysApply: false
|
|
|
113
196
|
|
|
114
197
|
## CheckBox
|
|
115
198
|
|
|
116
|
-
|
|
199
|
+
Checkbox. Native input-based, supports square/round shapes.
|
|
117
200
|
|
|
118
201
|
| Prop | Type | Default | Description |
|
|
119
202
|
|---|---|---|---|
|
|
120
|
-
| `size` | `'sm' \| 'md'` | `
|
|
121
|
-
| `shape` | `'square' \| 'round'` | `
|
|
122
|
-
| `checked` | `boolean` | - |
|
|
123
|
-
| `indeterminate` | `boolean` |
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
203
|
+
| `size` | `'sm'` \| `'md'` | `"md"` | Size |
|
|
204
|
+
| `shape` | `'square'` \| `'round'` | `"square"` | Shape |
|
|
205
|
+
| `checked` | `boolean` | - | Checked state |
|
|
206
|
+
| `indeterminate` | `boolean` | - | Indeterminate state (aria-checked="mixed") |
|
|
207
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
208
|
+
| `readOnly` | `boolean` | - | Read-only |
|
|
209
|
+
| `label` | `ReactNode` | - | Label text (ReactNode) |
|
|
210
|
+
| `children` | `ReactNode` | - | Label alternative content (ReactNode) |
|
|
211
|
+
| `name` | `string` | - | Form field name |
|
|
212
|
+
| `id` | `string` | - | Element ID |
|
|
213
|
+
| `value` | `string` | - | Value for form submission |
|
|
214
|
+
| `onCheckedChange` | `ReactNode` | - | Checked state change callback (checked: boolean) => void |
|
|
215
|
+
| `onChange` | `ReactNode` | - | Native change event handler |
|
|
216
|
+
| `className` | `string` | - | Style override |
|
|
126
217
|
|
|
127
218
|
```tsx
|
|
128
219
|
<CheckBox
|
|
129
220
|
checked={agreed}
|
|
130
221
|
onCheckedChange={setAgreed}
|
|
131
|
-
label="
|
|
222
|
+
label="I agree to the terms of service"
|
|
132
223
|
/>
|
|
133
224
|
|
|
134
225
|
<CheckBox shape="round" size="sm" checked indeterminate />
|
|
@@ -136,23 +227,36 @@ alwaysApply: false
|
|
|
136
227
|
|
|
137
228
|
---
|
|
138
229
|
|
|
139
|
-
## RadioGroup
|
|
230
|
+
## RadioGroup
|
|
140
231
|
|
|
141
|
-
|
|
232
|
+
Radio group. Used with RadioItem.
|
|
142
233
|
|
|
143
|
-
|
|
|
234
|
+
| Prop | Type | Default | Description |
|
|
144
235
|
|---|---|---|---|
|
|
145
|
-
| `name` | `string`
|
|
146
|
-
| `value` | `string` | - |
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
236
|
+
| `name` | `string` | - | Form name (required) |
|
|
237
|
+
| `value` | `string` | - | Selected value (controlled) |
|
|
238
|
+
| `defaultValue` | `string` | - | Initial value (uncontrolled) |
|
|
239
|
+
| `size` | `'sm'` \| `'md'` | `"md"` | Size |
|
|
240
|
+
| `orientation` | `'horizontal'` \| `'vertical'` | `"vertical"` | Layout direction |
|
|
241
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
242
|
+
| `children` | `ReactNode` | - | RadioItem list (ReactNode, required) |
|
|
243
|
+
| `aria-label` | `string` | - | Accessibility label |
|
|
244
|
+
| `aria-labelledby` | `string` | - | Accessibility label reference ID |
|
|
245
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: string) => void |
|
|
246
|
+
| `className` | `string` | - | Style override |
|
|
247
|
+
|
|
248
|
+
### RadioItem
|
|
249
|
+
|
|
250
|
+
Individual option within RadioGroup.
|
|
151
251
|
|
|
152
|
-
|
|
|
153
|
-
|
|
154
|
-
| `value` | `string`
|
|
155
|
-
| `
|
|
252
|
+
| Prop | Type | Default | Description |
|
|
253
|
+
|---|---|---|---|
|
|
254
|
+
| `value` | `string` | - | Item value (required) |
|
|
255
|
+
| `size` | `'sm'` \| `'md'` | - | Size (overrides group) |
|
|
256
|
+
| `label` | `ReactNode` | - | Label text (ReactNode) |
|
|
257
|
+
| `children` | `ReactNode` | - | Label alternative content (ReactNode) |
|
|
258
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
259
|
+
| `className` | `string` | - | Style override |
|
|
156
260
|
|
|
157
261
|
```tsx
|
|
158
262
|
<RadioGroup
|
|
@@ -160,11 +264,11 @@ alwaysApply: false
|
|
|
160
264
|
value={plan}
|
|
161
265
|
onValueChange={setPlan}
|
|
162
266
|
orientation="horizontal"
|
|
163
|
-
aria-label="
|
|
267
|
+
aria-label="Select plan"
|
|
164
268
|
>
|
|
165
|
-
<RadioItem value="free" label="
|
|
166
|
-
<RadioItem value="pro" label="
|
|
167
|
-
<RadioItem value="enterprise" label="
|
|
269
|
+
<RadioItem value="free" label="Free" />
|
|
270
|
+
<RadioItem value="pro" label="Pro" />
|
|
271
|
+
<RadioItem value="enterprise" label="Enterprise" />
|
|
168
272
|
</RadioGroup>
|
|
169
273
|
```
|
|
170
274
|
|
|
@@ -172,14 +276,19 @@ alwaysApply: false
|
|
|
172
276
|
|
|
173
277
|
## Switch
|
|
174
278
|
|
|
175
|
-
|
|
279
|
+
Toggle switch. Native checkbox-based, role="switch".
|
|
176
280
|
|
|
177
281
|
| Prop | Type | Default | Description |
|
|
178
282
|
|---|---|---|---|
|
|
179
|
-
| `size` | `'sm' \| 'md'` | `
|
|
180
|
-
| `checked` | `boolean` | - |
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
283
|
+
| `size` | `'sm'` \| `'md'` | `"md"` | Size |
|
|
284
|
+
| `checked` | `boolean` | - | On/off state |
|
|
285
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
286
|
+
| `readOnly` | `boolean` | - | Read-only |
|
|
287
|
+
| `name` | `string` | - | Form field name |
|
|
288
|
+
| `id` | `string` | - | Element ID |
|
|
289
|
+
| `onCheckedChange` | `ReactNode` | - | Toggle state change callback (checked: boolean) => void |
|
|
290
|
+
| `onChange` | `ReactNode` | - | Native change event handler (ChangeEvent) |
|
|
291
|
+
| `className` | `string` | - | Style override |
|
|
183
292
|
|
|
184
293
|
```tsx
|
|
185
294
|
<Switch checked={darkMode} onCheckedChange={setDarkMode} />
|
|
@@ -189,24 +298,27 @@ alwaysApply: false
|
|
|
189
298
|
|
|
190
299
|
## Chip
|
|
191
300
|
|
|
192
|
-
|
|
301
|
+
Chip/tag/badge. Close button displayed via onClose prop.
|
|
193
302
|
|
|
194
303
|
| Prop | Type | Default | Description |
|
|
195
304
|
|---|---|---|---|
|
|
196
|
-
| `variant` | `'default' \| 'filled' \| 'outline' \| 'accent'` | `
|
|
197
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `
|
|
198
|
-
| `asChild` | `boolean` |
|
|
199
|
-
| `disabled` | `boolean` | - |
|
|
200
|
-
| `
|
|
305
|
+
| `variant` | `'default'` \| `'filled'` \| `'outline'` \| `'accent'` | `"default"` | Style |
|
|
306
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Size |
|
|
307
|
+
| `asChild` | `boolean` | - | If true, renders as child element (Slot pattern) |
|
|
308
|
+
| `disabled` | `boolean` | - | Disabled (auto aria-disabled) |
|
|
309
|
+
| `children` | `ReactNode` | - | Chip content (ReactNode) |
|
|
310
|
+
| `onClose` | `ReactNode` | - | Close button click callback (e: MouseEvent) => void. Shows X button when provided |
|
|
311
|
+
| `onClick` | `ReactNode` | - | Click event handler |
|
|
312
|
+
| `className` | `string` | - | Style override |
|
|
201
313
|
|
|
202
314
|
```tsx
|
|
203
315
|
<Chip variant="accent" size="sm">New</Chip>
|
|
204
316
|
|
|
205
317
|
<Chip onClose={() => removeTag(id)}>React</Chip>
|
|
206
318
|
|
|
207
|
-
// <li
|
|
319
|
+
// Render as <li>
|
|
208
320
|
<Chip asChild variant="filled">
|
|
209
|
-
<li
|
|
321
|
+
<li>List chip</li>
|
|
210
322
|
</Chip>
|
|
211
323
|
```
|
|
212
324
|
|
|
@@ -214,31 +326,73 @@ alwaysApply: false
|
|
|
214
326
|
|
|
215
327
|
## Spinner
|
|
216
328
|
|
|
217
|
-
|
|
329
|
+
Loading indicator. SVG-based. Built-in role="status".
|
|
218
330
|
|
|
219
331
|
| Prop | Type | Default | Description |
|
|
220
332
|
|---|---|---|---|
|
|
221
|
-
| `size` | `number` | `20` | px
|
|
222
|
-
| `
|
|
223
|
-
| `aria-label` | `string` | `
|
|
333
|
+
| `size` | `number` | `20` | Size in px |
|
|
334
|
+
| `color` | `string` | - | Color (CSS color value, default currentColor) |
|
|
335
|
+
| `aria-label` | `string` | `"Loading"` | Accessibility label |
|
|
336
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
337
|
+
| `className` | `string` | - | Color override etc. |
|
|
224
338
|
|
|
225
339
|
```tsx
|
|
226
340
|
<Spinner size={24} />
|
|
227
341
|
|
|
228
|
-
<Spinner size={14} className="text-white" aria-label="
|
|
342
|
+
<Spinner size={14} className="text-white" aria-label="Loading" />
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Skeleton
|
|
348
|
+
|
|
349
|
+
Skeleton loading placeholder. Size/shape via className. With children, wraps transparently to maintain actual size.
|
|
350
|
+
|
|
351
|
+
| Prop | Type | Default | Description |
|
|
352
|
+
|---|---|---|---|
|
|
353
|
+
| `as` | `'div'` \| `'span'` | `"div"` | Rendered tag |
|
|
354
|
+
| `circle` | `boolean` | `false` | Circle skeleton (rounded-full) |
|
|
355
|
+
| `width` | `string` \| `number` | - | Width (e.g. '100px', '50%', 200) |
|
|
356
|
+
| `height` | `string` \| `number` | - | Height (e.g. '16px', 40) |
|
|
357
|
+
| `children` | `ReactNode` | - | Inner content (shown when loaded, maintains actual size) |
|
|
358
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
359
|
+
| `className` | `string` | - | Style override |
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
// Basic usage (size via className)
|
|
363
|
+
<Skeleton className="h-4 w-48" />
|
|
364
|
+
<Skeleton className="h-3 w-32" />
|
|
365
|
+
|
|
366
|
+
// Circular avatar skeleton
|
|
367
|
+
<Skeleton circle width={40} height={40} />
|
|
368
|
+
|
|
369
|
+
// width/height props
|
|
370
|
+
<Skeleton width="100%" height={120} className="rounded-lg" />
|
|
371
|
+
|
|
372
|
+
// Match children size
|
|
373
|
+
<Skeleton>
|
|
374
|
+
<p>Skeleton will match this text size</p>
|
|
375
|
+
</Skeleton>
|
|
376
|
+
|
|
377
|
+
// With DataList
|
|
378
|
+
<DataList list={data} skeletonElement={<MySkeleton />} skeletonCount={5}>
|
|
379
|
+
{({ item }) => <Card key={item.id} {...item} />}
|
|
380
|
+
</DataList>
|
|
229
381
|
```
|
|
230
382
|
|
|
231
383
|
---
|
|
232
384
|
|
|
233
385
|
## Divider
|
|
234
386
|
|
|
235
|
-
|
|
387
|
+
Divider. Supports horizontal/vertical, solid/dashed/dotted.
|
|
236
388
|
|
|
237
389
|
| Prop | Type | Default | Description |
|
|
238
390
|
|---|---|---|---|
|
|
239
|
-
| `orientation` | `'horizontal' \| 'vertical'` | `
|
|
240
|
-
| `variant` | `'solid' \| 'dashed' \| 'dotted'` | `
|
|
241
|
-
| `color` | `string` | - |
|
|
391
|
+
| `orientation` | `'horizontal'` \| `'vertical'` | `"horizontal"` | Direction |
|
|
392
|
+
| `variant` | `'solid'` \| `'dashed'` \| `'dotted'` | `"solid"` | Line style |
|
|
393
|
+
| `color` | `string` | - | Custom color (CSS value) |
|
|
394
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
395
|
+
| `className` | `string` | - | Style override |
|
|
242
396
|
|
|
243
397
|
```tsx
|
|
244
398
|
<Divider />
|
|
@@ -249,19 +403,22 @@ alwaysApply: false
|
|
|
249
403
|
|
|
250
404
|
## Tooltip
|
|
251
405
|
|
|
252
|
-
|
|
406
|
+
Tooltip. Based on Radix Tooltip. Built-in Provider.
|
|
253
407
|
|
|
254
408
|
| Prop | Type | Default | Description |
|
|
255
409
|
|---|---|---|---|
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
258
|
-
| `
|
|
259
|
-
| `
|
|
260
|
-
| `
|
|
261
|
-
| `
|
|
410
|
+
| `children` | `ReactNode` | - | Trigger element (ReactNode, required) |
|
|
411
|
+
| `content` | `ReactNode` | - | Tooltip content (ReactNode, required) |
|
|
412
|
+
| `variant` | `'dark'` \| `'light'` | `"dark"` | Style |
|
|
413
|
+
| `side` | `'top'` \| `'right'` \| `'bottom'` \| `'left'` | `"top"` | Position |
|
|
414
|
+
| `align` | `'start'` \| `'center'` \| `'end'` | `"center"` | Alignment |
|
|
415
|
+
| `delayDuration` | `number` | `200` | Show delay (ms) |
|
|
416
|
+
| `disabled` | `boolean` | `false` | Disabled |
|
|
417
|
+
| `className` | `string` | - | Content style |
|
|
418
|
+
| `triggerClassName` | `string` | - | Trigger style |
|
|
262
419
|
|
|
263
420
|
```tsx
|
|
264
|
-
<Tooltip content="
|
|
421
|
+
<Tooltip content="Copied!" side="bottom">
|
|
265
422
|
<button>📋</button>
|
|
266
423
|
</Tooltip>
|
|
267
424
|
```
|
|
@@ -270,21 +427,25 @@ alwaysApply: false
|
|
|
270
427
|
|
|
271
428
|
## Popover
|
|
272
429
|
|
|
273
|
-
|
|
430
|
+
Popover. Based on Radix Popover.
|
|
274
431
|
|
|
275
432
|
| Prop | Type | Default | Description |
|
|
276
433
|
|---|---|---|---|
|
|
277
|
-
| `trigger` | `ReactNode` | - |
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
281
|
-
| `
|
|
282
|
-
| `open` | `boolean` | - |
|
|
283
|
-
| `onOpenChange` | `(open: boolean) => void
|
|
434
|
+
| `trigger` | `ReactNode` | - | Trigger element (ReactNode, required) |
|
|
435
|
+
| `side` | `'top'` \| `'right'` \| `'bottom'` \| `'left'` | `"bottom"` | Position |
|
|
436
|
+
| `align` | `'start'` \| `'center'` \| `'end'` | `"center"` | Alignment |
|
|
437
|
+
| `sideOffset` | `number` | `4` | Position offset (px) |
|
|
438
|
+
| `alignOffset` | `number` | - | Alignment offset (px) |
|
|
439
|
+
| `open` | `boolean` | - | Controlled mode |
|
|
440
|
+
| `onOpenChange` | `ReactNode` | - | Open/close state change callback (open: boolean) => void |
|
|
441
|
+
| `onClickTrigger` | `ReactNode` | - | Callback on trigger element click. Passed to PopoverPrimitive.Trigger onClick. |
|
|
442
|
+
| `children` | `ReactNode` | - | Popover body (ReactNode) |
|
|
443
|
+
| `className` | `string` | - | Content style |
|
|
444
|
+
| `arrowClassName` | `string` | - | Arrow style |
|
|
284
445
|
|
|
285
446
|
```tsx
|
|
286
|
-
<Popover trigger={<Button variant="outline"
|
|
287
|
-
<div className="p-4"
|
|
447
|
+
<Popover trigger={<Button variant="outline">Menu</Button>}>
|
|
448
|
+
<div className="p-4">Popover content</div>
|
|
288
449
|
</Popover>
|
|
289
450
|
```
|
|
290
451
|
|
|
@@ -292,27 +453,29 @@ alwaysApply: false
|
|
|
292
453
|
|
|
293
454
|
## Accordion
|
|
294
455
|
|
|
295
|
-
|
|
456
|
+
Accordion. Supports both items array and composable patterns.
|
|
296
457
|
|
|
297
458
|
| Prop | Type | Default | Description |
|
|
298
459
|
|---|---|---|---|
|
|
299
|
-
| `items` | `
|
|
300
|
-
| `type` | `'single' \| 'multiple'` | `
|
|
301
|
-
| `collapsible` | `boolean` | `true` |
|
|
302
|
-
| `value`
|
|
303
|
-
| `
|
|
460
|
+
| `items` | `object`[] | - | Accordion item array (required) |
|
|
461
|
+
| `type` | `'single'` \| `'multiple'` | `"single"` | Single/multiple open mode |
|
|
462
|
+
| `collapsible` | `boolean` | `true` | Allow collapsing all |
|
|
463
|
+
| `value` | `string` \| `string`[] | - | Controlled mode |
|
|
464
|
+
| `defaultValue` | `string` \| `string`[] | - | Uncontrolled initial value |
|
|
465
|
+
| `onValueChange` | `ReactNode` | - | Open item change callback (value: string | string[]) => void |
|
|
466
|
+
| `className` | `string` | - | Root style |
|
|
304
467
|
|
|
305
468
|
```tsx
|
|
306
469
|
<Accordion items={[
|
|
307
|
-
{ id: '1', trigger: 'FAQ 1', content: '
|
|
308
|
-
{ id: '2', trigger: 'FAQ 2', content: '
|
|
470
|
+
{ id: '1', trigger: 'FAQ 1', content: 'Answer 1' },
|
|
471
|
+
{ id: '2', trigger: 'FAQ 2', content: 'Answer 2' },
|
|
309
472
|
]} />
|
|
310
473
|
|
|
311
|
-
//
|
|
474
|
+
// Composable pattern
|
|
312
475
|
<AccordionRoot type="single" collapsible>
|
|
313
476
|
<AccordionItem value="item-1">
|
|
314
|
-
<AccordionTrigger
|
|
315
|
-
<AccordionContent
|
|
477
|
+
<AccordionTrigger>Title</AccordionTrigger>
|
|
478
|
+
<AccordionContent>Content</AccordionContent>
|
|
316
479
|
</AccordionItem>
|
|
317
480
|
</AccordionRoot>
|
|
318
481
|
```
|
|
@@ -321,24 +484,41 @@ alwaysApply: false
|
|
|
321
484
|
|
|
322
485
|
## Drawer
|
|
323
486
|
|
|
324
|
-
|
|
487
|
+
Drawer/bottom sheet. Based on Vaul. Compound component pattern.
|
|
325
488
|
|
|
326
489
|
| Prop | Type | Default | Description |
|
|
327
490
|
|---|---|---|---|
|
|
328
|
-
| `direction` | `'bottom' \| 'top' \| 'left' \| 'right'` | `
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
491
|
+
| `direction` | `'bottom'` \| `'top'` \| `'left'` \| `'right'` | `"bottom"` | Direction |
|
|
492
|
+
| `open` | `boolean` | - | Open state (controlled mode) |
|
|
493
|
+
| `onOpenChange` | `ReactNode` | - | Open state change callback (open: boolean) => void |
|
|
494
|
+
| `dismissible` | `boolean` | - | Allow close via swipe/outside click (default true) |
|
|
495
|
+
| `modal` | `boolean` | - | Modal mode (default true). If false, background is interactive |
|
|
496
|
+
| `shouldScaleBackground` | `boolean` | - | Background scale effect (default false) |
|
|
497
|
+
| `children` | `ReactNode` | - | Drawer sub-components (ReactNode, required) |
|
|
498
|
+
|
|
499
|
+
### DrawerContent
|
|
500
|
+
|
|
501
|
+
Drawer.Content area.
|
|
502
|
+
|
|
503
|
+
| Prop | Type | Default | Description |
|
|
504
|
+
|---|---|---|---|
|
|
505
|
+
| `direction` | `'bottom'` \| `'top'` \| `'left'` \| `'right'` | `"bottom"` | Direction (Context takes priority) |
|
|
506
|
+
| `blur` | `'none'` \| `'sm'` \| `'md'` | `"none"` | Overlay blur |
|
|
507
|
+
| `showHandle` | `boolean` | `true` | Show handle bar |
|
|
508
|
+
| `children` | `ReactNode` | - | Content area (ReactNode) |
|
|
509
|
+
| `overlayClassName` | `string` | - | Overlay style |
|
|
510
|
+
| `className` | `string` | - | Panel style |
|
|
331
511
|
|
|
332
512
|
```tsx
|
|
333
513
|
<Drawer direction="bottom">
|
|
334
514
|
<Drawer.Trigger asChild>
|
|
335
|
-
<Button
|
|
515
|
+
<Button>Open</Button>
|
|
336
516
|
</Drawer.Trigger>
|
|
337
517
|
<Drawer.Content>
|
|
338
|
-
<Drawer.Title
|
|
339
|
-
<Drawer.Description
|
|
518
|
+
<Drawer.Title>Title</Drawer.Title>
|
|
519
|
+
<Drawer.Description>Description</Drawer.Description>
|
|
340
520
|
<Drawer.Close asChild>
|
|
341
|
-
<Button variant="ghost"
|
|
521
|
+
<Button variant="ghost">Close</Button>
|
|
342
522
|
</Drawer.Close>
|
|
343
523
|
</Drawer.Content>
|
|
344
524
|
</Drawer>
|
|
@@ -346,353 +526,756 @@ alwaysApply: false
|
|
|
346
526
|
|
|
347
527
|
---
|
|
348
528
|
|
|
349
|
-
## Modal
|
|
529
|
+
## Modal
|
|
350
530
|
|
|
351
|
-
|
|
531
|
+
Modal template. All modal components must be wrapped with ModalTemplate.
|
|
352
532
|
|
|
353
|
-
|
|
533
|
+
| Prop | Type | Default | Description |
|
|
534
|
+
|---|---|---|---|
|
|
535
|
+
| `title` | `ReactNode` | - | Header title (ReactNode) |
|
|
536
|
+
| `desc` | `ReactNode` | - | Header description (ReactNode) |
|
|
537
|
+
| `layout` | `'default'` \| `'bottom-sheet'` \| `'slide-left'` \| `'slide-right'` \| `'full-page'` \| `'full-page-reverse'` \| `'draggable'` | `"default"` | Layout |
|
|
538
|
+
| `showDim` | `boolean` | `true` | Show dim overlay |
|
|
539
|
+
| `dimClose` | `boolean` | `true` | Close on dim click |
|
|
540
|
+
| `hideHeader` | `boolean` | `false` | Hide header |
|
|
541
|
+
| `hideFooter` | `boolean` | `true` | Hide footer |
|
|
542
|
+
| `footer` | `ReactNode` | - | Custom footer (ReactElement) |
|
|
543
|
+
| `animation` | `object` | - | Modal animation |
|
|
544
|
+
| `enableDrag` | `boolean` | `true` | Enable drag (bottom-sheet/draggable layouts) |
|
|
545
|
+
| `dragPersistKey` | `string` | - | Drag position persistence key |
|
|
546
|
+
| `close` | `ReactNode` | - | Modal close function (isAnimation?: boolean) => void (auto-injected) |
|
|
547
|
+
| `children` | `ReactNode` | - | Modal body (ReactNode, required) |
|
|
548
|
+
| `className` | `string` | - | Root wrapper style |
|
|
549
|
+
| `innerClassName` | `string` | - | Modal body style |
|
|
550
|
+
| `bodyClassName` | `string` | - | Body area style |
|
|
551
|
+
| `footerClassName` | `string` | - | Footer area style |
|
|
552
|
+
| `dimClassName` | `string` | - | Dim overlay style |
|
|
553
|
+
| `headerClassName` | `string` | - | Header area style |
|
|
554
|
+
|
|
555
|
+
### modal()
|
|
556
|
+
|
|
557
|
+
modal() function call options. component automatically receives close/resolve as props.
|
|
354
558
|
|
|
355
|
-
|
|
559
|
+
| Prop | Type | Default | Description |
|
|
560
|
+
|---|---|---|---|
|
|
561
|
+
| `component` | `ReactNode` | - | Modal component (required). Automatically receives close/resolve as props |
|
|
562
|
+
| `props` | `Record<string, any>` | - | Props to pass to component |
|
|
563
|
+
| `id` | `string` | - | Modal ID (used for duplicate check) |
|
|
564
|
+
| `layout` | `'default'` \| `'bottom-sheet'` \| `'slide-left'` \| `'slide-right'` \| `'full-page'` \| `'full-page-reverse'` \| `'draggable'` | - | Layout |
|
|
565
|
+
| `animation` | `object` | - | Modal animation |
|
|
566
|
+
| `scrollEnable` | `boolean` | - | Allow background scroll |
|
|
567
|
+
| `isToggle` | `boolean` | - | Toggle mode (close on re-call of same modal) |
|
|
568
|
+
| `isAlone` | `boolean` | - | Alone mode (close all existing modals before opening) |
|
|
569
|
+
| `duplicateCheck` | `boolean` | - | Prevent duplicate opening of same component |
|
|
570
|
+
| `disableEscapeKeyPress` | `boolean` | - | Disable close via ESC key |
|
|
571
|
+
| `componentName` | `string` | - | Modal identifier name (used for duplicate check, modal search) |
|
|
572
|
+
| `onOpen` | `ReactNode` | - | Callback when modal opens |
|
|
573
|
+
| `onClose` | `ReactNode` | - | Callback when modal closes |
|
|
574
|
+
|
|
575
|
+
**IMPORTANT: Modal components MUST be wrapped with `ModalTemplate`.**
|
|
356
576
|
|
|
357
577
|
```tsx
|
|
358
578
|
import { ModalTemplate } from '@nexus-cross/design-system/modal';
|
|
359
579
|
|
|
360
|
-
// 모달 컴포넌트는 반드시 close와 resolve를 props로 받는다
|
|
361
580
|
function MyModal({ close, resolve }: { close: () => void; resolve: (value: any) => void }) {
|
|
362
581
|
return (
|
|
363
582
|
<ModalTemplate
|
|
364
|
-
title="
|
|
365
|
-
desc="
|
|
583
|
+
title="Modal Title"
|
|
584
|
+
desc="Modal description (optional)"
|
|
366
585
|
close={close}
|
|
367
|
-
layout="default"
|
|
368
|
-
hideFooter
|
|
586
|
+
layout="default"
|
|
587
|
+
hideFooter
|
|
369
588
|
>
|
|
370
589
|
<div className="space-y-4">
|
|
371
|
-
<p className="text-text-secondary"
|
|
372
|
-
<Button onClick={() => resolve({ confirmed: true })}
|
|
590
|
+
<p className="text-text-secondary">Modal content</p>
|
|
591
|
+
<Button onClick={() => resolve({ confirmed: true })}>Confirm</Button>
|
|
373
592
|
</div>
|
|
374
593
|
</ModalTemplate>
|
|
375
594
|
);
|
|
376
595
|
}
|
|
377
596
|
```
|
|
378
597
|
|
|
379
|
-
###
|
|
380
|
-
|
|
381
|
-
| Prop | Type | Default | Description |
|
|
382
|
-
|---|---|---|---|
|
|
383
|
-
| `title` | `ReactNode` | - | 헤더 제목 |
|
|
384
|
-
| `desc` | `ReactNode` | - | 헤더 설명 |
|
|
385
|
-
| `close` | `() => void` (필수) | - | 닫기 함수 (props로 자동 주입됨) |
|
|
386
|
-
| `layout` | `'default' \| 'bottom-sheet' \| 'slide-left' \| 'slide-right' \| 'full-page' \| 'full-page-reverse' \| 'draggable'` | `'default'` | 레이아웃 |
|
|
387
|
-
| `showDim` | `boolean` | `true` | 딤 배경 표시 |
|
|
388
|
-
| `dimClose` | `boolean` | `true` | 딤 클릭 시 닫기 |
|
|
389
|
-
| `hideHeader` | `boolean` | `false` | 헤더 숨김 |
|
|
390
|
-
| `hideFooter` | `boolean` | `true` | 푸터 숨김 |
|
|
391
|
-
| `footer` | `ReactElement` | - | 커스텀 푸터 |
|
|
392
|
-
| `enableDrag` | `boolean` | `false` | 드래그 활성화 (draggable 레이아웃) |
|
|
393
|
-
| `dragPersistKey` | `string` | - | 드래그 위치 저장 키 |
|
|
394
|
-
| `innerClassName` | `string` | - | 모달 본체 스타일 오버라이드 |
|
|
395
|
-
| `bodyClassName` | `string` | - | 바디 영역 스타일 오버라이드 |
|
|
396
|
-
|
|
397
|
-
### 모달 호출
|
|
598
|
+
### Calling a Modal
|
|
398
599
|
|
|
399
600
|
```tsx
|
|
400
601
|
import { modal, useModal, ModalContainer } from '@nexus-cross/design-system/modal';
|
|
401
602
|
|
|
402
|
-
//
|
|
603
|
+
// ModalContainer MUST be placed at the app root
|
|
403
604
|
<ModalContainer />
|
|
404
605
|
|
|
405
|
-
//
|
|
606
|
+
// Method 1: modal() function
|
|
406
607
|
const result = await modal({
|
|
407
608
|
component: MyModal,
|
|
408
|
-
props: { /*
|
|
609
|
+
props: { /* additional props */ },
|
|
409
610
|
});
|
|
410
611
|
|
|
411
|
-
//
|
|
612
|
+
// Method 2: useModal() hook
|
|
412
613
|
const { modal: openModal } = useModal();
|
|
413
614
|
openModal({
|
|
414
615
|
component: MyModal,
|
|
415
|
-
options: { isAlone: true },
|
|
616
|
+
options: { isAlone: true },
|
|
416
617
|
});
|
|
417
618
|
```
|
|
418
619
|
|
|
419
|
-
###
|
|
620
|
+
### Prohibited
|
|
420
621
|
|
|
421
|
-
-
|
|
422
|
-
- `close` prop
|
|
423
|
-
-
|
|
622
|
+
- Do NOT create modal components without ModalTemplate (using plain `<div>`)
|
|
623
|
+
- Do NOT define the `close` prop manually (the system injects it automatically)
|
|
624
|
+
- Do NOT implement a separate dim/overlay inside the modal
|
|
424
625
|
|
|
425
626
|
---
|
|
426
627
|
|
|
427
|
-
##
|
|
628
|
+
## Tab
|
|
428
629
|
|
|
429
|
-
|
|
630
|
+
Tab navigation. line/pill variants.
|
|
430
631
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
632
|
+
| Prop | Type | Default | Description |
|
|
633
|
+
|---|---|---|---|
|
|
634
|
+
| `items` | `object`[] | - | Tab item array (required) |
|
|
635
|
+
| `activeKey` | `string` | - | Controlled mode active key |
|
|
636
|
+
| `defaultActiveKey` | `string` | - | Uncontrolled initial key |
|
|
637
|
+
| `variant` | `'line'` \| `'pill'` | `"line"` | Style |
|
|
638
|
+
| `size` | `'sm'` \| `'md'` | `"md"` | Size |
|
|
639
|
+
| `destroyInactive` | `boolean` | `false` | Unmount inactive panels |
|
|
640
|
+
| `onTabChange` | `ReactNode` | - | Tab change callback (key: string) => void |
|
|
641
|
+
| `className` | `string` | - | Root style |
|
|
642
|
+
| `tabListClassName` | `string` | - | Tab list style |
|
|
643
|
+
| `tabPanelClassName` | `string` | - | Tab panel style |
|
|
436
644
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
645
|
+
```tsx
|
|
646
|
+
<Tab
|
|
647
|
+
items={[
|
|
648
|
+
{ key: 'a', label: 'Tab A', children: <p>A</p> },
|
|
649
|
+
{ key: 'b', label: 'Tab B', children: <p>B</p> },
|
|
650
|
+
]}
|
|
651
|
+
defaultActiveKey="a"
|
|
652
|
+
variant="pill"
|
|
653
|
+
/>
|
|
442
654
|
```
|
|
443
655
|
|
|
444
656
|
---
|
|
445
657
|
|
|
446
|
-
##
|
|
658
|
+
## Carousel
|
|
447
659
|
|
|
448
|
-
|
|
660
|
+
Carousel. Based on Embla Carousel. Sub-components: CarouselSlide, CarouselPrev, CarouselNext, CarouselDots.
|
|
449
661
|
|
|
450
|
-
| Prop | Type | Description |
|
|
451
|
-
|
|
452
|
-
| `
|
|
453
|
-
| `
|
|
454
|
-
| `
|
|
455
|
-
| `
|
|
456
|
-
| `
|
|
662
|
+
| Prop | Type | Default | Description |
|
|
663
|
+
|---|---|---|---|
|
|
664
|
+
| `opts` | `Record<string, any>` | - | Embla options (loop, align, etc.) |
|
|
665
|
+
| `plugins` | `ReactNode`[] | - | Embla plugins |
|
|
666
|
+
| `onApiChange` | `ReactNode` | - | Embla API change callback (api: CarouselApi) => void |
|
|
667
|
+
| `children` | `ReactNode` | - | Carousel slides and sub-components (ReactNode) |
|
|
668
|
+
| `className` | `string` | - | Style override |
|
|
669
|
+
|
|
670
|
+
Sub-components: `CarouselSlide`, `CarouselPrev`, `CarouselNext`, `CarouselDots`
|
|
457
671
|
|
|
458
672
|
```tsx
|
|
459
|
-
<
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
</InfiniteScroll>
|
|
673
|
+
<Carousel opts={{ loop: true }}>
|
|
674
|
+
<CarouselSlide>Slide 1</CarouselSlide>
|
|
675
|
+
<CarouselSlide>Slide 2</CarouselSlide>
|
|
676
|
+
<CarouselPrev />
|
|
677
|
+
<CarouselNext />
|
|
678
|
+
<CarouselDots />
|
|
679
|
+
</Carousel>
|
|
467
680
|
```
|
|
468
681
|
|
|
469
682
|
---
|
|
470
683
|
|
|
471
|
-
##
|
|
684
|
+
## Pagination
|
|
472
685
|
|
|
473
|
-
|
|
686
|
+
Pagination. Previous/next + page number buttons.
|
|
474
687
|
|
|
475
688
|
| Prop | Type | Default | Description |
|
|
476
689
|
|---|---|---|---|
|
|
477
|
-
| `
|
|
478
|
-
| `
|
|
479
|
-
| `
|
|
480
|
-
| `
|
|
690
|
+
| `currentPage` | `number` | - | Current page (1-based, required) |
|
|
691
|
+
| `totalPages` | `number` | - | Total page count (required) |
|
|
692
|
+
| `siblingCount` | `number` | `1` | Number of pages shown on each side of current |
|
|
693
|
+
| `showEdges` | `boolean` | - | Always show first/last page |
|
|
694
|
+
| `size` | `'sm'` \| `'md'` | `"md"` | Size |
|
|
695
|
+
| `onPageChange` | `ReactNode` | - | Page change callback (page: number) => void, required |
|
|
696
|
+
| `className` | `string` | - | <nav> style |
|
|
481
697
|
|
|
482
698
|
```tsx
|
|
483
|
-
<
|
|
699
|
+
<Pagination currentPage={2} totalPages={10} onPageChange={setPage} />
|
|
484
700
|
```
|
|
485
701
|
|
|
486
702
|
---
|
|
487
703
|
|
|
488
|
-
##
|
|
704
|
+
## Avatar
|
|
489
705
|
|
|
490
|
-
|
|
706
|
+
Avatar. Supports image, fallback text, and children.
|
|
707
|
+
|
|
708
|
+
| Prop | Type | Default | Description |
|
|
709
|
+
|---|---|---|---|
|
|
710
|
+
| `src` | `string` | - | Image URL |
|
|
711
|
+
| `alt` | `string` | - | Alt text |
|
|
712
|
+
| `fallback` | `ReactNode` | - | Displayed on image load failure (ReactNode) |
|
|
713
|
+
| `size` | `'xs'` \| `'sm'` \| `'md'` \| `'lg'` \| `'xl'` | `"md"` | Size |
|
|
714
|
+
| `shape` | `'circle'` \| `'square'` | `"circle"` | Shape |
|
|
715
|
+
| `children` | `ReactNode` | - | Custom image element (e.g. Next.js Image) |
|
|
716
|
+
| `onImageError` | `ReactNode` | - | Image load error callback () => void |
|
|
717
|
+
| `className` | `string` | - | Style override |
|
|
491
718
|
|
|
492
719
|
```tsx
|
|
493
|
-
|
|
494
|
-
|
|
720
|
+
<Avatar src="/user.png" alt="User" size="lg" />
|
|
721
|
+
<Avatar fallback="JD" shape="square" size="sm" />
|
|
495
722
|
```
|
|
496
723
|
|
|
497
|
-
|
|
724
|
+
---
|
|
498
725
|
|
|
499
|
-
|
|
500
|
-
const { ref, inView } = useInView({ threshold: 0.5 });
|
|
501
|
-
<div ref={ref}>{inView && <LazyContent />}</div>
|
|
502
|
-
```
|
|
726
|
+
## Counter
|
|
503
727
|
|
|
504
|
-
|
|
728
|
+
Number count animation.
|
|
729
|
+
|
|
730
|
+
| Prop | Type | Default | Description |
|
|
731
|
+
|---|---|---|---|
|
|
732
|
+
| `endValue` | `number` | - | Target value (required) |
|
|
733
|
+
| `startValue` | `number` | `0` | Start value |
|
|
734
|
+
| `duration` | `number` | `1500` | Animation duration (ms) |
|
|
735
|
+
| `delay` | `number` | `0` | Start delay (ms) |
|
|
736
|
+
| `separator` | `boolean` | `true` | Thousands separator |
|
|
737
|
+
| `digits` | `number` | `0` | Decimal places |
|
|
738
|
+
| `triggerOnView` | `boolean` | `false` | Start on viewport entry |
|
|
739
|
+
| `onEnd` | `ReactNode` | - | Count complete callback () => void |
|
|
740
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
741
|
+
| `className` | `string` | - | Style override |
|
|
505
742
|
|
|
506
743
|
```tsx
|
|
507
|
-
|
|
744
|
+
<Counter endValue={1234} duration={2000} separator />
|
|
508
745
|
```
|
|
509
746
|
|
|
510
|
-
|
|
747
|
+
---
|
|
748
|
+
|
|
749
|
+
## Countdown
|
|
750
|
+
|
|
751
|
+
Countdown timer.
|
|
752
|
+
|
|
753
|
+
| Prop | Type | Default | Description |
|
|
754
|
+
|---|---|---|---|
|
|
755
|
+
| `endTimestamp` | `number` | - | End time (Unix ms, required) |
|
|
756
|
+
| `separator` | `ReactNode` | `":"` | Separator (ReactNode) |
|
|
757
|
+
| `showDays` | `boolean` | `true` | Show days unit |
|
|
758
|
+
| `labels` | `object` | - | Unit labels |
|
|
759
|
+
| `render` | `ReactNode` | - | Custom render function |
|
|
760
|
+
| `onEnd` | `ReactNode` | - | Countdown end callback () => void |
|
|
761
|
+
| `className` | `string` | - | Style override |
|
|
511
762
|
|
|
512
763
|
```tsx
|
|
513
|
-
|
|
514
|
-
<div ref={ref}>드롭다운 내용</div>
|
|
764
|
+
<Countdown endTimestamp={Date.now() + 60_000} showDays={false} onEnd={handleEnd} />
|
|
515
765
|
```
|
|
516
766
|
|
|
517
767
|
---
|
|
518
768
|
|
|
519
|
-
##
|
|
769
|
+
## Marquee
|
|
520
770
|
|
|
521
|
-
|
|
771
|
+
Marquee (scrolling text/elements).
|
|
522
772
|
|
|
523
773
|
| Prop | Type | Default | Description |
|
|
524
774
|
|---|---|---|---|
|
|
525
|
-
| `
|
|
526
|
-
| `
|
|
527
|
-
| `
|
|
528
|
-
| `
|
|
529
|
-
| `
|
|
775
|
+
| `direction` | `'left'` \| `'right'` \| `'up'` \| `'down'` | `"left"` | Direction |
|
|
776
|
+
| `speed` | `number` | `40` | Animation speed (seconds) |
|
|
777
|
+
| `pauseOnHover` | `boolean` | `false` | Pause on hover |
|
|
778
|
+
| `gap` | `number` | `16` | Item gap (px) |
|
|
779
|
+
| `children` | `ReactNode` | - | Content to repeat (ReactNode, required) |
|
|
780
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
781
|
+
| `className` | `string` | - | Style override |
|
|
530
782
|
|
|
531
783
|
```tsx
|
|
532
|
-
<
|
|
784
|
+
<Marquee direction="left" speed={30} pauseOnHover>
|
|
785
|
+
<span>Scrolling text</span>
|
|
786
|
+
</Marquee>
|
|
533
787
|
```
|
|
534
788
|
|
|
535
789
|
---
|
|
536
790
|
|
|
537
|
-
##
|
|
791
|
+
## VirtualList
|
|
538
792
|
|
|
539
|
-
|
|
793
|
+
Virtual scroll list. Based on @tanstack/react-virtual.
|
|
540
794
|
|
|
541
795
|
| Prop | Type | Default | Description |
|
|
542
796
|
|---|---|---|---|
|
|
543
|
-
| `
|
|
544
|
-
| `
|
|
545
|
-
| `
|
|
546
|
-
| `
|
|
547
|
-
| `
|
|
548
|
-
| `
|
|
797
|
+
| `items` | `ReactNode`[] | - | Data array (required) |
|
|
798
|
+
| `estimateSize` | `number` \| `ReactNode` | - | Estimated item height (number or (index) => number, required) |
|
|
799
|
+
| `renderItem` | `ReactNode` | - | Item renderer (item, index, virtualItem) => ReactNode (required) |
|
|
800
|
+
| `overscan` | `number` | `5` | Overscan count |
|
|
801
|
+
| `gap` | `number` | `0` | Item gap (px) |
|
|
802
|
+
| `className` | `string` | - | Scroll container style |
|
|
803
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
804
|
+
| `endReachedThreshold` | `number` | `200` | End detection threshold (px) |
|
|
805
|
+
| `onEndReached` | `ReactNode` | - | End reached callback () => void |
|
|
806
|
+
|
|
807
|
+
### VirtualGrid
|
|
808
|
+
|
|
809
|
+
Virtual scroll grid. Based on @tanstack/react-virtual.
|
|
810
|
+
|
|
811
|
+
| Prop | Type | Default | Description |
|
|
812
|
+
|---|---|---|---|
|
|
813
|
+
| `items` | `ReactNode`[] | - | Data array (required) |
|
|
814
|
+
| `columns` | `number` | - | Column count (required) |
|
|
815
|
+
| `estimateSize` | `number` \| `ReactNode` | - | Estimated item height (required) |
|
|
816
|
+
| `renderItem` | `ReactNode` | - | Item renderer (item, index) => ReactNode (required) |
|
|
817
|
+
| `overscan` | `number` | `3` | Overscan count |
|
|
818
|
+
| `gap` | `number` | `0` | Item gap (px) |
|
|
819
|
+
| `className` | `string` | - | Scroll container style |
|
|
820
|
+
| `style` | `ReactNode` | - | Inline style (CSSProperties) |
|
|
821
|
+
| `endReachedThreshold` | `number` | `200` | End detection threshold (px) |
|
|
822
|
+
| `onEndReached` | `ReactNode` | - | End reached callback () => void |
|
|
549
823
|
|
|
550
824
|
```tsx
|
|
551
|
-
<
|
|
552
|
-
|
|
825
|
+
<VirtualList
|
|
826
|
+
items={data}
|
|
827
|
+
estimateSize={48}
|
|
828
|
+
renderItem={(item) => <div>{item.name}</div>}
|
|
829
|
+
onEndReached={loadMore}
|
|
830
|
+
/>
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
### VirtualGrid
|
|
834
|
+
|
|
835
|
+
Same as VirtualList + `columns: number` (required).
|
|
836
|
+
|
|
837
|
+
```tsx
|
|
838
|
+
<VirtualGrid items={data} estimateSize={120} columns={3} renderItem={(item) => <Card {...item} />} />
|
|
553
839
|
```
|
|
554
840
|
|
|
555
841
|
---
|
|
556
842
|
|
|
557
|
-
##
|
|
843
|
+
## DataList
|
|
558
844
|
|
|
559
|
-
|
|
845
|
+
Data list. Automatically handles loading/skeleton/empty/data states based on list. Built-in ErrorBoundary.
|
|
560
846
|
|
|
561
847
|
| Prop | Type | Default | Description |
|
|
562
848
|
|---|---|---|---|
|
|
563
|
-
| `
|
|
564
|
-
| `
|
|
565
|
-
| `
|
|
566
|
-
| `
|
|
567
|
-
| `
|
|
568
|
-
| `
|
|
569
|
-
| `
|
|
570
|
-
| `
|
|
849
|
+
| `list` | `ReactNode`[] | - | Data array to render. null = loading state (required) |
|
|
850
|
+
| `noDataMessage` | `ReactNode` | - | Message for empty array (string | ReactElement) |
|
|
851
|
+
| `errorFallback` | `ReactNode` | - | Fallback on error (ReactNode) |
|
|
852
|
+
| `loadingElement` | `ReactNode` | - | Custom loading element (default: Spinner) |
|
|
853
|
+
| `skeletonElement` | `ReactNode` | - | Skeleton element during loading (ReactElement) |
|
|
854
|
+
| `skeletonCount` | `number` | `3` | Skeleton repeat count |
|
|
855
|
+
| `loading` | `boolean` | `false` | Force loading state |
|
|
856
|
+
| `children` | `ReactNode` | - | Item render function: ({ item, index }) => ReactNode (required) |
|
|
857
|
+
| `className` | `string` | - | Root element style |
|
|
858
|
+
|
|
859
|
+
When list is null → **loading**, [] → **empty state**, array → **render**. ErrorBoundary built-in.
|
|
860
|
+
|
|
861
|
+
- **Default loading**: Without skeletonElement, a Spinner is shown automatically
|
|
862
|
+
- **Skeleton loading**: Pass a custom skeleton component to skeletonElement, rendered skeletonCount times
|
|
571
863
|
|
|
572
864
|
```tsx
|
|
573
|
-
|
|
865
|
+
// Basic usage — Spinner shown automatically when list is null
|
|
866
|
+
<DataList list={users} noDataMessage="No users found">
|
|
867
|
+
{({ item, index }) => <UserCard key={item.id} user={item} />}
|
|
868
|
+
</DataList>
|
|
869
|
+
|
|
870
|
+
// Skeleton loading — implement and pass a custom skeleton component
|
|
871
|
+
function UserSkeleton() {
|
|
872
|
+
return (
|
|
873
|
+
<div className="flex items-center gap-3 px-4 py-3">
|
|
874
|
+
<Skeleton circle width={32} height={32} />
|
|
875
|
+
<div className="flex-1 space-y-1.5">
|
|
876
|
+
<Skeleton className="h-3 w-24" />
|
|
877
|
+
<Skeleton className="h-2.5 w-16" />
|
|
878
|
+
</div>
|
|
879
|
+
</div>
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
<DataList
|
|
884
|
+
list={products}
|
|
885
|
+
skeletonElement={<UserSkeleton />}
|
|
886
|
+
skeletonCount={5}
|
|
887
|
+
>
|
|
888
|
+
{({ item }) => <ProductCard key={item.id} {...item} />}
|
|
889
|
+
</DataList>
|
|
574
890
|
```
|
|
575
891
|
|
|
576
892
|
---
|
|
577
893
|
|
|
578
|
-
##
|
|
894
|
+
## InfiniteScroll
|
|
579
895
|
|
|
580
|
-
|
|
896
|
+
Infinite scroll. Based on IntersectionObserver.
|
|
581
897
|
|
|
582
898
|
| Prop | Type | Default | Description |
|
|
583
899
|
|---|---|---|---|
|
|
584
|
-
| `
|
|
585
|
-
| `
|
|
586
|
-
| `
|
|
587
|
-
| `
|
|
588
|
-
| `
|
|
589
|
-
| `
|
|
900
|
+
| `list` | `ReactNode`[] | - | Current data array (required) |
|
|
901
|
+
| `totalCount` | `number` | - | Total count (mutually exclusive with hasMore) |
|
|
902
|
+
| `hasMore` | `boolean` | - | Has more items (mutually exclusive with totalCount) |
|
|
903
|
+
| `tag` | `string` | `"div"` | Children wrapper tag |
|
|
904
|
+
| `rootMargin` | `number` | `100` | Detection margin (px) |
|
|
905
|
+
| `loading` | `boolean` | - | Loading state |
|
|
906
|
+
| `loadingElement` | `ReactNode` | - | Custom loading element |
|
|
907
|
+
| `handleLoadMore` | `ReactNode` | - | Load more callback () => void, required |
|
|
908
|
+
| `scrollTarget` | `ReactNode` | - | Scroll target element (HTMLElement | Document | MutableRefObject) |
|
|
909
|
+
| `children` | `ReactNode` | - | List item rendering (ReactNode, required) |
|
|
910
|
+
| `className` | `string` | - | Style override |
|
|
590
911
|
|
|
591
912
|
```tsx
|
|
592
|
-
<
|
|
913
|
+
<InfiniteScroll
|
|
914
|
+
list={items}
|
|
915
|
+
totalCount={100}
|
|
916
|
+
loading={isLoading}
|
|
917
|
+
handleLoadMore={fetchMore}
|
|
918
|
+
>
|
|
919
|
+
{items.map(item => <Card key={item.id} {...item} />)}
|
|
920
|
+
</InfiniteScroll>
|
|
593
921
|
```
|
|
594
922
|
|
|
595
923
|
---
|
|
596
924
|
|
|
597
|
-
##
|
|
925
|
+
## Ellipsis
|
|
598
926
|
|
|
599
|
-
|
|
927
|
+
Text ellipsis. Built-in show more/less toggle.
|
|
600
928
|
|
|
601
929
|
| Prop | Type | Default | Description |
|
|
602
930
|
|---|---|---|---|
|
|
603
|
-
| `
|
|
604
|
-
| `
|
|
605
|
-
| `
|
|
606
|
-
| `
|
|
931
|
+
| `content` | `ReactNode` | `""` | Body text (ReactNode) |
|
|
932
|
+
| `lineClamp` | `number` | `2` | Line clamp limit |
|
|
933
|
+
| `triggerMore` | `ReactNode` | `"more"` | Show more text (ReactNode) |
|
|
934
|
+
| `triggerLess` | `ReactNode` | `"less"` | Show less text (ReactNode) |
|
|
935
|
+
| `defaultShortened` | `boolean` | `true` | Initial collapsed state |
|
|
936
|
+
| `observingEnvs` | `boolean`[] | - | Re-measure on external condition change |
|
|
937
|
+
| `onShowMoreLessClick` | `ReactNode` | - | Show more/less click callback () => void |
|
|
938
|
+
| `className` | `string` | - | Style override |
|
|
607
939
|
|
|
608
940
|
```tsx
|
|
609
|
-
<
|
|
610
|
-
<span>흐르는 텍스트</span>
|
|
611
|
-
</Marquee>
|
|
941
|
+
<Ellipsis content={longText} lineClamp={3} triggerMore="more" triggerLess="less" />
|
|
612
942
|
```
|
|
613
943
|
|
|
614
944
|
---
|
|
615
945
|
|
|
616
|
-
##
|
|
946
|
+
## NumberInput
|
|
617
947
|
|
|
618
|
-
|
|
948
|
+
Number input. Accelerated increment on long press. Exposes increment/decrement methods via ref. numberInputBind(ref, direction) binds same acceleration to external buttons.
|
|
619
949
|
|
|
620
950
|
| Prop | Type | Default | Description |
|
|
621
951
|
|---|---|---|---|
|
|
622
|
-
| `
|
|
623
|
-
| `
|
|
624
|
-
| `
|
|
625
|
-
| `
|
|
626
|
-
| `
|
|
627
|
-
| `
|
|
628
|
-
| `
|
|
952
|
+
| `value` | `number` \| `string` | - | Current value |
|
|
953
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` \| `'xl'` | `"md"` | Size |
|
|
954
|
+
| `error` | `boolean` | - | Error state |
|
|
955
|
+
| `min` | `number` | - | Minimum value |
|
|
956
|
+
| `max` | `number` | - | Maximum value |
|
|
957
|
+
| `step` | `number` | `1` | Step increment |
|
|
958
|
+
| `digit` | `number` | `0` | Decimal places |
|
|
959
|
+
| `hideButtons` | `boolean` | `false` | Hide default spin buttons. Use with numberInputBind for external button event binding |
|
|
960
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
961
|
+
| `readOnly` | `boolean` | - | Read-only (includes hiding spin buttons) |
|
|
962
|
+
| `placeholder` | `string` | - | Placeholder |
|
|
963
|
+
| `name` | `string` | - | Form field name |
|
|
964
|
+
| `id` | `string` | - | Element ID |
|
|
965
|
+
| `autoFocus` | `boolean` | - | Auto focus |
|
|
966
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: number | undefined) => void |
|
|
967
|
+
| `onBlur` | `ReactNode` | - | Blur callback |
|
|
968
|
+
| `onFocus` | `ReactNode` | - | Focus callback |
|
|
969
|
+
| `className` | `string` | - | Style override |
|
|
970
|
+
|
|
971
|
+
Press-and-hold accelerates increment/decrement (100ms → 75ms → 50ms → 30ms). Default is right-side vertical spin buttons. Use `numberInputBind(ref, direction)` to bind the same acceleration events to external buttons for free placement.
|
|
629
972
|
|
|
630
973
|
```tsx
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
974
|
+
// Basic usage — right-side vertical spin buttons
|
|
975
|
+
<NumberInput
|
|
976
|
+
value={count}
|
|
977
|
+
onValueChange={setCount}
|
|
978
|
+
min={0}
|
|
979
|
+
max={100}
|
|
980
|
+
step={5}
|
|
638
981
|
/>
|
|
982
|
+
|
|
983
|
+
// External buttons — bind events with numberInputBind
|
|
984
|
+
const ref = useRef<NumberInputRef>(null);
|
|
985
|
+
|
|
986
|
+
<NumberInput ref={ref} value={count} onValueChange={setCount} hideButtons />
|
|
987
|
+
|
|
988
|
+
// Buttons can be placed anywhere, completely separate from NumberInput
|
|
989
|
+
<button {...numberInputBind(ref, 'decrement')}><MinusIcon /></button>
|
|
990
|
+
<button {...numberInputBind(ref, 'increment')}><PlusIcon /></button>
|
|
991
|
+
|
|
992
|
+
// Single invocation (onClick)
|
|
993
|
+
<button onClick={() => ref.current?.increment()}>+1</button>
|
|
639
994
|
```
|
|
640
995
|
|
|
641
996
|
---
|
|
642
997
|
|
|
643
|
-
##
|
|
998
|
+
## PriceInput
|
|
644
999
|
|
|
645
|
-
|
|
1000
|
+
Price/amount input field with prefix, suffix, balance display, and auto-fill on balance click.
|
|
646
1001
|
|
|
647
1002
|
| Prop | Type | Default | Description |
|
|
648
1003
|
|---|---|---|---|
|
|
649
|
-
| `
|
|
650
|
-
| `
|
|
651
|
-
| `
|
|
1004
|
+
| `size` | `'md'` \| `'lg'` \| `'xl'` | `"md"` | Size |
|
|
1005
|
+
| `error` | `boolean` | - | Error state (shows danger border) |
|
|
1006
|
+
| `prefix` | `boolean` \| `ReactNode` | `true` | Prefix element. true = "$", ReactNode = custom content, false = hidden |
|
|
1007
|
+
| `suffix` | `ReactNode` | - | Suffix element after the input (e.g. "CROSSD", icon, ReactNode) |
|
|
1008
|
+
| `label` | `ReactNode` | - | Label displayed above the input (ReactNode) |
|
|
1009
|
+
| `description` | `ReactNode` | - | Description below the input. Turns red on error (ReactNode) |
|
|
1010
|
+
| `balance` | `string` \| `number` | - | Balance value in the header. Clicking fills the input |
|
|
1011
|
+
| `balanceLabel` | `string` | `"Balance"` | Label text for balance display |
|
|
1012
|
+
| `balanceContent` | `ReactNode` | - | Custom balance display (ReactNode). Replaces default text, keeps click-to-fill |
|
|
1013
|
+
| `maxBalance` | `number` | - | Max allowed value. Exceeding auto-applies error state and turns balance red |
|
|
1014
|
+
| `separator` | `boolean` | `false` | Display thousands separator (comma). onValueChange receives raw value without commas |
|
|
1015
|
+
| `align` | `'left'` \| `'right'` | `"left"` | Text alignment inside the input |
|
|
1016
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
1017
|
+
| `placeholder` | `string` | - | Placeholder |
|
|
1018
|
+
| `value` | `ReactNode` | - | Controlled value |
|
|
1019
|
+
| `id` | `string` | - | Element ID |
|
|
1020
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: string) => void |
|
|
1021
|
+
| `onBalanceClick` | `ReactNode` | - | Balance click callback (balance: string | number) => void |
|
|
1022
|
+
| `className` | `string` | - | Style override |
|
|
652
1023
|
|
|
653
|
-
|
|
1024
|
+
---
|
|
654
1025
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
1026
|
+
## Badge
|
|
1027
|
+
|
|
1028
|
+
Badge indicator. Dot or count display. Wraps children when provided.
|
|
1029
|
+
|
|
1030
|
+
| Prop | Type | Default | Description |
|
|
1031
|
+
|---|---|---|---|
|
|
1032
|
+
| `count` | `number` | - | Badge count number |
|
|
1033
|
+
| `max` | `number` | `99` | Max count (shows "99+" when exceeded) |
|
|
1034
|
+
| `dot` | `boolean` | `false` | Show as dot instead of count |
|
|
1035
|
+
| `showZero` | `boolean` | `false` | Show badge when count is 0 |
|
|
1036
|
+
| `variant` | `'danger'` \| `'primary'` \| `'secondary'` \| `'info'` \| `'success'` \| `'warning'` | `"danger"` | Color variant |
|
|
1037
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Size |
|
|
1038
|
+
| `offset` | `any` | - | Position offset [x, y] in px |
|
|
1039
|
+
| `children` | `ReactNode` | - | Anchor element to attach badge to (ReactNode) |
|
|
1040
|
+
| `className` | `string` | - | Style override |
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
## Progress
|
|
1045
|
+
|
|
1046
|
+
Progress bar. Linear progress indicator with percentage display.
|
|
1047
|
+
|
|
1048
|
+
| Prop | Type | Default | Description |
|
|
1049
|
+
|---|---|---|---|
|
|
1050
|
+
| `value` | `number` | `0` | Current progress value |
|
|
1051
|
+
| `max` | `number` | `100` | Maximum value |
|
|
1052
|
+
| `variant` | `'primary'` \| `'success'` \| `'warning'` \| `'danger'` \| `'info'` | `"primary"` | Color variant |
|
|
1053
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Bar height |
|
|
1054
|
+
| `showValue` | `boolean` | `false` | Show percentage text |
|
|
1055
|
+
| `indeterminate` | `boolean` | `false` | Indeterminate loading animation |
|
|
1056
|
+
| `label` | `string` | - | Label text above the bar |
|
|
1057
|
+
| `className` | `string` | - | Style override |
|
|
1058
|
+
|
|
1059
|
+
---
|
|
1060
|
+
|
|
1061
|
+
## Alert
|
|
1062
|
+
|
|
1063
|
+
Alert / Banner. Inline notification with icon, title, description.
|
|
1064
|
+
|
|
1065
|
+
| Prop | Type | Default | Description |
|
|
1066
|
+
|---|---|---|---|
|
|
1067
|
+
| `variant` | `'info'` \| `'success'` \| `'warning'` \| `'danger'` | `"info"` | Alert type / color |
|
|
1068
|
+
| `title` | `string` | - | Alert title (bold) |
|
|
1069
|
+
| `children` | `ReactNode` | - | Alert description (ReactNode) |
|
|
1070
|
+
| `icon` | `ReactNode` | - | Custom icon (ReactNode). Auto icon by variant if omitted |
|
|
1071
|
+
| `closable` | `boolean` | `false` | Show close button |
|
|
1072
|
+
| `onClose` | `ReactNode` | - | Close callback () => void |
|
|
1073
|
+
| `action` | `ReactNode` | - | Action area (ReactNode, e.g. Button) |
|
|
1074
|
+
| `className` | `string` | - | Style override |
|
|
1075
|
+
|
|
1076
|
+
---
|
|
1077
|
+
|
|
1078
|
+
## EmptyState
|
|
1079
|
+
|
|
1080
|
+
Empty state placeholder. Shown when data is empty or unavailable.
|
|
1081
|
+
|
|
1082
|
+
| Prop | Type | Default | Description |
|
|
1083
|
+
|---|---|---|---|
|
|
1084
|
+
| `icon` | `ReactNode` | - | Custom icon (ReactNode). Default inbox icon |
|
|
1085
|
+
| `title` | `string` | - | Title text |
|
|
1086
|
+
| `description` | `string` | - | Description text |
|
|
1087
|
+
| `action` | `ReactNode` | - | Action area (ReactNode, e.g. Button) |
|
|
1088
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Overall size |
|
|
1089
|
+
| `children` | `ReactNode` | - | Additional content (ReactNode) |
|
|
1090
|
+
| `className` | `string` | - | Style override |
|
|
664
1091
|
|
|
665
1092
|
---
|
|
666
1093
|
|
|
667
|
-
##
|
|
1094
|
+
## Breadcrumb
|
|
668
1095
|
|
|
669
|
-
|
|
1096
|
+
Breadcrumb navigation. Shows current location path.
|
|
1097
|
+
|
|
1098
|
+
| Prop | Type | Default | Description |
|
|
1099
|
+
|---|---|---|---|
|
|
1100
|
+
| `items` | `object`[] | - | Breadcrumb items array (required) |
|
|
1101
|
+
| `separator` | `ReactNode` | - | Custom separator (ReactNode). Default: chevron |
|
|
1102
|
+
| `maxItems` | `number` | - | Max visible items (collapses middle with "...") |
|
|
1103
|
+
| `className` | `string` | - | Style override |
|
|
1104
|
+
|
|
1105
|
+
---
|
|
670
1106
|
|
|
671
|
-
|
|
1107
|
+
## Stepper
|
|
1108
|
+
|
|
1109
|
+
Stepper. Step-by-step progress indicator.
|
|
672
1110
|
|
|
673
1111
|
| Prop | Type | Default | Description |
|
|
674
1112
|
|---|---|---|---|
|
|
675
|
-
| `
|
|
676
|
-
| `
|
|
677
|
-
| `
|
|
678
|
-
| `
|
|
679
|
-
| `
|
|
680
|
-
| `
|
|
681
|
-
|
|
1113
|
+
| `steps` | `object`[] | - | Step items array (required) |
|
|
1114
|
+
| `current` | `number` | `0` | Current step index (0-based) |
|
|
1115
|
+
| `status` | `'process'` \| `'error'` | `"process"` | Current step status |
|
|
1116
|
+
| `orientation` | `'horizontal'` \| `'vertical'` | `"horizontal"` | Layout direction |
|
|
1117
|
+
| `size` | `'sm'` \| `'md'` | `"md"` | Size |
|
|
1118
|
+
| `className` | `string` | - | Style override |
|
|
1119
|
+
|
|
1120
|
+
---
|
|
1121
|
+
|
|
1122
|
+
## DropdownMenu
|
|
1123
|
+
|
|
1124
|
+
Dropdown menu. Based on Radix DropdownMenu. Action menu for context/more menus.
|
|
1125
|
+
|
|
1126
|
+
| Prop | Type | Default | Description |
|
|
1127
|
+
|---|---|---|---|
|
|
1128
|
+
| `children` | `ReactNode` | - | Trigger element (ReactNode, required) |
|
|
1129
|
+
| `items` | `object`[] | - | Menu items array (required) |
|
|
1130
|
+
| `align` | `'start'` \| `'center'` \| `'end'` | `"start"` | Alignment |
|
|
1131
|
+
| `side` | `'top'` \| `'right'` \| `'bottom'` \| `'left'` | `"bottom"` | Position |
|
|
1132
|
+
| `className` | `string` | - | Trigger wrapper style |
|
|
1133
|
+
| `contentClassName` | `string` | - | Content panel style |
|
|
1134
|
+
|
|
1135
|
+
---
|
|
1136
|
+
|
|
1137
|
+
## ToggleGroup
|
|
1138
|
+
|
|
1139
|
+
Toggle group / Segment control. Based on Radix ToggleGroup.
|
|
1140
|
+
|
|
1141
|
+
| Prop | Type | Default | Description |
|
|
1142
|
+
|---|---|---|---|
|
|
1143
|
+
| `type` | `'single'` \| `'multiple'` | `"single"` | Selection mode |
|
|
1144
|
+
| `items` | `object`[] | - | Toggle items array (required) |
|
|
1145
|
+
| `value` | `ReactNode` | - | Controlled value (string | string[]) |
|
|
1146
|
+
| `defaultValue` | `ReactNode` | - | Default value |
|
|
1147
|
+
| `onValueChange` | `ReactNode` | - | Value change callback |
|
|
1148
|
+
| `variant` | `'default'` \| `'outline'` | `"default"` | Style variant |
|
|
1149
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Size |
|
|
1150
|
+
| `disabled` | `boolean` | - | Disable all items |
|
|
1151
|
+
| `className` | `string` | - | Style override |
|
|
1152
|
+
|
|
1153
|
+
---
|
|
1154
|
+
|
|
1155
|
+
## Slider
|
|
1156
|
+
|
|
1157
|
+
Slider / Range input. Based on Radix Slider. Supports single and range mode.
|
|
1158
|
+
|
|
1159
|
+
| Prop | Type | Default | Description |
|
|
1160
|
+
|---|---|---|---|
|
|
1161
|
+
| `value` | `number`[] | - | Controlled value (number[]). Use [50] for single, [20, 80] for range |
|
|
1162
|
+
| `defaultValue` | `number`[] | - | Default value |
|
|
1163
|
+
| `min` | `number` | `0` | Minimum |
|
|
1164
|
+
| `max` | `number` | `100` | Maximum |
|
|
1165
|
+
| `step` | `number` | `1` | Step increment |
|
|
1166
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Track height / thumb size |
|
|
1167
|
+
| `showValue` | `boolean` | `false` | Show current value text |
|
|
1168
|
+
| `formatValue` | `ReactNode` | - | Value format function (value: number) => string |
|
|
1169
|
+
| `label` | `string` | - | Label text |
|
|
1170
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
1171
|
+
| `onValueChange` | `ReactNode` | - | Value change callback (value: number[]) => void |
|
|
1172
|
+
| `onValueCommit` | `ReactNode` | - | Committed value callback (on pointer up) |
|
|
1173
|
+
| `className` | `string` | - | Style override |
|
|
1174
|
+
|
|
1175
|
+
---
|
|
1176
|
+
|
|
1177
|
+
## TagInput
|
|
1178
|
+
|
|
1179
|
+
Tag input. Enter key to add, Backspace to delete last tag.
|
|
1180
|
+
|
|
1181
|
+
| Prop | Type | Default | Description |
|
|
1182
|
+
|---|---|---|---|
|
|
1183
|
+
| `value` | `string`[] | - | Controlled tags array |
|
|
1184
|
+
| `defaultValue` | `string`[] | - | Default tags |
|
|
1185
|
+
| `onChange` | `ReactNode` | - | Tags change callback (tags: string[]) => void |
|
|
1186
|
+
| `placeholder` | `string` | `"태그 입력 후 Enter"` | Input placeholder |
|
|
1187
|
+
| `max` | `number` | - | Maximum number of tags |
|
|
1188
|
+
| `disabled` | `boolean` | - | Disabled |
|
|
1189
|
+
| `allowDuplicates` | `boolean` | `false` | Allow duplicate tags |
|
|
1190
|
+
| `label` | `string` | - | Label text |
|
|
1191
|
+
| `description` | `string` | - | Helper text below input |
|
|
1192
|
+
| `size` | `'sm'` \| `'md'` \| `'lg'` | `"md"` | Size |
|
|
1193
|
+
| `className` | `string` | - | Style override |
|
|
1194
|
+
|
|
1195
|
+
---
|
|
1196
|
+
|
|
1197
|
+
## NxImage
|
|
1198
|
+
|
|
1199
|
+
Enhanced image. Lazy loading, fallback, aspect-ratio support.
|
|
1200
|
+
|
|
1201
|
+
| Prop | Type | Default | Description |
|
|
1202
|
+
|---|---|---|---|
|
|
1203
|
+
| `src` | `string` | - | Image source URL |
|
|
1204
|
+
| `alt` | `string` | - | Alt text |
|
|
1205
|
+
| `fallback` | `ReactNode` | - | Custom fallback element (ReactNode) |
|
|
1206
|
+
| `fallbackSrc` | `string` | - | Fallback image URL on error |
|
|
1207
|
+
| `aspectRatio` | `string` | - | CSS aspect-ratio (e.g. "16/9", "1/1") |
|
|
1208
|
+
| `objectFit` | `'cover'` \| `'contain'` \| `'fill'` \| `'none'` | `"cover"` | Object-fit mode |
|
|
1209
|
+
| `lazy` | `boolean` | `true` | Enable lazy loading (loading="lazy") |
|
|
1210
|
+
| `wrapperClassName` | `string` | - | Wrapper div style |
|
|
1211
|
+
| `className` | `string` | - | Image element style |
|
|
1212
|
+
|
|
1213
|
+
---
|
|
1214
|
+
|
|
1215
|
+
## DatePicker
|
|
1216
|
+
|
|
1217
|
+
DatePicker. Calendar popup for date selection. Based on react-day-picker.
|
|
1218
|
+
|
|
1219
|
+
| Prop | Type | Default | Description |
|
|
1220
|
+
|---|---|---|---|
|
|
1221
|
+
| `value` | `ReactNode` | - | Controlled date value (Date) |
|
|
1222
|
+
| `defaultValue` | `ReactNode` | - | Default date (Date) |
|
|
1223
|
+
| `onChange` | `ReactNode` | - | Date change callback (date: Date | undefined) => void |
|
|
1224
|
+
| `placeholder` | `string` | `"날짜 선택"` | Placeholder text |
|
|
1225
|
+
| `disabled` | `boolean` | `false` | Disabled |
|
|
1226
|
+
| `minDate` | `ReactNode` | - | Minimum selectable date (Date) |
|
|
1227
|
+
| `maxDate` | `ReactNode` | - | Maximum selectable date (Date) |
|
|
1228
|
+
| `locale` | `'ko'` \| `'en'` | `"ko"` | Calendar locale |
|
|
1229
|
+
| `formatStr` | `string` | `"yyyy-MM-dd"` | Date format string (date-fns format) |
|
|
1230
|
+
| `className` | `string` | - | Style override |
|
|
1231
|
+
|
|
1232
|
+
---
|
|
1233
|
+
|
|
1234
|
+
## Hooks
|
|
1235
|
+
|
|
1236
|
+
### useModal
|
|
682
1237
|
|
|
683
1238
|
```tsx
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
estimateSize={48}
|
|
687
|
-
renderItem={(item) => <div>{item.name}</div>}
|
|
688
|
-
onEndReached={loadMore}
|
|
689
|
-
/>
|
|
1239
|
+
const { open, close } = useModal();
|
|
1240
|
+
open(MyComponent, { title: 'Title' });
|
|
690
1241
|
```
|
|
691
1242
|
|
|
692
|
-
###
|
|
1243
|
+
### useInView
|
|
693
1244
|
|
|
694
|
-
|
|
1245
|
+
```tsx
|
|
1246
|
+
const { ref, inView } = useInView({ threshold: 0.5 });
|
|
1247
|
+
<div ref={ref}>{inView && <LazyContent />}</div>
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
### useCheckDevice
|
|
695
1251
|
|
|
696
1252
|
```tsx
|
|
697
|
-
|
|
1253
|
+
const { isMobile, isTablet, isDesktop } = useCheckDevice();
|
|
698
1254
|
```
|
|
1255
|
+
|
|
1256
|
+
### useClickOutside
|
|
1257
|
+
|
|
1258
|
+
```tsx
|
|
1259
|
+
const ref = useClickOutside<HTMLDivElement>(() => setOpen(false));
|
|
1260
|
+
<div ref={ref}>Dropdown content</div>
|
|
1261
|
+
```
|
|
1262
|
+
|
|
1263
|
+
---
|
|
1264
|
+
|
|
1265
|
+
## Toast (Imperative API)
|
|
1266
|
+
|
|
1267
|
+
Toast notifications. Sonner-based.
|
|
1268
|
+
|
|
1269
|
+
```tsx
|
|
1270
|
+
import { toast, Toaster } from '@nexus-cross/design-system';
|
|
1271
|
+
|
|
1272
|
+
// Place Toaster at app root
|
|
1273
|
+
<Toaster position="top-right" />
|
|
1274
|
+
|
|
1275
|
+
// Usage
|
|
1276
|
+
toast('Saved successfully');
|
|
1277
|
+
toast.success('Success!');
|
|
1278
|
+
toast.error('An error occurred');
|
|
1279
|
+
toast.loading('Processing...');
|
|
1280
|
+
```
|
|
1281
|
+
|