azamat-ui-kit-cli 0.2.2 → 0.3.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.
Files changed (103) hide show
  1. package/README.md +11 -0
  2. package/dist/index.cjs +452 -0
  3. package/package.json +2 -2
  4. package/vendor/src/components/actions/action-menu.tsx +21 -18
  5. package/vendor/src/components/calendar/calendar.tsx +153 -102
  6. package/vendor/src/components/calendar/date-picker.tsx +24 -14
  7. package/vendor/src/components/calendar/date-range-picker.tsx +137 -58
  8. package/vendor/src/components/charts/charts.tsx +32 -21
  9. package/vendor/src/components/command/command-palette.tsx +68 -57
  10. package/vendor/src/components/data-table/data-table-bulk-actions.tsx +23 -20
  11. package/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +21 -10
  12. package/vendor/src/components/data-table/data-table-pagination.tsx +6 -6
  13. package/vendor/src/components/data-table/data-table-toolbar.tsx +72 -44
  14. package/vendor/src/components/data-table/data-table.tsx +15 -11
  15. package/vendor/src/components/data-table/table-export-menu.tsx +1 -1
  16. package/vendor/src/components/data-table/table-import-button.tsx +1 -1
  17. package/vendor/src/components/display/data-state.tsx +20 -8
  18. package/vendor/src/components/display/index.ts +19 -15
  19. package/vendor/src/components/display/metric-card.tsx +35 -0
  20. package/vendor/src/components/display/progress-circle.tsx +24 -0
  21. package/vendor/src/components/display/smart-card.tsx +49 -27
  22. package/vendor/src/components/display/status-dot.tsx +45 -0
  23. package/vendor/src/components/display/user-card.tsx +30 -0
  24. package/vendor/src/components/feedback/alert.tsx +21 -11
  25. package/vendor/src/components/feedback/empty-state.tsx +2 -2
  26. package/vendor/src/components/feedback/loading-state.tsx +2 -2
  27. package/vendor/src/components/feedback/page-state.tsx +19 -15
  28. package/vendor/src/components/feedback/status-badge.tsx +43 -43
  29. package/vendor/src/components/form/form-app-input.tsx +147 -0
  30. package/vendor/src/components/form/form-date-input.tsx +16 -19
  31. package/vendor/src/components/form/form-field-shell.tsx +11 -8
  32. package/vendor/src/components/form/form-field-utils.ts +76 -0
  33. package/vendor/src/components/form/form-input.tsx +423 -44
  34. package/vendor/src/components/form/form-number-input.tsx +16 -15
  35. package/vendor/src/components/form/form-phone-input.tsx +15 -9
  36. package/vendor/src/components/form/form-search-input.tsx +16 -19
  37. package/vendor/src/components/form/form-select.tsx +4 -3
  38. package/vendor/src/components/form/public.ts +16 -14
  39. package/vendor/src/components/form/smart-form-shell.tsx +13 -12
  40. package/vendor/src/components/inputs/app-input.tsx +27 -0
  41. package/vendor/src/components/inputs/async-select.tsx +113 -84
  42. package/vendor/src/components/inputs/clearable-input.tsx +81 -61
  43. package/vendor/src/components/inputs/date-input.tsx +21 -17
  44. package/vendor/src/components/inputs/date-range-input.tsx +10 -10
  45. package/vendor/src/components/inputs/index.ts +1 -0
  46. package/vendor/src/components/inputs/input-decorator.tsx +101 -57
  47. package/vendor/src/components/inputs/masked-input.tsx +20 -20
  48. package/vendor/src/components/inputs/money-input.tsx +2 -2
  49. package/vendor/src/components/inputs/number-input.tsx +29 -19
  50. package/vendor/src/components/inputs/password-input.tsx +82 -45
  51. package/vendor/src/components/inputs/phone-input.tsx +24 -2
  52. package/vendor/src/components/inputs/quantity-input.tsx +2 -2
  53. package/vendor/src/components/inputs/search-input.tsx +54 -3
  54. package/vendor/src/components/inputs/simple-select.tsx +110 -22
  55. package/vendor/src/components/layout/app-shell.tsx +2 -2
  56. package/vendor/src/components/layout/index.ts +5 -4
  57. package/vendor/src/components/layout/page-header.tsx +79 -35
  58. package/vendor/src/components/layout/public.ts +12 -10
  59. package/vendor/src/components/layout/section-header.tsx +56 -0
  60. package/vendor/src/components/layout/stack.tsx +106 -0
  61. package/vendor/src/components/layout/stat-card.tsx +66 -29
  62. package/vendor/src/components/navigation/index.ts +1 -0
  63. package/vendor/src/components/navigation/nav-tabs.tsx +60 -0
  64. package/vendor/src/components/navigation/page-tabs.tsx +41 -26
  65. package/vendor/src/components/navigation/pagination.tsx +14 -10
  66. package/vendor/src/components/overlay/alert-dialog.tsx +65 -0
  67. package/vendor/src/components/overlay/drawer.tsx +71 -0
  68. package/vendor/src/components/overlay/index.ts +4 -2
  69. package/vendor/src/components/patterns/data-view.tsx +13 -8
  70. package/vendor/src/components/ui/badge.tsx +96 -52
  71. package/vendor/src/components/ui/button.tsx +99 -61
  72. package/vendor/src/components/ui/card.tsx +84 -25
  73. package/vendor/src/components/ui/checkbox.tsx +68 -68
  74. package/vendor/src/components/ui/command.tsx +32 -32
  75. package/vendor/src/components/ui/dialog.tsx +135 -138
  76. package/vendor/src/components/ui/dropdown-menu.tsx +21 -21
  77. package/vendor/src/components/ui/hover-card.tsx +49 -0
  78. package/vendor/src/components/ui/input-primitive.tsx +24 -0
  79. package/vendor/src/components/ui/input.tsx +191 -20
  80. package/vendor/src/components/ui/kbd.tsx +33 -0
  81. package/vendor/src/components/ui/popover.tsx +11 -11
  82. package/vendor/src/components/ui/radio-group.tsx +102 -0
  83. package/vendor/src/components/ui/right-click-menu.tsx +60 -0
  84. package/vendor/src/components/ui/scroll-box.tsx +27 -0
  85. package/vendor/src/components/ui/segmented-control.tsx +21 -17
  86. package/vendor/src/components/ui/select.tsx +187 -189
  87. package/vendor/src/components/ui/skeleton.tsx +2 -2
  88. package/vendor/src/components/ui/switch.tsx +60 -60
  89. package/vendor/src/components/ui/table.tsx +114 -114
  90. package/vendor/src/components/ui/tabs.tsx +2 -2
  91. package/vendor/src/components/ui/textarea.tsx +1 -1
  92. package/vendor/src/components/upload/file-dropzone.tsx +38 -0
  93. package/vendor/src/components/upload/file-upload.tsx +4 -4
  94. package/vendor/src/components/upload/image-upload.tsx +22 -19
  95. package/vendor/src/components/upload/index.ts +2 -0
  96. package/vendor/src/families/catalog.ts +1 -0
  97. package/vendor/src/families/docs-groups.ts +10 -1
  98. package/vendor/src/families/member-metadata.ts +24 -0
  99. package/vendor/src/families/member-snippets.ts +41 -2
  100. package/vendor/src/families/migration-map.ts +3 -0
  101. package/vendor/src/index.ts +23 -18
  102. package/vendor/templates/styles/globals.css +253 -0
  103. package/dist/index.js +0 -432
@@ -9,9 +9,11 @@ import { parseDateKey } from "./date-utils"
9
9
 
10
10
  export type DateRangePickerValue = CalendarDateRange
11
11
 
12
- export type DateRangePickerLabels = CalendarProps["labels"] & {
13
- placeholder?: string
14
- }
12
+ export type DateRangePickerLabels = CalendarProps["labels"] & {
13
+ placeholder?: string
14
+ apply?: React.ReactNode
15
+ clear?: React.ReactNode
16
+ }
15
17
 
16
18
  export type DateRangePickerProps = Omit<
17
19
  CalendarProps,
@@ -21,11 +23,13 @@ export type DateRangePickerProps = Omit<
21
23
  onValueChange?: (value: DateRangePickerValue) => void
22
24
  labels?: DateRangePickerLabels
23
25
  placeholder?: string
24
- disabled?: boolean
25
- formatValue?: (value: string) => React.ReactNode
26
- triggerClassName?: string
27
- contentClassName?: string
28
- }
26
+ disabled?: boolean
27
+ formatValue?: (value: string) => React.ReactNode
28
+ closeOnSelect?: boolean
29
+ showFooter?: boolean
30
+ triggerClassName?: string
31
+ contentClassName?: string
32
+ }
29
33
 
30
34
  function defaultFormatValue(value: string) {
31
35
  const date = parseDateKey(value)
@@ -33,63 +37,138 @@ function defaultFormatValue(value: string) {
33
37
  return new Intl.DateTimeFormat("en-US", { dateStyle: "medium" }).format(date)
34
38
  }
35
39
 
36
- function DateRangePicker({
37
- className,
38
- value,
40
+ function DateRangePicker({
41
+ className,
42
+ value,
39
43
  onValueChange,
40
44
  labels,
41
- placeholder,
42
- disabled = false,
43
- formatValue = defaultFormatValue,
44
- triggerClassName,
45
- contentClassName,
46
- ...calendarProps
47
- }: DateRangePickerProps) {
48
- const [open, setOpen] = React.useState(false)
49
- const from = value?.from ?? ""
50
- const to = value?.to ?? ""
51
- const hasValue = Boolean(from || to)
52
-
53
- const label = from && to
54
- ? `${formatValue(from)} - ${formatValue(to)}`
45
+ placeholder,
46
+ disabled = false,
47
+ formatValue = defaultFormatValue,
48
+ closeOnSelect = true,
49
+ showFooter = false,
50
+ triggerClassName,
51
+ contentClassName,
52
+ numberOfMonths = 2,
53
+ pagedNavigation = true,
54
+ ...calendarProps
55
+ }: DateRangePickerProps) {
56
+ const [open, setOpen] = React.useState(false)
57
+ const [draftValue, setDraftValue] = React.useState<DateRangePickerValue>(value ?? {})
58
+ const from = value?.from ?? ""
59
+ const to = value?.to ?? ""
60
+ const hasValue = Boolean(from || to)
61
+ const activeValue = showFooter ? draftValue : value
62
+ const activeFrom = activeValue?.from ?? ""
63
+ const activeTo = activeValue?.to ?? ""
64
+ const hasDraftValue = Boolean(activeFrom || activeTo)
65
+
66
+ const label = from && to
67
+ ? `${formatValue(from)} - ${formatValue(to)}`
55
68
  : from
56
- ? `${formatValue(from)} - ...`
57
- : placeholder ?? labels?.placeholder ?? "Select date range"
58
-
59
- const handleRangeChange = (nextValue: DateRangePickerValue) => {
60
- onValueChange?.(nextValue)
61
- if (nextValue.from && nextValue.to) {
62
- setOpen(false)
63
- }
64
- }
65
-
66
- return (
67
- <div data-slot="date-range-picker" className={cn("w-full", className)}>
69
+ ? `${formatValue(from)} - ...`
70
+ : placeholder ?? labels?.placeholder ?? "Select date range"
71
+
72
+ const draftLabel = activeFrom && activeTo
73
+ ? `${formatValue(activeFrom)} - ${formatValue(activeTo)}`
74
+ : activeFrom
75
+ ? `${formatValue(activeFrom)} - ...`
76
+ : labels?.placeholder ?? "Select date range"
77
+
78
+ React.useEffect(() => {
79
+ if (open && showFooter) {
80
+ setDraftValue(value ?? {})
81
+ }
82
+ }, [open, showFooter, value])
83
+
84
+ const handleRangeChange = (nextValue: DateRangePickerValue) => {
85
+ if (showFooter) {
86
+ setDraftValue(nextValue)
87
+ return
88
+ }
89
+
90
+ onValueChange?.(nextValue)
91
+ if (closeOnSelect && nextValue.from && nextValue.to) {
92
+ setOpen(false)
93
+ }
94
+ }
95
+
96
+ const applyDraftValue = () => {
97
+ onValueChange?.(draftValue)
98
+ setOpen(false)
99
+ }
100
+
101
+ const clearDraftValue = () => {
102
+ const nextValue = {}
103
+
104
+ if (showFooter) {
105
+ setDraftValue(nextValue)
106
+ return
107
+ }
108
+
109
+ onValueChange?.(nextValue)
110
+ }
111
+
112
+ return (
113
+ <div data-slot="date-range-picker" className={cn("w-full", className)}>
68
114
  <Popover open={open} onOpenChange={setOpen}>
69
- <PopoverTrigger
70
- render={
71
- <Button
72
- type="button"
73
- variant="outline"
74
- disabled={disabled}
75
- className={cn("w-full justify-start text-left font-normal", !hasValue && "text-muted-foreground", triggerClassName)}
76
- />
77
- }
78
- >
115
+ <PopoverTrigger
116
+ render={
117
+ <Button
118
+ type="button"
119
+ variant="outline"
120
+ disabled={disabled}
121
+ className={cn(
122
+ "min-h-11 w-full justify-start rounded-[min(var(--radius-xl),16px)] border-border/80 bg-background/96 text-left font-normal shadow-[0_1px_0_rgba(255,255,255,0.06)]",
123
+ !hasValue && "text-muted-foreground",
124
+ triggerClassName
125
+ )}
126
+ />
127
+ }
128
+ >
79
129
  <CalendarIcon data-icon="inline-start" />
80
130
  <span className="min-w-0 flex-1 truncate">{label}</span>
81
131
  </PopoverTrigger>
82
- <PopoverContent align="start" className={cn("w-auto p-0", contentClassName)}>
83
- <Calendar
84
- mode="range"
85
- range={value}
86
- onRangeChange={handleRangeChange}
87
- labels={labels}
88
- {...calendarProps}
89
- />
90
- </PopoverContent>
91
- </Popover>
92
- </div>
132
+ <PopoverContent
133
+ align="start"
134
+ className={cn(
135
+ "w-auto rounded-[var(--radius-2xl)] border-border/80 bg-popover/98 p-0 shadow-[0_24px_80px_rgba(15,23,42,0.18)] backdrop-blur",
136
+ contentClassName
137
+ )}
138
+ >
139
+ <Calendar
140
+ mode="range"
141
+ range={activeValue}
142
+ onRangeChange={handleRangeChange}
143
+ labels={labels}
144
+ numberOfMonths={numberOfMonths}
145
+ pagedNavigation={pagedNavigation}
146
+ {...calendarProps}
147
+ />
148
+ {showFooter && (
149
+ <div className="flex flex-wrap items-center justify-between gap-3 border-t border-border/70 bg-muted/18 px-4 py-3">
150
+ <div className="min-w-0 text-sm text-muted-foreground">
151
+ <span className="block truncate">{draftLabel}</span>
152
+ </div>
153
+ <div className="flex items-center gap-2">
154
+ <Button type="button" variant="ghost" size="sm" className="rounded-full" onClick={clearDraftValue}>
155
+ {labels?.clear ?? "Clear"}
156
+ </Button>
157
+ <Button
158
+ type="button"
159
+ size="sm"
160
+ className="rounded-full"
161
+ disabled={!hasDraftValue}
162
+ onClick={applyDraftValue}
163
+ >
164
+ {labels?.apply ?? "Apply"}
165
+ </Button>
166
+ </div>
167
+ </div>
168
+ )}
169
+ </PopoverContent>
170
+ </Popover>
171
+ </div>
93
172
  )
94
173
  }
95
174
 
@@ -85,12 +85,16 @@ export type ChartFrameProps = React.ComponentProps<typeof Card> & {
85
85
  action?: React.ReactNode
86
86
  }
87
87
 
88
- function ChartFrame({ title, description, action, className, children, ...props }: ChartFrameProps) {
89
- return (
90
- <Card data-slot="chart-frame" className={className} {...props}>
91
- {(title || description || action) && (
92
- <CardHeader className="flex flex-row items-start justify-between gap-3">
93
- <div className="grid gap-1">
88
+ function ChartFrame({ title, description, action, className, children, ...props }: ChartFrameProps) {
89
+ return (
90
+ <Card
91
+ data-slot="chart-frame"
92
+ className={cn("border-border/75 bg-card/96 shadow-sm ring-1 ring-foreground/4", className)}
93
+ {...props}
94
+ >
95
+ {(title || description || action) && (
96
+ <CardHeader className="flex flex-row items-start justify-between gap-3">
97
+ <div className="grid gap-1">
94
98
  {title && <CardTitle>{title}</CardTitle>}
95
99
  {description && <CardDescription>{description}</CardDescription>}
96
100
  </div>
@@ -115,20 +119,20 @@ function BarChart({ data, size = "md", max, showLabels = true, showValues = true
115
119
  const resolvedMax = max ?? safeMax(data.map((item) => item.value))
116
120
  const height = chartHeightBySize[size]
117
121
 
118
- return (
119
- <div data-slot="bar-chart" className={cn("grid gap-3", className)} {...props}>
120
- <div className="flex items-end gap-2" style={{ height }}>
122
+ return (
123
+ <div data-slot="bar-chart" className={cn("grid gap-3", className)} {...props}>
124
+ <div className="flex items-end gap-2" style={{ height }}>
121
125
  {data.map((item, index) => {
122
126
  const ratio = normalizeValue(item.value, resolvedMax)
123
127
  return (
124
128
  <div key={index} className="flex min-w-0 flex-1 flex-col items-center gap-2">
125
129
  {showValues && <div className="text-xs text-muted-foreground">{item.value}</div>}
126
- <div className="flex w-full flex-1 items-end rounded-md bg-muted/50">
127
- <div
128
- className={cn("w-full rounded-md bg-primary transition-all", barClassName)}
129
- style={{ height: `${Math.max(ratio * 100, item.value > 0 ? 3 : 0)}%`, background: item.color }}
130
- />
131
- </div>
130
+ <div className="flex w-full flex-1 items-end rounded-[min(var(--radius-xl),16px)] border border-border/60 bg-muted/38 p-1">
131
+ <div
132
+ className={cn("w-full rounded-[min(var(--radius-lg),12px)] bg-primary transition-all", barClassName)}
133
+ style={{ height: `${Math.max(ratio * 100, item.value > 0 ? 3 : 0)}%`, background: item.color }}
134
+ />
135
+ </div>
132
136
  {showLabels && <div className="max-w-full truncate text-xs text-muted-foreground">{item.label}</div>}
133
137
  </div>
134
138
  )
@@ -253,12 +257,19 @@ export type MetricTrendProps = React.ComponentProps<"div"> & {
253
257
  values?: number[]
254
258
  }
255
259
 
256
- function MetricTrend({ label, value, change, positive = true, values, className, ...props }: MetricTrendProps) {
257
- return (
258
- <div data-slot="metric-trend" className={cn("grid gap-3 rounded-lg border bg-card p-4", className)} {...props}>
259
- <div className="flex items-start justify-between gap-3">
260
- <div className="grid gap-1">
261
- <div className="text-sm text-muted-foreground">{label}</div>
260
+ function MetricTrend({ label, value, change, positive = true, values, className, ...props }: MetricTrendProps) {
261
+ return (
262
+ <div
263
+ data-slot="metric-trend"
264
+ className={cn(
265
+ "grid gap-3 rounded-[var(--radius-2xl)] border border-border/75 bg-card/96 p-4 shadow-sm ring-1 ring-foreground/4",
266
+ className
267
+ )}
268
+ {...props}
269
+ >
270
+ <div className="flex items-start justify-between gap-3">
271
+ <div className="grid gap-1">
272
+ <div className="text-sm text-muted-foreground">{label}</div>
262
273
  <div className="text-2xl font-semibold tracking-tight">{value}</div>
263
274
  </div>
264
275
  {change && (
@@ -255,71 +255,82 @@ function CommandPalette({
255
255
  }
256
256
  }
257
257
 
258
- return (
259
- <Dialog open={open} onOpenChange={onOpenChange}>
260
- <DialogContent className={cn("overflow-hidden p-0 sm:max-w-xl", contentClassName)}>
258
+ return (
259
+ <Dialog open={open} onOpenChange={onOpenChange}>
260
+ <DialogContent
261
+ className={cn(
262
+ "overflow-hidden rounded-[var(--radius-3xl)] border-border/80 bg-popover/98 p-0 shadow-[0_28px_90px_rgba(15,23,42,0.24)] backdrop-blur sm:max-w-xl",
263
+ contentClassName
264
+ )}
265
+ >
261
266
  <DialogHeader className="sr-only">
262
267
  <DialogTitle>{title}</DialogTitle>
263
268
  <DialogDescription>{description}</DialogDescription>
264
269
  </DialogHeader>
265
270
 
266
- <div
267
- data-slot="command-palette"
268
- className={cn("flex max-h-[32rem] flex-col overflow-hidden rounded-lg bg-popover text-popover-foreground", className)}
269
- >
270
- <div className="relative border-b p-2">
271
- <SearchIcon className="pointer-events-none absolute left-4 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
272
- <Input
273
- value={search}
274
- onChange={(event) => setSearch(event.target.value)}
275
- placeholder={placeholder}
276
- className={cn("border-0 pl-8 shadow-none focus-visible:ring-0", inputClassName)}
277
- autoFocus
278
- />
279
- </div>
280
-
281
- <div className={cn("overflow-y-auto p-2", listClassName)}>
282
- {!hasResults && hasLoading && (
283
- <div className="flex items-center justify-center gap-2 py-8 text-sm text-muted-foreground">
284
- {renderLoading?.(search) ?? (
285
- <>
286
- <Loader2Icon className="size-4 animate-spin" />
271
+ <div
272
+ data-slot="command-palette"
273
+ className={cn(
274
+ "flex max-h-[32rem] flex-col overflow-hidden rounded-[var(--radius-3xl)] bg-popover/98 text-popover-foreground",
275
+ className
276
+ )}
277
+ >
278
+ <div className="relative border-b border-border/70 bg-muted/20 p-3">
279
+ <SearchIcon className="pointer-events-none absolute left-4 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
280
+ <Input
281
+ value={search}
282
+ onChange={(event) => setSearch(event.target.value)}
283
+ placeholder={placeholder}
284
+ className={cn(
285
+ "h-11 rounded-full border-border/75 bg-background/96 pl-10 shadow-[0_1px_0_rgba(255,255,255,0.05)] focus-visible:ring-2",
286
+ inputClassName
287
+ )}
288
+ autoFocus
289
+ />
290
+ </div>
291
+
292
+ <div className={cn("overflow-y-auto p-3", listClassName)}>
293
+ {!hasResults && hasLoading && (
294
+ <div className="flex items-center justify-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-border/70 bg-muted/30 py-8 text-sm text-muted-foreground">
295
+ {renderLoading?.(search) ?? (
296
+ <>
297
+ <Loader2Icon className="size-4 animate-spin" />
287
298
  {loadingLabel}
288
299
  </>
289
300
  )}
290
301
  </div>
291
302
  )}
292
-
293
- {!hasResults && !hasLoading && (
294
- <div className="py-8 text-center text-sm text-muted-foreground">
295
- {renderEmpty?.(search) ?? emptyLabel}
296
- </div>
297
- )}
298
-
299
- {renderedGroups.map((group) => (
300
- <div key={group.id} className="py-1">
301
- {group.label && (
302
- <div className="flex items-center justify-between px-2 py-1.5 text-xs font-medium text-muted-foreground">
303
- <span>{group.label}</span>
304
- {group.loading && <Loader2Icon className="size-3.5 animate-spin" />}
305
- </div>
306
- )}
307
-
303
+
304
+ {!hasResults && !hasLoading && (
305
+ <div className="rounded-[min(var(--radius-xl),16px)] border border-border/70 bg-muted/30 py-8 text-center text-sm text-muted-foreground">
306
+ {renderEmpty?.(search) ?? emptyLabel}
307
+ </div>
308
+ )}
309
+
310
+ {renderedGroups.map((group) => (
311
+ <div key={group.id} className="py-1">
312
+ {group.label && (
313
+ <div className="flex items-center justify-between px-2 py-2 text-[11px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
314
+ <span>{group.label}</span>
315
+ {group.loading && <Loader2Icon className="size-3.5 animate-spin" />}
316
+ </div>
317
+ )}
318
+
308
319
  {group.error ? (
309
- <div className="rounded-md px-2 py-2 text-xs text-destructive">
320
+ <div className="rounded-[min(var(--radius-xl),16px)] border border-destructive/20 bg-destructive/8 px-3 py-2 text-xs text-destructive">
310
321
  Could not load commands.
311
322
  </div>
312
323
  ) : null}
313
-
314
- {group.loading && group.items.length === 0 && (
315
- <div className="rounded-md px-2 py-2 text-xs text-muted-foreground">
316
- {group.loadingLabel ?? loadingLabel}
317
- </div>
318
- )}
319
-
320
- {group.items.length === 0 && !group.loading && !group.error && group.emptyLabel && (
321
- <div className="rounded-md px-2 py-2 text-xs text-muted-foreground">{group.emptyLabel}</div>
322
- )}
324
+
325
+ {group.loading && group.items.length === 0 && (
326
+ <div className="rounded-[min(var(--radius-xl),16px)] border border-border/70 bg-muted/25 px-3 py-2 text-xs text-muted-foreground">
327
+ {group.loadingLabel ?? loadingLabel}
328
+ </div>
329
+ )}
330
+
331
+ {group.items.length === 0 && !group.loading && !group.error && group.emptyLabel && (
332
+ <div className="rounded-[min(var(--radius-xl),16px)] border border-border/70 bg-muted/25 px-3 py-2 text-xs text-muted-foreground">{group.emptyLabel}</div>
333
+ )}
323
334
 
324
335
  {group.items.map((item) => {
325
336
  const isLoading = loadingKey === item.id
@@ -327,12 +338,12 @@ function CommandPalette({
327
338
  return (
328
339
  <button
329
340
  key={item.id}
330
- type="button"
331
- disabled={item.disabled || isLoading}
332
- data-disabled={item.disabled || undefined}
333
- className="flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-sm outline-none hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50"
334
- onClick={() => void handleSelect(item, group)}
335
- >
341
+ type="button"
342
+ disabled={item.disabled || isLoading}
343
+ data-disabled={item.disabled || undefined}
344
+ className="flex w-full items-start gap-3 rounded-[min(var(--radius-xl),16px)] border border-transparent px-3 py-2.5 text-left text-sm outline-none transition-colors hover:border-border/70 hover:bg-accent/60 hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50"
345
+ onClick={() => void handleSelect(item, group)}
346
+ >
336
347
  {item.icon && <span className="shrink-0 text-muted-foreground [&_svg]:size-4">{item.icon}</span>}
337
348
  <span className="min-w-0 flex-1">
338
349
  <span className="block truncate">{item.label}</span>
@@ -51,32 +51,35 @@ function DataTableBulkActions<TData>({
51
51
  onSelect: action.onSelect ? () => action.onSelect?.(rows) : undefined,
52
52
  }))
53
53
 
54
- return (
55
- <div data-slot="data-table-bulk-actions" className="flex items-center gap-2">
56
- <ActionMenu
57
- label={label}
58
- actions={resolvedActions}
54
+ return (
55
+ <div data-slot="data-table-bulk-actions" className="flex items-center gap-2">
56
+ <ActionMenu
57
+ label={label}
58
+ actions={resolvedActions}
59
59
  disabled={disabled || count === 0}
60
60
  trigger={
61
- <Button
62
- type="button"
63
- variant="outline"
64
- size="sm"
65
- disabled={disabled || count === 0}
66
- className={cn("gap-1.5", triggerClassName)}
67
- >
68
- {selectedLabel(count)}
69
- <ChevronDownIcon className="size-3.5" />
61
+ <Button
62
+ type="button"
63
+ variant="outline"
64
+ size="sm"
65
+ disabled={disabled || count === 0}
66
+ className={cn(
67
+ "gap-1.5 border-border/80 bg-background/94 shadow-[0_1px_0_rgba(255,255,255,0.06)]",
68
+ triggerClassName
69
+ )}
70
+ >
71
+ {selectedLabel(count)}
72
+ <ChevronDownIcon className="size-3.5" />
70
73
  </Button>
71
74
  }
72
75
  {...props}
73
76
  />
74
-
75
- {onClearSelection && count > 0 && (
76
- <Button type="button" variant="ghost" size="sm" onClick={onClearSelection}>
77
- {clearLabel}
78
- </Button>
79
- )}
77
+
78
+ {onClearSelection && count > 0 && (
79
+ <Button type="button" variant="ghost" size="sm" className="rounded-full" onClick={onClearSelection}>
80
+ {clearLabel}
81
+ </Button>
82
+ )}
80
83
  </div>
81
84
  )
82
85
  }
@@ -47,19 +47,30 @@ function DataTableColumnVisibilityMenu<TData>({
47
47
 
48
48
  return (
49
49
  <DropdownMenu>
50
- <DropdownMenuTrigger
51
- render={
52
- <Button type="button" variant="outline" size="sm" className={triggerClassName} />
53
- }
54
- >
50
+ <DropdownMenuTrigger
51
+ render={
52
+ <Button
53
+ type="button"
54
+ variant="outline"
55
+ size="sm"
56
+ className={cn(
57
+ "border-border/80 bg-background/94 shadow-[0_1px_0_rgba(255,255,255,0.06)]",
58
+ triggerClassName
59
+ )}
60
+ />
61
+ }
62
+ >
55
63
  <Columns3Icon data-icon="inline-start" />
56
64
  {triggerLabel ?? label}
57
65
  </DropdownMenuTrigger>
58
- <DropdownMenuContent
59
- align={align}
60
- side={side}
61
- className={cn("min-w-48", contentClassName)}
62
- >
66
+ <DropdownMenuContent
67
+ align={align}
68
+ side={side}
69
+ className={cn(
70
+ "min-w-48 rounded-[var(--radius-2xl)] border-border/80 bg-popover/98 shadow-[0_24px_80px_rgba(15,23,42,0.18)] backdrop-blur",
71
+ contentClassName
72
+ )}
73
+ >
63
74
  <DropdownMenuLabel>{label}</DropdownMenuLabel>
64
75
  <DropdownMenuSeparator />
65
76
  {columns.map((column) => (
@@ -66,12 +66,12 @@ function DataTablePagination({
66
66
  <SimpleSelect
67
67
  value={String(pageSize)}
68
68
  onValueChange={(value) => onPageSizeChange(Number(value))}
69
- options={pageSizeOptions.map((option) => ({
70
- label: String(option),
71
- value: String(option),
72
- }))}
73
- disabled={disabled}
74
- triggerClassName="h-9 w-20 rounded-full border-border/80 bg-background/90"
69
+ options={pageSizeOptions.map((option) => ({
70
+ label: String(option),
71
+ value: String(option),
72
+ }))}
73
+ disabled={disabled}
74
+ triggerClassName="h-9 w-20 rounded-full border-border/85 bg-background/94"
75
75
  />
76
76
  </div>
77
77
  )}