@adamosuiteservices/ui 2.18.6 → 2.19.1
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/README.md +1 -1
- package/dist/accordion-rounded.cjs +8 -8
- package/dist/accordion-rounded.js +12 -12
- package/dist/accordion.cjs +1 -1
- package/dist/accordion.js +1 -1
- package/dist/alert.cjs +32 -23
- package/dist/alert.js +53 -43
- package/dist/amount-input.cjs +8 -0
- package/dist/amount-input.js +191 -0
- package/dist/avatar.cjs +7 -7
- package/dist/avatar.js +18 -18
- package/dist/badge.cjs +24 -28
- package/dist/badge.js +45 -42
- package/dist/breadcrumb.cjs +3 -4
- package/dist/breadcrumb.js +17 -18
- package/dist/button-CPm4-98H.cjs +87 -0
- package/dist/button-D4ddrxyp.js +156 -0
- package/dist/button-group.cjs +1 -1
- package/dist/button-group.js +1 -1
- package/dist/button.cjs +1 -1
- package/dist/button.js +1 -1
- package/dist/{calendar-Dorq3-wv.cjs → calendar-DXq90PYV.cjs} +20 -22
- package/dist/{calendar-xBaFu2sB.js → calendar-DgfO9zab.js} +239 -240
- package/dist/calendar.cjs +1 -1
- package/dist/calendar.js +1 -1
- package/dist/card.cjs +3 -3
- package/dist/card.js +4 -4
- package/dist/checkbox-CIzBdqN7.cjs +24 -0
- package/dist/{checkbox-DL_jFvgl.js → checkbox-DPlUjwLi.js} +54 -52
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/colors.css +1 -1
- package/dist/combobox-DG9u4g84.js +692 -0
- package/dist/combobox-DylTjGrw.cjs +57 -0
- package/dist/combobox.cjs +1 -1
- package/dist/combobox.js +1 -1
- package/dist/components/layout/sidebar/sidebar.d.ts +2 -1
- package/dist/components/layout/toaster/toaster.d.ts +1 -1
- package/dist/components/ui/alert/alert.d.ts +1 -1
- package/dist/components/ui/amount-input/amount-input.d.ts +32 -0
- package/dist/components/ui/amount-input/index.d.ts +1 -0
- package/dist/components/ui/badge/badge.d.ts +3 -2
- package/dist/components/ui/calendar/calendar.d.ts +1 -1
- package/dist/components/ui/combobox/combobox.d.ts +3 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts +3 -1
- package/dist/components/ui/selectable-card/index.d.ts +1 -0
- package/dist/components/ui/selectable-card/selectable-card.d.ts +22 -0
- package/dist/components/ui/timeline/index.d.ts +1 -0
- package/dist/components/ui/timeline/timeline.d.ts +30 -0
- package/dist/components/ui/typography/typography.d.ts +1 -1
- package/dist/context-menu.cjs +18 -19
- package/dist/context-menu.js +37 -38
- package/dist/date-picker-selector.cjs +1 -1
- package/dist/date-picker-selector.js +3 -3
- package/dist/dialog.cjs +7 -9
- package/dist/dialog.js +36 -38
- package/dist/dropdown-menu.cjs +57 -36
- package/dist/dropdown-menu.js +206 -173
- package/dist/field.cjs +12 -7
- package/dist/field.js +51 -45
- package/dist/file-upload-v2.cjs +11 -5
- package/dist/file-upload-v2.js +75 -60
- package/dist/file-upload.cjs +11 -5
- package/dist/file-upload.js +118 -110
- package/dist/full-screen-loader.cjs +1 -1
- package/dist/full-screen-loader.js +1 -1
- package/dist/{icon-B7joBr0A.cjs → icon-C5Q2b1Am.cjs} +1 -1
- package/dist/{icon-BFQz1tQC.js → icon-t4jt1Z2h.js} +1 -1
- package/dist/icon.cjs +1 -1
- package/dist/icon.js +1 -1
- package/dist/index-BBT2EGq8.js +18 -0
- package/dist/index-DCsgSkBj.cjs +1 -0
- package/dist/input-8sEO5zwD.js +44 -0
- package/dist/input-AONeSXcs.cjs +22 -0
- package/dist/input-group-BLffLxyg.cjs +86 -0
- package/dist/input-group-DmevJAqa.js +240 -0
- package/dist/input-group.cjs +1 -84
- package/dist/input-group.js +7 -234
- package/dist/input-otp.cjs +5 -7
- package/dist/input-otp.js +58 -60
- package/dist/input.cjs +1 -1
- package/dist/input.js +1 -1
- package/dist/kbd.cjs +6 -7
- package/dist/kbd.js +14 -15
- package/dist/{label-DqfX9cHc.cjs → label-B7Z1D5-Q.cjs} +5 -4
- package/dist/{label-C6zVnc3d.js → label-_BWRIH7C.js} +14 -13
- package/dist/label.cjs +1 -1
- package/dist/label.js +1 -1
- package/dist/pagination.cjs +5 -5
- package/dist/pagination.js +18 -18
- package/dist/radio-group.cjs +12 -9
- package/dist/radio-group.js +66 -63
- package/dist/select.cjs +18 -16
- package/dist/select.js +18 -16
- package/dist/selectable-card.cjs +29 -0
- package/dist/selectable-card.js +129 -0
- package/dist/separator-DXdc7LcC.cjs +7 -0
- package/dist/{separator-CsaqP20m.js → separator-DZfXXbNt.js} +1 -1
- package/dist/separator.cjs +1 -1
- package/dist/separator.js +1 -1
- package/dist/{sheet-Cnq7TCzu.cjs → sheet-Cp6JGhWC.cjs} +10 -10
- package/dist/{sheet-C9vce0ut.js → sheet-hWerE8S1.js} +9 -6
- package/dist/sheet.cjs +1 -1
- package/dist/sheet.js +1 -1
- package/dist/sidebar.cjs +10 -10
- package/dist/sidebar.js +83 -92
- package/dist/slider.cjs +1 -1
- package/dist/slider.js +1 -1
- package/dist/{spinner-C7q7NthY.cjs → spinner-DUZ2vcus.cjs} +1 -1
- package/dist/{spinner-DQ5JLL3U.js → spinner-_-J3zJ_g.js} +1 -1
- package/dist/spinner.cjs +1 -1
- package/dist/spinner.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/switch.cjs +2 -4
- package/dist/switch.js +71 -73
- package/dist/table.cjs +14 -14
- package/dist/table.js +12 -12
- package/dist/tabs-underline.cjs +11 -15
- package/dist/tabs-underline.js +20 -24
- package/dist/tabs.cjs +10 -14
- package/dist/tabs.js +20 -24
- package/dist/tailwind-colors.css +1 -1
- package/dist/tailwind-theme.css +1 -1
- package/dist/textarea-BSooGyp-.cjs +18 -0
- package/dist/textarea-D_sj6ivo.js +39 -0
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/themes.css +1 -1
- package/dist/timeline.cjs +4 -0
- package/dist/timeline.js +189 -0
- package/dist/toaster.cjs +5 -4
- package/dist/toaster.js +33 -32
- package/dist/toggle.cjs +4 -4
- package/dist/toggle.js +17 -17
- package/dist/tooltip.cjs +5 -6
- package/dist/tooltip.js +4 -5
- package/docs/components/layout/sidebar.md +81 -53
- package/docs/components/layout/toaster.md +35 -55
- package/docs/components/ui/accordion-rounded.md +12 -11
- package/docs/components/ui/alert.md +66 -36
- package/docs/components/ui/amount-input.md +229 -0
- package/docs/components/ui/avatar.md +28 -32
- package/docs/components/ui/badge.md +85 -32
- package/docs/components/ui/breadcrumb.md +5 -7
- package/docs/components/ui/button-group.md +16 -16
- package/docs/components/ui/button.md +23 -36
- package/docs/components/ui/calendar.md +54 -27
- package/docs/components/ui/card.md +5 -4
- package/docs/components/ui/checkbox.md +3 -3
- package/docs/components/ui/combobox.md +35 -1
- package/docs/components/ui/command.md +7 -7
- package/docs/components/ui/context-menu.md +14 -15
- package/docs/components/ui/date-picker-selector.md +31 -31
- package/docs/components/ui/dialog.md +47 -49
- package/docs/components/ui/dropdown-menu.md +34 -37
- package/docs/components/ui/field.md +25 -31
- package/docs/components/ui/file-upload-v2.md +11 -0
- package/docs/components/ui/file-upload.md +105 -108
- package/docs/components/ui/hover-card.md +28 -6
- package/docs/components/ui/icon.md +10 -9
- package/docs/components/ui/input-group.md +9 -9
- package/docs/components/ui/input.md +30 -33
- package/docs/components/ui/kbd.md +10 -9
- package/docs/components/ui/label.md +6 -6
- package/docs/components/ui/pagination.md +3 -3
- package/docs/components/ui/popover.md +1 -0
- package/docs/components/ui/progress.md +3 -3
- package/docs/components/ui/radio-group.md +18 -6
- package/docs/components/ui/scroll-area.md +4 -4
- package/docs/components/ui/select.md +14 -12
- package/docs/components/ui/selectable-card.md +204 -0
- package/docs/components/ui/separator.md +4 -4
- package/docs/components/ui/sheet.md +21 -3
- package/docs/components/ui/slider.md +3 -3
- package/docs/components/ui/switch.md +7 -7
- package/docs/components/ui/table.md +7 -4
- package/docs/components/ui/tabs-underline.md +36 -36
- package/docs/components/ui/tabs.md +6 -4
- package/docs/components/ui/textarea.md +6 -4
- package/docs/components/ui/timeline.md +214 -0
- package/docs/components/ui/toggle.md +1 -1
- package/docs/components/ui/tooltip.md +3 -3
- package/llm.txt +7 -4
- package/package.json +13 -1
- package/dist/button-BnUlAtuD.js +0 -132
- package/dist/button-CFJs0esR.cjs +0 -63
- package/dist/checkbox-3RIZX2HF.cjs +0 -22
- package/dist/combobox-MkeJiTXj.js +0 -637
- package/dist/combobox-jJRxvUsB.cjs +0 -40
- package/dist/input-BCiOr4Fy.js +0 -44
- package/dist/input-Bz5k4w94.cjs +0 -22
- package/dist/separator-CCGaTo09.cjs +0 -7
- package/dist/textarea-BRCnIxdB.js +0 -33
- package/dist/textarea-DkFUS_oS.cjs +0 -14
|
@@ -143,32 +143,32 @@ The main component that renders the complete calendar.
|
|
|
143
143
|
|
|
144
144
|
#### Props
|
|
145
145
|
|
|
146
|
-
| Prop | Type | Default
|
|
147
|
-
| ----------------- | ---------------------------------------------------------------- |
|
|
148
|
-
| `mode` | `"single" \| "multiple" \| "range" \| "default"` | `"default"`
|
|
149
|
-
| `selected` | `Date \| Date[] \| DateRange \| undefined` | `undefined`
|
|
150
|
-
| `onSelect` | `(date) => void` | -
|
|
151
|
-
| `defaultMonth` | `Date` | Current month
|
|
152
|
-
| `numberOfMonths` | `number` | `1`
|
|
153
|
-
| `captionLayout` | `"label" \| "dropdown" \| "dropdown-months" \| "dropdown-years"` | `"label"`
|
|
154
|
-
| `showOutsideDays` | `boolean` | `true`
|
|
155
|
-
| `showWeekNumber` | `boolean` | `false`
|
|
156
|
-
| `disabled` | `Date \| Date[] \| DateRange \| ((date: Date) => boolean)` | -
|
|
157
|
-
| `hidden` | `Date \| Date[] \| DateRange \| ((date: Date) => boolean)` | -
|
|
158
|
-
| `fromDate` | `Date` | -
|
|
159
|
-
| `toDate` | `Date` | -
|
|
160
|
-
| `fromMonth` | `Date` | -
|
|
161
|
-
| `toMonth` | `Date` | -
|
|
162
|
-
| `fromYear` | `number` | -
|
|
163
|
-
| `toYear` | `number` | -
|
|
164
|
-
| `timeZone` | `string` | System
|
|
165
|
-
| `locale` | `Locale` | System
|
|
166
|
-
| `weekStartsOn` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | `0`
|
|
167
|
-
| `buttonVariant` | `ButtonProps["variant"]` | `"
|
|
168
|
-
| `className` | `string` | -
|
|
169
|
-
| `classNames` | `ClassNames` | -
|
|
170
|
-
| `components` | `Components` | -
|
|
171
|
-
| `formatters` | `Formatters` | -
|
|
146
|
+
| Prop | Type | Default | Description |
|
|
147
|
+
| ----------------- | ---------------------------------------------------------------- | ---------------- | ----------------------------------------- |
|
|
148
|
+
| `mode` | `"single" \| "multiple" \| "range" \| "default"` | `"default"` | Date selection mode |
|
|
149
|
+
| `selected` | `Date \| Date[] \| DateRange \| undefined` | `undefined` | Selected date(s) according to mode |
|
|
150
|
+
| `onSelect` | `(date) => void` | - | Callback when selection changes |
|
|
151
|
+
| `defaultMonth` | `Date` | Current month | Initial month to show |
|
|
152
|
+
| `numberOfMonths` | `number` | `1` | Number of months to show simultaneously |
|
|
153
|
+
| `captionLayout` | `"label" \| "dropdown" \| "dropdown-months" \| "dropdown-years"` | `"label"` | Header navigation type |
|
|
154
|
+
| `showOutsideDays` | `boolean` | `true` | Show days from adjacent months |
|
|
155
|
+
| `showWeekNumber` | `boolean` | `false` | Show week numbers |
|
|
156
|
+
| `disabled` | `Date \| Date[] \| DateRange \| ((date: Date) => boolean)` | - | Disabled dates |
|
|
157
|
+
| `hidden` | `Date \| Date[] \| DateRange \| ((date: Date) => boolean)` | - | Completely hidden dates |
|
|
158
|
+
| `fromDate` | `Date` | - | Minimum selectable date |
|
|
159
|
+
| `toDate` | `Date` | - | Maximum selectable date |
|
|
160
|
+
| `fromMonth` | `Date` | - | Minimum navigable month |
|
|
161
|
+
| `toMonth` | `Date` | - | Maximum navigable month |
|
|
162
|
+
| `fromYear` | `number` | - | Minimum navigable year |
|
|
163
|
+
| `toYear` | `number` | - | Maximum navigable year |
|
|
164
|
+
| `timeZone` | `string` | System | Time zone (e.g., `"America/New_York"`) |
|
|
165
|
+
| `locale` | `Locale` | System | Locale object from `date-fns` for i18n |
|
|
166
|
+
| `weekStartsOn` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | `0` | Week start day (0=Sunday, 1=Monday) |
|
|
167
|
+
| `buttonVariant` | `ButtonProps["variant"]` | `"link-neutral"` | Variant for navigation buttons |
|
|
168
|
+
| `className` | `string` | - | Additional CSS classes for container |
|
|
169
|
+
| `classNames` | `ClassNames` | - | Object with classes for internal elements |
|
|
170
|
+
| `components` | `Components` | - | Custom components for override |
|
|
171
|
+
| `formatters` | `Formatters` | - | Custom formatting functions |
|
|
172
172
|
|
|
173
173
|
### CalendarDayButton
|
|
174
174
|
|
|
@@ -268,6 +268,30 @@ Only year dropdown, month with arrows.
|
|
|
268
268
|
<Calendar captionLayout="dropdown-years" />
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
+
## Internationalization (i18n)
|
|
272
|
+
|
|
273
|
+
Pass any `date-fns/locale` object via the `locale` prop to translate month names, weekday names and the dropdown formatter. Use `labels` to translate the ARIA labels for navigation buttons.
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { es } from "date-fns/locale";
|
|
277
|
+
|
|
278
|
+
<Calendar
|
|
279
|
+
mode="single"
|
|
280
|
+
locale={es}
|
|
281
|
+
captionLayout="dropdown"
|
|
282
|
+
labels={{
|
|
283
|
+
labelPrevious: () => "Mes anterior",
|
|
284
|
+
labelNext: () => "Mes siguiente",
|
|
285
|
+
labelMonthDropdown: () => "Seleccionar mes",
|
|
286
|
+
labelYearDropdown: () => "Seleccionar año",
|
|
287
|
+
}}
|
|
288
|
+
selected={date}
|
|
289
|
+
onSelect={setDate}
|
|
290
|
+
/>;
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`date-fns` is a peer dependency of this library — no extra installation needed. Browse available locales at [date-fns.org/docs/I18n](https://date-fns.org/docs/I18n).
|
|
294
|
+
|
|
271
295
|
## Advanced patterns
|
|
272
296
|
|
|
273
297
|
### Disabled dates (multiple ways)
|
|
@@ -962,7 +986,10 @@ const handleSelect = (selectedRange: DateRange | undefined) => {
|
|
|
962
986
|
- **Grid Layout**: Uses CSS Grid internally for calendar layout
|
|
963
987
|
- **Focus Management**: CalendarDayButton uses `useEffect` for automatic focus on day with `focused` modifier
|
|
964
988
|
- **Data Attributes**: Days use `data-selected-single`, `data-range-start`, `data-range-end`, `data-range-middle` for specific styles
|
|
965
|
-
- **Aspect Ratio**:
|
|
989
|
+
- **Aspect Ratio**: Day cells and buttons use `aspect-41/34` (wider than tall) for a compact rectangular shape
|
|
990
|
+
- **Gap between cells**: `gap-0.5` between columns prevents hover ring from touching adjacent cells
|
|
991
|
+
- **Selected day**: Uses `bg-primary-400` (slightly lighter than primary) for the selected single day
|
|
992
|
+
- **Hover state**: Shows a `ring-1 ring-primary-300` outline on hover instead of a background fill
|
|
966
993
|
- **Button Variants**: Navigation uses `buttonVariants()` from Button component for visual consistency
|
|
967
994
|
- **Dropdown with Overlay**: Dropdowns use native select with invisible overlay (`opacity-0`) for accessibility
|
|
968
995
|
- **Responsive**: Multiple months change from `flex-row` to `flex-col` on mobile with `md:flex-row`
|
|
@@ -7,10 +7,10 @@ Versatile container with rounded borders, configurable padding, shadow, and bord
|
|
|
7
7
|
- **6 color variants**: Default, Primary, Muted, Success, Warning, Destructive
|
|
8
8
|
- **2 shadow variants**: Default (with elevation) and None (flat design, default)
|
|
9
9
|
- **2 border variants**: Default (visible) and Transparent (invisible but maintains space)
|
|
10
|
-
- **Modular composition**:
|
|
10
|
+
- **Modular composition**: 7 subcomponents (Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter)
|
|
11
11
|
- **Automatic header grid**: Detects `CardAction` and automatically adjusts layout with `has-data-[slot=card-action]:grid-cols-[1fr_auto]`
|
|
12
12
|
- **Container queries**: CardHeader uses `@container/card-header` for responsive layouts
|
|
13
|
-
- **Flexible spacing**: `gap-
|
|
13
|
+
- **Flexible spacing**: `gap-8` between main sections, auto spacing in header/footer with borders
|
|
14
14
|
- **Optional borders**: `.border-b` and `.border-t` classes add separators with automatic padding
|
|
15
15
|
- **Data slots**: Each subcomponent has `data-slot` for specific CSS targeting
|
|
16
16
|
- **Integration with other components**: Transparent background for Calendar/other nested components
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
CardAction,
|
|
27
27
|
CardContent,
|
|
28
28
|
CardFooter,
|
|
29
|
+
cardVariants,
|
|
29
30
|
} from "@adamosuiteservices/ui/card";
|
|
30
31
|
```
|
|
31
32
|
|
|
@@ -143,7 +144,7 @@ Main card title.
|
|
|
143
144
|
| `className` | `string` | Additional CSS classes |
|
|
144
145
|
| `children` | `ReactNode` | Title text |
|
|
145
146
|
|
|
146
|
-
**Default styles**: `
|
|
147
|
+
**Default styles**: `text-sm font-bold text-foreground`
|
|
147
148
|
|
|
148
149
|
### CardDescription
|
|
149
150
|
|
|
@@ -156,7 +157,7 @@ Card description or subtitle.
|
|
|
156
157
|
| `className` | `string` | Additional CSS classes |
|
|
157
158
|
| `children` | `ReactNode` | Description text |
|
|
158
159
|
|
|
159
|
-
**Default styles**: `text-
|
|
160
|
+
**Default styles**: `text-foreground text-sm`
|
|
160
161
|
|
|
161
162
|
### CardAction
|
|
162
163
|
|
|
@@ -72,7 +72,7 @@ const someChecked = items.some(Boolean) && !allChecked;
|
|
|
72
72
|
/>;
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
**Visual**: Shows a
|
|
75
|
+
**Visual**: Shows a `remove` icon (Material Symbols) instead of check.
|
|
76
76
|
|
|
77
77
|
### 4. Disabled
|
|
78
78
|
|
|
@@ -81,7 +81,7 @@ const someChecked = items.some(Boolean) && !allChecked;
|
|
|
81
81
|
<Checkbox disabled defaultChecked />
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
**Styles**: `opacity-
|
|
84
|
+
**Styles**: `bg-disabled opacity-100` + `cursor-not-allowed`
|
|
85
85
|
|
|
86
86
|
### 5. Invalid (error state)
|
|
87
87
|
|
|
@@ -102,7 +102,7 @@ const someChecked = items.some(Boolean) && !allChecked;
|
|
|
102
102
|
</div>
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
**Styles**: Red border (`border-destructive`) + red ring (`ring-destructive/
|
|
105
|
+
**Styles**: Red border (`border-destructive`) + red ring on focus (`ring-4 ring-destructive/10`)
|
|
106
106
|
|
|
107
107
|
## Fieldset disabled
|
|
108
108
|
|
|
@@ -15,6 +15,11 @@ import { Combobox } from "@adamosuiteservices/ui/combobox";
|
|
|
15
15
|
options={[
|
|
16
16
|
{ value: "option1", label: "Option 1" },
|
|
17
17
|
{ value: "option2", label: "Option 2", disabled: true },
|
|
18
|
+
{
|
|
19
|
+
value: "option3",
|
|
20
|
+
label: "Option 3",
|
|
21
|
+
supportiveText: "Additional context",
|
|
22
|
+
},
|
|
18
23
|
]}
|
|
19
24
|
value={selectedValue}
|
|
20
25
|
onValueChange={setSelectedValue}
|
|
@@ -27,7 +32,7 @@ import { Combobox } from "@adamosuiteservices/ui/combobox";
|
|
|
27
32
|
|
|
28
33
|
| Prop | Type | Default | Description |
|
|
29
34
|
| ----------------------- | ------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
-
| `options` | `ComboboxOption[]` | **required** | Array of options `{ value, label, disabled? }`
|
|
35
|
+
| `options` | `ComboboxOption[]` | **required** | Array of options `{ value, label, disabled?, supportiveText? }` |
|
|
31
36
|
| `value` | `string \| string[]` | - | Controlled value (string for single, array for multiple) |
|
|
32
37
|
| `onValueChange` | `(value: string \| string[]) => void` | - | Callback when selection changes |
|
|
33
38
|
| `searchable` | `boolean` | `false` | Enables search input |
|
|
@@ -422,6 +427,34 @@ const options = [
|
|
|
422
427
|
/>;
|
|
423
428
|
```
|
|
424
429
|
|
|
430
|
+
### With supportive text
|
|
431
|
+
|
|
432
|
+
Each option can display a secondary line of supporting text below the label.
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
<Combobox
|
|
436
|
+
searchable
|
|
437
|
+
options={[
|
|
438
|
+
{
|
|
439
|
+
value: "ne",
|
|
440
|
+
label: "Next.js",
|
|
441
|
+
supportiveText: "React framework with SSR and SSG support",
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
value: "sv",
|
|
445
|
+
label: "SvelteKit",
|
|
446
|
+
supportiveText: "Full-stack framework built on Svelte",
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
value: "nu",
|
|
450
|
+
label: "Nuxt.js",
|
|
451
|
+
supportiveText: "Vue framework for server-side rendering",
|
|
452
|
+
},
|
|
453
|
+
]}
|
|
454
|
+
labels={{ placeholder: "Select framework..." }}
|
|
455
|
+
/>
|
|
456
|
+
```
|
|
457
|
+
|
|
425
458
|
### Invalid state
|
|
426
459
|
|
|
427
460
|
```tsx
|
|
@@ -740,6 +773,7 @@ The `renders` prop allows complete UI customization using the render prop patter
|
|
|
740
773
|
## Implementation notes
|
|
741
774
|
|
|
742
775
|
- **Composition**: Uses Popover + Command + Button + Checkbox internally
|
|
776
|
+
- **`ComboboxOption`**: Supports `value`, `label`, `disabled?` and `supportiveText?`. When `supportiveText` is provided, the item uses a two-row layout: label row on top and supporting text below in `text-muted-foreground`.
|
|
743
777
|
- **Search**:
|
|
744
778
|
- Uses custom filter function that searches by label and/or value
|
|
745
779
|
- Case-insensitive by default
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
</Command>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
**Components**:
|
|
43
|
+
**Components**: 9 (Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut)
|
|
44
44
|
|
|
45
45
|
## Main props
|
|
46
46
|
|
|
@@ -390,7 +390,7 @@ function CustomFilter() {
|
|
|
390
390
|
|
|
391
391
|
### CommandItem states
|
|
392
392
|
|
|
393
|
-
- **Selected**: `data-[selected=true]` → `bg-
|
|
393
|
+
- **Selected**: `data-[selected=true]` → `bg-muted`, `text-foreground`
|
|
394
394
|
- **Disabled**: `data-[disabled=true]` → `opacity-50`, `pointer-events-none`
|
|
395
395
|
|
|
396
396
|
### Empty state
|
|
@@ -441,12 +441,12 @@ function CustomFilter() {
|
|
|
441
441
|
|
|
442
442
|
### CommandItem
|
|
443
443
|
|
|
444
|
-
- **
|
|
445
|
-
- **Padding**: `px-
|
|
446
|
-
- **Border**: `border-b` between items
|
|
444
|
+
- **Min-height**: `min-h-11` (44px)
|
|
445
|
+
- **Padding**: `px-4` horizontal, no vertical padding
|
|
446
|
+
- **Border**: `border-b border-divider` between items
|
|
447
447
|
- **Rounded corners**: Last item has `rounded-b-[calc(var(--radius)-1px)]` and no bottom border
|
|
448
|
-
- **Gap**: `gap-
|
|
449
|
-
- **
|
|
448
|
+
- **Gap**: `gap-3` between content elements
|
|
449
|
+
- **SVG icons**: auto `size-4` and `text-muted-foreground` if no `size-*`/`text-*` class is set
|
|
450
450
|
|
|
451
451
|
### CommandGroup
|
|
452
452
|
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
|
|
96
96
|
**Variants**:
|
|
97
97
|
|
|
98
|
-
- `default`: `focus:bg-
|
|
98
|
+
- `default`: `focus:bg-muted`, `focus:text-foreground`
|
|
99
99
|
- `destructive`: `text-destructive`, `focus:bg-destructive/10`, `focus:text-destructive`
|
|
100
100
|
|
|
101
101
|
### ContextMenuCheckboxItem
|
|
@@ -107,7 +107,7 @@ import {
|
|
|
107
107
|
| `disabled` | `boolean` | Disables the item |
|
|
108
108
|
| `className` | `string` | Additional CSS classes |
|
|
109
109
|
|
|
110
|
-
**Indicator**: Check icon (Material Symbol "check") automatic when `checked={true}`, positioned with `pl-8`
|
|
110
|
+
**Indicator**: Check icon (Material Symbol "check") automatic when `checked={true}`, `text-xl text-success`, positioned with `pl-8`
|
|
111
111
|
|
|
112
112
|
### ContextMenuRadioGroup
|
|
113
113
|
|
|
@@ -150,7 +150,7 @@ import {
|
|
|
150
150
|
| `inset` | `boolean` | Left padding (`pl-8`) |
|
|
151
151
|
| `className` | `string` | Additional CSS classes |
|
|
152
152
|
|
|
153
|
-
**Styles**: `text-foreground`, `
|
|
153
|
+
**Styles**: `text-xs`, `text-muted-foreground`, `px-2 py-1.5`
|
|
154
154
|
|
|
155
155
|
### ContextMenuShortcut
|
|
156
156
|
|
|
@@ -456,23 +456,22 @@ function App() {
|
|
|
456
456
|
|
|
457
457
|
### Items (MenuItem, SubTrigger)
|
|
458
458
|
|
|
459
|
-
- **Height**: `
|
|
460
|
-
- **Padding**: `
|
|
459
|
+
- **Height**: `h-11` (44px fixed)
|
|
460
|
+
- **Padding**: `pl-4 pr-10` (left/right for icon alignment)
|
|
461
461
|
- **Rounded corners**: `first:rounded-t-sm`, `last:rounded-b-sm` (only first/last items)
|
|
462
462
|
- **Icon constraints**: None - icons use their natural sizes
|
|
463
|
-
- **Gap**: `gap-
|
|
463
|
+
- **Gap**: `gap-3` between content elements
|
|
464
464
|
|
|
465
465
|
### CheckboxItem and RadioItem
|
|
466
466
|
|
|
467
|
-
- **Height**: `
|
|
467
|
+
- **Height**: `h-11` (44px fixed)
|
|
468
468
|
- **Padding**: `pl-8` (left), `pr-10` (right) - space for indicators
|
|
469
469
|
- **Rounded corners**: `first:rounded-t-sm`, `last:rounded-b-sm`
|
|
470
470
|
|
|
471
471
|
### Label
|
|
472
472
|
|
|
473
|
-
- **
|
|
474
|
-
- **
|
|
475
|
-
- **Display**: `flex items-center` for vertical centering
|
|
473
|
+
- **Padding**: `px-2 py-1.5`
|
|
474
|
+
- **Text**: `text-xs text-muted-foreground`
|
|
476
475
|
|
|
477
476
|
### Content
|
|
478
477
|
|
|
@@ -490,13 +489,13 @@ function App() {
|
|
|
490
489
|
|
|
491
490
|
### ContextMenuItem states
|
|
492
491
|
|
|
493
|
-
- **Focus**: `data-[highlighted]` → `bg-
|
|
492
|
+
- **Focus**: `data-[highlighted]` → `bg-muted`, `text-foreground`
|
|
494
493
|
- **Disabled**: `data-[disabled=true]` → `opacity-50`, `pointer-events-none`
|
|
495
494
|
- **Destructive**: `data-[variant=destructive]` → `text-destructive`
|
|
496
495
|
|
|
497
496
|
### ContextMenuSubTrigger states
|
|
498
497
|
|
|
499
|
-
- **Open**: `data-[state=open]` → `bg-
|
|
498
|
+
- **Open**: `data-[state=open]` → `bg-muted`, `text-foreground`
|
|
500
499
|
|
|
501
500
|
### Content animations
|
|
502
501
|
|
|
@@ -569,6 +568,6 @@ By default, the menu appears at cursor position. Can be customized:
|
|
|
569
568
|
|
|
570
569
|
## References
|
|
571
570
|
|
|
572
|
-
- **Radix UI Context Menu**: https://www.radix-ui.com/primitives/docs/components/context-menu
|
|
573
|
-
- **shadcn/ui Context Menu**: https://ui.shadcn.com/docs/components/context-menu
|
|
574
|
-
- **ARIA Menu Pattern**: https://www.w3.org/WAI/ARIA/apg/patterns/menu
|
|
571
|
+
- **Radix UI Context Menu**: <https://www.radix-ui.com/primitives/docs/components/context-menu>
|
|
572
|
+
- **shadcn/ui Context Menu**: <https://ui.shadcn.com/docs/components/context-menu>
|
|
573
|
+
- **ARIA Menu Pattern**: <https://www.w3.org/WAI/ARIA/apg/patterns/menu/>
|
|
@@ -33,13 +33,13 @@ The component manages two Popovers simultaneously:
|
|
|
33
33
|
**Implemented solution:**
|
|
34
34
|
|
|
35
35
|
```tsx
|
|
36
|
-
// 1.
|
|
36
|
+
// 1. The Combobox receives a ref pointing to its trigger button
|
|
37
37
|
<Combobox
|
|
38
38
|
ref={(node) => { comboboxRef.current = node; }}
|
|
39
39
|
// ...
|
|
40
40
|
/>
|
|
41
41
|
|
|
42
|
-
// 2.
|
|
42
|
+
// 2. The calendar Popover uses virtualRef to position itself
|
|
43
43
|
<Popover open={calendarOpen}>
|
|
44
44
|
<PopoverAnchor virtualRef={comboboxRef} />
|
|
45
45
|
<PopoverContent>
|
|
@@ -94,15 +94,15 @@ function MyComponent() {
|
|
|
94
94
|
|
|
95
95
|
## Props
|
|
96
96
|
|
|
97
|
-
| Prop | Tipo
|
|
98
|
-
| ------------------- |
|
|
99
|
-
| `dateRange` | `DateRange`
|
|
100
|
-
| `onDateRangeChange` | `(dateRange: DateRange) => void`
|
|
101
|
-
| `labels` | `DatePickerSelectorLabels`
|
|
102
|
-
| `combobox` | `ComboboxProps
|
|
103
|
-
| `calendar` | `CalendarProps
|
|
104
|
-
| `aria-invalid` | `"true" \| "false" \| boolean`
|
|
105
|
-
| `disabled` | `boolean`
|
|
97
|
+
| Prop | Tipo | Default | Description |
|
|
98
|
+
| ------------------- | ----------------------------------------------------------- | ------- | ------------------------------------------- |
|
|
99
|
+
| `dateRange` | `DateRange` | - | **Required**. Current date range |
|
|
100
|
+
| `onDateRangeChange` | `(dateRange: DateRange) => void` | - | **Required**. Callback when range changes |
|
|
101
|
+
| `labels` | `DatePickerSelectorLabels` | - | Customizable labels for all UI text |
|
|
102
|
+
| `combobox` | `Omit<ComboboxProps, "options">` | - | Additional props for the Combobox component |
|
|
103
|
+
| `calendar` | `Omit<CalendarProps, "mode" \| "selected" \| "onSelected">` | - | Additional props for the Calendar component |
|
|
104
|
+
| `aria-invalid` | `"true" \| "false" \| boolean` | - | Indicates invalid state (red border) |
|
|
105
|
+
| `disabled` | `boolean` | `false` | Disables the date selector |
|
|
106
106
|
|
|
107
107
|
### DateRange Type
|
|
108
108
|
|
|
@@ -357,23 +357,23 @@ The date selector inside a `<fieldset disabled>` automatically inherits the disa
|
|
|
357
357
|
|
|
358
358
|
### State synchronization
|
|
359
359
|
|
|
360
|
-
|
|
360
|
+
The component automatically synchronizes its internal state with the `dateRange` prop via a `useEffect`. This means that:
|
|
361
361
|
|
|
362
|
-
- ✅
|
|
363
|
-
- ✅
|
|
364
|
-
- ✅
|
|
365
|
-
- ✅
|
|
362
|
+
- ✅ External changes to `dateRange` update the combobox automatically
|
|
363
|
+
- ✅ Resetting the range externally (e.g., a Reset button) updates the UI correctly
|
|
364
|
+
- ✅ Forms that clear fields work without additional configuration
|
|
365
|
+
- ✅ Does not require manually controlling the combobox state
|
|
366
366
|
|
|
367
|
-
**
|
|
367
|
+
**Synchronization example:**
|
|
368
368
|
|
|
369
369
|
```tsx
|
|
370
|
-
//
|
|
370
|
+
// Reset from external code
|
|
371
371
|
setDateRange({ from: undefined, to: undefined });
|
|
372
|
-
// →
|
|
372
|
+
// → The combobox will automatically show the placeholder
|
|
373
373
|
|
|
374
|
-
//
|
|
374
|
+
// Set a preset range
|
|
375
375
|
setDateRange({ from: subDays(new Date(), 7), to: new Date() });
|
|
376
|
-
// →
|
|
376
|
+
// → The combobox will detect and display "Last 7 days"
|
|
377
377
|
```
|
|
378
378
|
|
|
379
379
|
### Preset ranges
|
|
@@ -415,11 +415,11 @@ This ensures the user never ends up with "Custom" selected without having comple
|
|
|
415
415
|
|
|
416
416
|
## Use cases
|
|
417
417
|
|
|
418
|
-
**
|
|
419
|
-
**Dashboards**:
|
|
420
|
-
**Analytics**:
|
|
421
|
-
**
|
|
422
|
-
**Logs**:
|
|
418
|
+
**Report filters**: Select date range to generate reports
|
|
419
|
+
**Dashboards**: Filter data by time periods
|
|
420
|
+
**Analytics**: Compare metrics across different ranges
|
|
421
|
+
**Search**: Filter results by date range
|
|
422
|
+
**Logs**: View records in specific periods
|
|
423
423
|
|
|
424
424
|
## Dependencies
|
|
425
425
|
|
|
@@ -452,7 +452,7 @@ This component uses internally:
|
|
|
452
452
|
### State management
|
|
453
453
|
|
|
454
454
|
```tsx
|
|
455
|
-
// ✅
|
|
455
|
+
// ✅ Correct - Controlled state
|
|
456
456
|
const [dateRange, setDateRange] = useState<DateRange>({
|
|
457
457
|
from: undefined,
|
|
458
458
|
to: undefined,
|
|
@@ -460,7 +460,7 @@ const [dateRange, setDateRange] = useState<DateRange>({
|
|
|
460
460
|
|
|
461
461
|
<DatePickerSelector dateRange={dateRange} onDateRangeChange={setDateRange} />;
|
|
462
462
|
|
|
463
|
-
// ❌
|
|
463
|
+
// ❌ Incorrect - Uninitialized state
|
|
464
464
|
const [dateRange, setDateRange] = useState();
|
|
465
465
|
```
|
|
466
466
|
|
|
@@ -488,19 +488,19 @@ const handleChange = (range: DateRange) => {
|
|
|
488
488
|
```tsx
|
|
489
489
|
import { format } from "date-fns";
|
|
490
490
|
|
|
491
|
-
// ✅
|
|
491
|
+
// ✅ Correct - Format with date-fns
|
|
492
492
|
const displayDate = dateRange.from
|
|
493
493
|
? format(dateRange.from, "PP")
|
|
494
494
|
: "Not selected";
|
|
495
495
|
|
|
496
|
-
// ❌
|
|
496
|
+
// ❌ Avoid - toString() is not user-friendly
|
|
497
497
|
const displayDate = dateRange.from?.toString();
|
|
498
498
|
```
|
|
499
499
|
|
|
500
500
|
### Internationalization
|
|
501
501
|
|
|
502
502
|
```tsx
|
|
503
|
-
// ✅
|
|
503
|
+
// ✅ Correct - Provide all labels
|
|
504
504
|
<DatePickerSelector
|
|
505
505
|
labels={{
|
|
506
506
|
last7Days: t("dateRange.last7Days"),
|