@stasho/ds 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -2
- package/src/components/alert/alert.tsx +14 -14
- package/src/components/badge/badge.tsx +15 -29
- package/src/components/breadcrumb/breadcrumb.tsx +4 -4
- package/src/components/button/button.tsx +203 -55
- package/src/components/card/card.tsx +2 -3
- package/src/components/checkbox/checkbox.tsx +21 -23
- package/src/components/combobox/combobox.tsx +20 -13
- package/src/components/copyable-text/copyable-text.tsx +3 -3
- package/src/components/dialog/dialog.tsx +3 -4
- package/src/components/form-field/form-field.tsx +2 -2
- package/src/components/input/input.tsx +13 -7
- package/src/components/multi-select/multi-select.tsx +26 -18
- package/src/components/pagination/pagination.tsx +11 -13
- package/src/components/progress-bar/progress-bar.tsx +6 -2
- package/src/components/radio-group/radio-group.tsx +15 -10
- package/src/components/select/select.tsx +19 -12
- package/src/components/slider/slider.tsx +25 -19
- package/src/components/stepper/stepper.tsx +20 -16
- package/src/components/switch/switch.tsx +23 -16
- package/src/components/table/table.tsx +3 -3
- package/src/components/tabs/tabs.tsx +24 -33
- package/src/components/textarea/textarea.tsx +13 -7
- package/src/components/tooltip/tooltip.tsx +2 -2
- package/src/components/ui/skeleton.tsx +1 -1
- package/src/styles/tokens.css +202 -283
- package/src/components/ui/spinner.tsx +0 -27
|
@@ -8,12 +8,17 @@ import { cn } from "@ac/lib/cn";
|
|
|
8
8
|
const triggerVariants = cva(
|
|
9
9
|
[
|
|
10
10
|
"inline-flex items-center justify-between",
|
|
11
|
-
"w-full font-sans text-foreground
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
11
|
+
"w-full font-sans text-foreground",
|
|
12
|
+
"bg-background dark:bg-surface",
|
|
13
|
+
"border border-edge rounded-none",
|
|
14
|
+
"hover:border-edge-hover",
|
|
15
|
+
"focus-visible:outline-none",
|
|
16
|
+
"focus-visible:border-accent-700 dark:focus-visible:border-accent",
|
|
17
|
+
"disabled:bg-muted dark:disabled:bg-background",
|
|
18
|
+
"disabled:border-edge/50",
|
|
19
|
+
"disabled:text-foreground/30",
|
|
20
|
+
"disabled:cursor-not-allowed",
|
|
21
|
+
"transition-colors",
|
|
17
22
|
].join(" "),
|
|
18
23
|
{
|
|
19
24
|
variants: {
|
|
@@ -82,8 +87,10 @@ const Combobox = forwardRef<HTMLButtonElement, ComboboxProps>(
|
|
|
82
87
|
aria-invalid={error || undefined}
|
|
83
88
|
className={cn(
|
|
84
89
|
triggerVariants({ size }),
|
|
85
|
-
error &&
|
|
86
|
-
|
|
90
|
+
error &&
|
|
91
|
+
"border-error hover:border-error focus-visible:border-error dark:focus-visible:border-error",
|
|
92
|
+
!selectedLabel &&
|
|
93
|
+
(disabled ? "text-muted-foreground/50" : "text-muted-foreground"),
|
|
87
94
|
className,
|
|
88
95
|
)}
|
|
89
96
|
{...rest}
|
|
@@ -105,8 +112,8 @@ const Combobox = forwardRef<HTMLButtonElement, ComboboxProps>(
|
|
|
105
112
|
<Popover.Content
|
|
106
113
|
className={cn(
|
|
107
114
|
"z-50 w-[var(--radix-popover-trigger-width)]",
|
|
108
|
-
"overflow-hidden rounded-
|
|
109
|
-
"bg-
|
|
115
|
+
"overflow-hidden rounded-none",
|
|
116
|
+
"bg-popover-bg border border-popover-border shadow",
|
|
110
117
|
)}
|
|
111
118
|
sideOffset={4}
|
|
112
119
|
align="start"
|
|
@@ -134,12 +141,12 @@ const Combobox = forwardRef<HTMLButtonElement, ComboboxProps>(
|
|
|
134
141
|
setOpen(false);
|
|
135
142
|
}}
|
|
136
143
|
className={cn(
|
|
137
|
-
"relative flex items-center rounded-
|
|
144
|
+
"relative flex items-center rounded-none px-4 py-2",
|
|
138
145
|
"text-sm text-foreground cursor-pointer select-none",
|
|
139
146
|
"outline-none",
|
|
140
147
|
"data-[selected=true]:bg-muted",
|
|
141
|
-
"data-[disabled=true]:
|
|
142
|
-
"data-[disabled=true]:
|
|
148
|
+
"data-[disabled=true]:text-foreground/30",
|
|
149
|
+
"data-[disabled=true]:cursor-not-allowed",
|
|
143
150
|
)}
|
|
144
151
|
>
|
|
145
152
|
<span className="flex-1">{option.label}</span>
|
|
@@ -98,7 +98,7 @@ const CopyableText = forwardRef<HTMLSpanElement, CopyableTextProps>(
|
|
|
98
98
|
ref={ref}
|
|
99
99
|
className={cn(
|
|
100
100
|
copyableTextVariants({ size }),
|
|
101
|
-
href && "text-
|
|
101
|
+
href && "text-accent-500 dark:text-accent",
|
|
102
102
|
className,
|
|
103
103
|
)}
|
|
104
104
|
{...rest}
|
|
@@ -125,7 +125,7 @@ const CopyableText = forwardRef<HTMLSpanElement, CopyableTextProps>(
|
|
|
125
125
|
onClick={handleCopy}
|
|
126
126
|
className={cn(
|
|
127
127
|
"relative inline-flex items-center justify-center",
|
|
128
|
-
"rounded-
|
|
128
|
+
"rounded-none cursor-pointer",
|
|
129
129
|
"hover:bg-foreground/10 transition-colors",
|
|
130
130
|
btnCn,
|
|
131
131
|
)}
|
|
@@ -170,7 +170,7 @@ const CopyableText = forwardRef<HTMLSpanElement, CopyableTextProps>(
|
|
|
170
170
|
rel="noopener noreferrer"
|
|
171
171
|
onClick={(e) => e.stopPropagation()}
|
|
172
172
|
className={cn(
|
|
173
|
-
"inline-flex items-center justify-center rounded-
|
|
173
|
+
"inline-flex items-center justify-center rounded-none",
|
|
174
174
|
"text-muted-foreground hover:text-foreground",
|
|
175
175
|
"hover:bg-foreground/10 transition-colors",
|
|
176
176
|
btnCn,
|
|
@@ -38,7 +38,7 @@ const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(
|
|
|
38
38
|
<DialogPrimitive.Content
|
|
39
39
|
ref={ref}
|
|
40
40
|
className={cn(
|
|
41
|
-
"relative w-full max-w-md rounded-
|
|
41
|
+
"relative w-full max-w-md rounded-xl bg-surface p-6",
|
|
42
42
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
43
43
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
44
44
|
"motion-reduce:animate-none",
|
|
@@ -56,10 +56,9 @@ const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(
|
|
|
56
56
|
{locked ? null : (
|
|
57
57
|
<DialogPrimitive.Close
|
|
58
58
|
className={cn(
|
|
59
|
-
"absolute top-4 right-4 rounded-
|
|
59
|
+
"absolute top-4 right-4 rounded-none",
|
|
60
60
|
"text-muted-foreground transition-colors hover:text-foreground",
|
|
61
|
-
"focus-visible:outline-
|
|
62
|
-
"focus-visible:ring-primary-400 focus-visible:ring-offset-2",
|
|
61
|
+
"focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2",
|
|
63
62
|
)}
|
|
64
63
|
aria-label="Close"
|
|
65
64
|
>
|
|
@@ -47,14 +47,14 @@ function FormField({
|
|
|
47
47
|
>
|
|
48
48
|
{label}
|
|
49
49
|
{required && (
|
|
50
|
-
<span className="text-error
|
|
50
|
+
<span className="text-error ml-0.5" aria-hidden="true">
|
|
51
51
|
*
|
|
52
52
|
</span>
|
|
53
53
|
)}
|
|
54
54
|
</label>
|
|
55
55
|
{child}
|
|
56
56
|
{error ? (
|
|
57
|
-
<p id={messageId} role="alert" className="text-xs text-error
|
|
57
|
+
<p id={messageId} role="alert" className="text-xs text-error">
|
|
58
58
|
{error}
|
|
59
59
|
</p>
|
|
60
60
|
) : helperText ? (
|
|
@@ -4,13 +4,18 @@ import { cn } from "@ac/lib/cn";
|
|
|
4
4
|
|
|
5
5
|
const inputVariants = cva(
|
|
6
6
|
[
|
|
7
|
-
"w-full font-sans text-foreground
|
|
8
|
-
"
|
|
7
|
+
"w-full font-sans text-foreground",
|
|
8
|
+
"bg-background dark:bg-surface",
|
|
9
|
+
"border border-edge rounded-none",
|
|
9
10
|
"placeholder:text-muted-foreground",
|
|
10
|
-
"focus-visible:outline-none
|
|
11
|
-
"focus-visible:
|
|
12
|
-
"disabled:
|
|
13
|
-
"
|
|
11
|
+
"focus-visible:outline-none",
|
|
12
|
+
"focus-visible:border-accent-700 dark:focus-visible:border-accent",
|
|
13
|
+
"disabled:bg-muted dark:disabled:bg-background",
|
|
14
|
+
"disabled:border-edge/50",
|
|
15
|
+
"disabled:text-foreground/30",
|
|
16
|
+
"disabled:placeholder:text-muted-foreground/50",
|
|
17
|
+
"disabled:cursor-not-allowed",
|
|
18
|
+
"transition-colors",
|
|
14
19
|
].join(" "),
|
|
15
20
|
{
|
|
16
21
|
variants: {
|
|
@@ -37,7 +42,8 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
37
42
|
ref={ref}
|
|
38
43
|
className={cn(
|
|
39
44
|
inputVariants({ size }),
|
|
40
|
-
error &&
|
|
45
|
+
error &&
|
|
46
|
+
"border-error hover:border-error focus-visible:border-error dark:focus-visible:border-error",
|
|
41
47
|
className,
|
|
42
48
|
)}
|
|
43
49
|
aria-invalid={error || undefined}
|
|
@@ -8,12 +8,17 @@ import { cn } from "@ac/lib/cn";
|
|
|
8
8
|
const triggerVariants = cva(
|
|
9
9
|
[
|
|
10
10
|
"inline-flex items-center gap-1.5",
|
|
11
|
-
"w-full font-sans text-foreground
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
11
|
+
"w-full font-sans text-foreground",
|
|
12
|
+
"bg-background dark:bg-surface",
|
|
13
|
+
"border border-edge rounded-none",
|
|
14
|
+
"hover:border-edge-hover",
|
|
15
|
+
"focus-visible:outline-none",
|
|
16
|
+
"focus-visible:border-accent-700 dark:focus-visible:border-accent",
|
|
17
|
+
"aria-disabled:bg-muted dark:aria-disabled:bg-background",
|
|
18
|
+
"aria-disabled:border-edge/50",
|
|
19
|
+
"aria-disabled:text-foreground/30",
|
|
20
|
+
"aria-disabled:cursor-not-allowed",
|
|
21
|
+
"transition-colors",
|
|
17
22
|
].join(" "),
|
|
18
23
|
{
|
|
19
24
|
variants: {
|
|
@@ -30,7 +35,7 @@ const triggerVariants = cva(
|
|
|
30
35
|
|
|
31
36
|
const tagVariants = cva(
|
|
32
37
|
[
|
|
33
|
-
"inline-flex items-center gap-1 rounded-
|
|
38
|
+
"inline-flex items-center gap-1 rounded-[2px] bg-muted",
|
|
34
39
|
"text-foreground max-w-32 select-none",
|
|
35
40
|
].join(" "),
|
|
36
41
|
{
|
|
@@ -137,8 +142,11 @@ const MultiSelect = forwardRef<HTMLDivElement, MultiSelectProps>(
|
|
|
137
142
|
triggerVariants({ size }),
|
|
138
143
|
"cursor-pointer",
|
|
139
144
|
error &&
|
|
140
|
-
"border-
|
|
141
|
-
!hasSelection &&
|
|
145
|
+
"border-error hover:border-error focus-visible:border-error dark:focus-visible:border-error",
|
|
146
|
+
!hasSelection &&
|
|
147
|
+
(disabled
|
|
148
|
+
? "text-muted-foreground/50"
|
|
149
|
+
: "text-muted-foreground"),
|
|
142
150
|
className,
|
|
143
151
|
)}
|
|
144
152
|
{...rest}
|
|
@@ -157,7 +165,7 @@ const MultiSelect = forwardRef<HTMLDivElement, MultiSelectProps>(
|
|
|
157
165
|
aria-label={`Remove ${opt.label}`}
|
|
158
166
|
onClick={(e) => removeTag(e, opt.value)}
|
|
159
167
|
className={cn(
|
|
160
|
-
"shrink-0 rounded-
|
|
168
|
+
"shrink-0 rounded-[2px]",
|
|
161
169
|
"hover:bg-foreground/10 transition-colors",
|
|
162
170
|
size === "sm" ? "size-3.5" : "size-4",
|
|
163
171
|
)}
|
|
@@ -187,7 +195,7 @@ const MultiSelect = forwardRef<HTMLDivElement, MultiSelectProps>(
|
|
|
187
195
|
aria-label="Clear all"
|
|
188
196
|
onClick={clearAll}
|
|
189
197
|
className={cn(
|
|
190
|
-
"shrink-0 rounded-
|
|
198
|
+
"shrink-0 rounded-[2px]",
|
|
191
199
|
"text-muted-foreground",
|
|
192
200
|
"hover:text-foreground transition-colors",
|
|
193
201
|
size === "sm" ? "size-4" : "size-5",
|
|
@@ -224,8 +232,8 @@ const MultiSelect = forwardRef<HTMLDivElement, MultiSelectProps>(
|
|
|
224
232
|
<Popover.Content
|
|
225
233
|
className={cn(
|
|
226
234
|
"z-50 w-[var(--radix-popover-trigger-width)]",
|
|
227
|
-
"overflow-hidden rounded-
|
|
228
|
-
"bg-
|
|
235
|
+
"overflow-hidden rounded-none",
|
|
236
|
+
"bg-popover-bg border border-popover-border shadow",
|
|
229
237
|
)}
|
|
230
238
|
sideOffset={4}
|
|
231
239
|
align="start"
|
|
@@ -260,22 +268,22 @@ const MultiSelect = forwardRef<HTMLDivElement, MultiSelectProps>(
|
|
|
260
268
|
onSelect={() => toggle(option.value)}
|
|
261
269
|
className={cn(
|
|
262
270
|
"relative flex items-center gap-2",
|
|
263
|
-
"rounded-
|
|
271
|
+
"rounded-none px-3 py-2",
|
|
264
272
|
"text-sm text-foreground",
|
|
265
273
|
"cursor-pointer select-none",
|
|
266
274
|
"outline-none",
|
|
267
275
|
"data-[selected=true]:bg-muted",
|
|
268
|
-
"data-[disabled=true]:
|
|
269
|
-
"data-[disabled=true]:
|
|
276
|
+
"data-[disabled=true]:text-foreground/30",
|
|
277
|
+
"data-[disabled=true]:cursor-not-allowed",
|
|
270
278
|
)}
|
|
271
279
|
>
|
|
272
280
|
<span
|
|
273
281
|
className={cn(
|
|
274
282
|
"flex size-4 shrink-0 items-center",
|
|
275
283
|
"justify-center",
|
|
276
|
-
"rounded border
|
|
284
|
+
"rounded-none border transition-colors",
|
|
277
285
|
selected
|
|
278
|
-
? "border-
|
|
286
|
+
? "border-accent bg-accent text-accent-foreground"
|
|
279
287
|
: "border-edge bg-surface",
|
|
280
288
|
)}
|
|
281
289
|
aria-hidden="true"
|
|
@@ -80,28 +80,26 @@ type PaginationProps = Omit<HTMLAttributes<HTMLElement>, "onChange"> & {
|
|
|
80
80
|
|
|
81
81
|
const NAV_BUTTON = [
|
|
82
82
|
"inline-flex items-center justify-center",
|
|
83
|
-
"size-8 rounded-
|
|
84
|
-
"text-
|
|
85
|
-
"hover:bg-primary-100 dark:hover:bg-primary-200/10",
|
|
83
|
+
"size-8 rounded-none",
|
|
84
|
+
"text-foreground/60 hover:text-accent-500 dark:hover:text-accent",
|
|
86
85
|
"transition-colors cursor-pointer",
|
|
87
|
-
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-
|
|
86
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
|
|
88
87
|
].join(" ");
|
|
89
88
|
|
|
90
|
-
const NAV_DISABLED = "
|
|
89
|
+
const NAV_DISABLED = "text-foreground/30 cursor-not-allowed";
|
|
91
90
|
|
|
92
91
|
const PAGE_BUTTON = [
|
|
93
92
|
"inline-flex items-center justify-center",
|
|
94
|
-
"size-
|
|
95
|
-
"font-
|
|
96
|
-
"text-
|
|
97
|
-
"hover:bg-primary-100 dark:hover:bg-primary-200/10",
|
|
93
|
+
"size-[26px] rounded-none",
|
|
94
|
+
"font-mono text-sm",
|
|
95
|
+
"text-foreground/60 hover:text-accent-500 dark:hover:text-accent",
|
|
98
96
|
"transition-colors cursor-pointer",
|
|
99
|
-
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-
|
|
97
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
|
|
100
98
|
].join(" ");
|
|
101
99
|
|
|
102
100
|
const PAGE_ACTIVE = [
|
|
103
|
-
"bg-
|
|
104
|
-
"hover:
|
|
101
|
+
"bg-accent/15 text-accent-500 dark:text-accent",
|
|
102
|
+
"hover:text-accent-500 dark:hover:text-accent",
|
|
105
103
|
].join(" ");
|
|
106
104
|
|
|
107
105
|
const Pagination = forwardRef<HTMLElement, PaginationProps>(
|
|
@@ -164,7 +162,7 @@ const Pagination = forwardRef<HTMLElement, PaginationProps>(
|
|
|
164
162
|
item === "ellipsis" ? (
|
|
165
163
|
<span
|
|
166
164
|
key={i}
|
|
167
|
-
className="inline-flex items-center justify-center size-
|
|
165
|
+
className="inline-flex items-center justify-center size-[26px] font-mono text-sm text-foreground/40 select-none"
|
|
168
166
|
aria-hidden="true"
|
|
169
167
|
>
|
|
170
168
|
{"\u2026"}
|
|
@@ -13,7 +13,11 @@ import { cn } from "@ac/lib/cn";
|
|
|
13
13
|
/* ── Variants ──────────────────────────────────── */
|
|
14
14
|
|
|
15
15
|
const progressBarVariants = cva(
|
|
16
|
-
|
|
16
|
+
[
|
|
17
|
+
"relative rounded-full overflow-hidden",
|
|
18
|
+
"bg-muted dark:bg-neutral-900",
|
|
19
|
+
"shadow-[inset_0_1px_0_rgba(255,255,255,0.06),inset_0_-1px_0_rgba(0,0,0,0.4)]",
|
|
20
|
+
].join(" "),
|
|
17
21
|
{
|
|
18
22
|
variants: {
|
|
19
23
|
size: {
|
|
@@ -89,7 +93,7 @@ const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(
|
|
|
89
93
|
data-fill=""
|
|
90
94
|
data-indeterminate={indeterminate ? "" : undefined}
|
|
91
95
|
className={cn(
|
|
92
|
-
"h-full rounded-full bg-
|
|
96
|
+
"h-full rounded-full bg-accent",
|
|
93
97
|
indeterminate
|
|
94
98
|
? "animate-progress-indeterminate"
|
|
95
99
|
: "transition-all",
|
|
@@ -5,21 +5,26 @@ import { cn } from "@ac/lib/cn";
|
|
|
5
5
|
|
|
6
6
|
const radioItemVariants = cva(
|
|
7
7
|
[
|
|
8
|
-
"peer shrink-0 rounded-full
|
|
9
|
-
"
|
|
8
|
+
"peer shrink-0 rounded-full",
|
|
9
|
+
"bg-background dark:bg-surface",
|
|
10
|
+
"border border-edge",
|
|
10
11
|
"hover:border-edge-hover",
|
|
11
|
-
"focus-visible:outline-none
|
|
12
|
-
"focus-visible:
|
|
13
|
-
"disabled:
|
|
14
|
-
"
|
|
12
|
+
"focus-visible:outline-none",
|
|
13
|
+
"focus-visible:border-accent-700 dark:focus-visible:border-accent",
|
|
14
|
+
"disabled:bg-muted dark:disabled:bg-background",
|
|
15
|
+
"disabled:border-edge/50",
|
|
16
|
+
"disabled:cursor-not-allowed",
|
|
17
|
+
"disabled:[&_span]:bg-foreground/30",
|
|
18
|
+
"disabled:data-[state=checked]:border-edge/50",
|
|
19
|
+
"data-[state=checked]:border-accent",
|
|
15
20
|
"transition-colors",
|
|
16
21
|
].join(" "),
|
|
17
22
|
{
|
|
18
23
|
variants: {
|
|
19
24
|
size: {
|
|
20
|
-
xs: "size-
|
|
21
|
-
sm: "size-
|
|
22
|
-
md: "size-
|
|
25
|
+
xs: "size-3.5",
|
|
26
|
+
sm: "size-4",
|
|
27
|
+
md: "size-5",
|
|
23
28
|
},
|
|
24
29
|
},
|
|
25
30
|
defaultVariants: {
|
|
@@ -70,7 +75,7 @@ const RadioGroupItem = forwardRef<HTMLButtonElement, RadioGroupItemProps>(
|
|
|
70
75
|
"transition-[clip-path] duration-200 ease-in-out motion-reduce:transition-none",
|
|
71
76
|
)}
|
|
72
77
|
>
|
|
73
|
-
<span className="block size-[80%] rounded-full bg-
|
|
78
|
+
<span className="block size-[80%] rounded-full bg-accent" />
|
|
74
79
|
</RadioGroupPrimitive.Indicator>
|
|
75
80
|
</RadioGroupPrimitive.Item>
|
|
76
81
|
);
|
|
@@ -7,13 +7,19 @@ import { cn } from "@ac/lib/cn";
|
|
|
7
7
|
const triggerVariants = cva(
|
|
8
8
|
[
|
|
9
9
|
"inline-flex items-center justify-between",
|
|
10
|
-
"w-full font-sans text-foreground
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
10
|
+
"w-full font-sans text-foreground",
|
|
11
|
+
"bg-background dark:bg-surface",
|
|
12
|
+
"border border-edge rounded-none",
|
|
13
|
+
"hover:border-edge-hover",
|
|
14
|
+
"focus-visible:outline-none",
|
|
15
|
+
"focus-visible:border-accent-700 dark:focus-visible:border-accent",
|
|
16
|
+
"disabled:bg-muted dark:disabled:bg-background",
|
|
17
|
+
"disabled:border-edge/50",
|
|
18
|
+
"disabled:text-foreground/30",
|
|
19
|
+
"disabled:cursor-not-allowed",
|
|
20
|
+
"transition-colors",
|
|
16
21
|
"data-[placeholder]:text-muted-foreground",
|
|
22
|
+
"disabled:data-[placeholder]:text-muted-foreground/50",
|
|
17
23
|
].join(" "),
|
|
18
24
|
{
|
|
19
25
|
variants: {
|
|
@@ -70,7 +76,8 @@ const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
70
76
|
aria-invalid={error || undefined}
|
|
71
77
|
className={cn(
|
|
72
78
|
triggerVariants({ size }),
|
|
73
|
-
error &&
|
|
79
|
+
error &&
|
|
80
|
+
"border-error hover:border-error focus-visible:border-error dark:focus-visible:border-error",
|
|
74
81
|
className,
|
|
75
82
|
)}
|
|
76
83
|
>
|
|
@@ -82,8 +89,8 @@ const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
82
89
|
<SelectPrimitive.Portal>
|
|
83
90
|
<SelectPrimitive.Content
|
|
84
91
|
className={cn(
|
|
85
|
-
"z-50 overflow-hidden rounded-
|
|
86
|
-
"bg-
|
|
92
|
+
"z-50 overflow-hidden rounded-none",
|
|
93
|
+
"bg-popover-bg border border-popover-border shadow",
|
|
87
94
|
)}
|
|
88
95
|
position="popper"
|
|
89
96
|
sideOffset={4}
|
|
@@ -95,12 +102,12 @@ const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
95
102
|
value={option.value}
|
|
96
103
|
disabled={option.disabled ?? false}
|
|
97
104
|
className={cn(
|
|
98
|
-
"relative flex items-center rounded-
|
|
105
|
+
"relative flex items-center rounded-none px-4 py-2",
|
|
99
106
|
"text-sm text-foreground cursor-pointer select-none",
|
|
100
107
|
"outline-none",
|
|
101
108
|
"data-[highlighted]:bg-muted",
|
|
102
|
-
"data-[disabled]:
|
|
103
|
-
"data-[disabled]:
|
|
109
|
+
"data-[disabled]:text-foreground/30",
|
|
110
|
+
"data-[disabled]:cursor-not-allowed",
|
|
104
111
|
)}
|
|
105
112
|
>
|
|
106
113
|
<SelectPrimitive.ItemText>
|
|
@@ -6,7 +6,8 @@ import { cn } from "@ac/lib/cn";
|
|
|
6
6
|
const trackVariants = cva(
|
|
7
7
|
[
|
|
8
8
|
"relative w-full grow overflow-hidden rounded-full",
|
|
9
|
-
"bg-
|
|
9
|
+
"bg-muted dark:bg-neutral-900",
|
|
10
|
+
"shadow-[inset_0_1px_0_rgba(255,255,255,0.06),inset_0_-1px_0_rgba(0,0,0,0.4)]",
|
|
10
11
|
].join(" "),
|
|
11
12
|
{
|
|
12
13
|
variants: {
|
|
@@ -23,17 +24,22 @@ const trackVariants = cva(
|
|
|
23
24
|
|
|
24
25
|
const thumbVariants = cva(
|
|
25
26
|
[
|
|
26
|
-
"block rounded-full bg-
|
|
27
|
-
"border-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
27
|
+
"block rounded-full bg-background",
|
|
28
|
+
"border-[1.5px] border-accent",
|
|
29
|
+
"transition-[background-color,box-shadow] motion-reduce:transition-none",
|
|
30
|
+
"hover:bg-accent",
|
|
31
|
+
"hover:shadow-[0_0_6px_var(--accent),0_0_12px_rgba(0,225,250,0.5)]",
|
|
32
|
+
"focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2",
|
|
33
|
+
"focus-visible:shadow-[0_0_6px_var(--accent),0_0_12px_rgba(0,225,250,0.5)]",
|
|
34
|
+
"data-[disabled]:bg-background data-[disabled]:border-foreground/30",
|
|
35
|
+
"data-[disabled]:hover:bg-background",
|
|
36
|
+
"data-[disabled]:shadow-none data-[disabled]:cursor-not-allowed",
|
|
31
37
|
].join(" "),
|
|
32
38
|
{
|
|
33
39
|
variants: {
|
|
34
40
|
size: {
|
|
35
|
-
sm: "size-
|
|
36
|
-
md: "size-5",
|
|
41
|
+
sm: "size-3",
|
|
42
|
+
md: "size-3.5",
|
|
37
43
|
},
|
|
38
44
|
},
|
|
39
45
|
defaultVariants: {
|
|
@@ -80,7 +86,7 @@ const Slider = forwardRef<
|
|
|
80
86
|
{...(disabled ? { disabled: true } : {})}
|
|
81
87
|
className={cn(
|
|
82
88
|
"relative flex w-full touch-none select-none items-center",
|
|
83
|
-
disabled && "
|
|
89
|
+
disabled && "cursor-not-allowed",
|
|
84
90
|
className,
|
|
85
91
|
)}
|
|
86
92
|
onValueChange={(val) => {
|
|
@@ -91,25 +97,25 @@ const Slider = forwardRef<
|
|
|
91
97
|
onPointerLeave={() => setHovering(false)}
|
|
92
98
|
{...rootProps}
|
|
93
99
|
>
|
|
94
|
-
<SliderPrimitive.Track
|
|
95
|
-
className=
|
|
96
|
-
trackVariants({ size }),
|
|
97
|
-
error && "ring-2 ring-error-400",
|
|
98
|
-
)}
|
|
99
|
-
>
|
|
100
|
-
<SliderPrimitive.Range className="absolute h-full bg-primary-500 rounded-full" />
|
|
100
|
+
<SliderPrimitive.Track className={cn(trackVariants({ size }))}>
|
|
101
|
+
<SliderPrimitive.Range className="absolute h-full bg-accent data-[disabled]:bg-foreground/30 rounded-full" />
|
|
101
102
|
</SliderPrimitive.Track>
|
|
102
103
|
{displayValue.map((val, i) => (
|
|
103
104
|
<SliderPrimitive.Thumb
|
|
104
105
|
key={i}
|
|
105
|
-
className={cn(
|
|
106
|
+
className={cn(
|
|
107
|
+
thumbVariants({ size }),
|
|
108
|
+
"relative",
|
|
109
|
+
error &&
|
|
110
|
+
"border-error hover:bg-error hover:shadow-[0_0_6px_var(--error),0_0_12px_rgba(255,61,0,0.5)] focus-visible:shadow-[0_0_6px_var(--error),0_0_12px_rgba(255,61,0,0.5)] focus-visible:outline-error",
|
|
111
|
+
)}
|
|
106
112
|
>
|
|
107
113
|
{showTooltip && hovering && (
|
|
108
114
|
<span
|
|
109
115
|
className={cn(
|
|
110
116
|
"absolute bottom-full left-1/2 -translate-x-1/2 mb-2",
|
|
111
|
-
"rounded-
|
|
112
|
-
"text-xs text-
|
|
117
|
+
"rounded-none bg-popover-bg border border-popover-border px-2 py-1",
|
|
118
|
+
"text-xs text-foreground whitespace-nowrap pointer-events-none",
|
|
113
119
|
)}
|
|
114
120
|
>
|
|
115
121
|
{val}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
useContext,
|
|
7
7
|
type HTMLAttributes,
|
|
8
8
|
} from "react";
|
|
9
|
+
import { Check } from "@phosphor-icons/react";
|
|
9
10
|
import { cn } from "@ac/lib/cn";
|
|
10
11
|
|
|
11
12
|
/* ── Stepper context (orientation) ─────────────── */
|
|
@@ -114,23 +115,22 @@ const StepperIndicator = forwardRef<HTMLDivElement, StepperIndicatorProps>(
|
|
|
114
115
|
ref={ref}
|
|
115
116
|
data-state={state}
|
|
116
117
|
className={cn(
|
|
117
|
-
"relative flex size-8 items-center justify-center rounded-
|
|
118
|
-
"font-
|
|
119
|
-
"border
|
|
120
|
-
"data-[state=active]:border-
|
|
121
|
-
"data-[state=
|
|
122
|
-
"
|
|
118
|
+
"relative flex size-8 items-center justify-center rounded-[2px]",
|
|
119
|
+
"font-sans text-sm font-semibold",
|
|
120
|
+
"border border-edge text-foreground/45 bg-transparent",
|
|
121
|
+
"data-[state=active]:border-accent data-[state=active]:text-accent-500 dark:data-[state=active]:text-accent",
|
|
122
|
+
"data-[state=active]:shadow-[0_0_6px_rgba(0,225,250,0.5),0_0_14px_rgba(0,225,250,0.3)]",
|
|
123
|
+
"data-[state=completed]:border-accent data-[state=completed]:bg-accent data-[state=completed]:text-neutral-950",
|
|
124
|
+
"transition-all duration-200 motion-reduce:transition-colors",
|
|
123
125
|
className,
|
|
124
126
|
)}
|
|
125
127
|
{...rest}
|
|
126
128
|
>
|
|
127
|
-
{state === "
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
</>
|
|
129
|
+
{state === "completed" ? (
|
|
130
|
+
<Check weight="bold" className="size-4" aria-hidden="true" />
|
|
131
|
+
) : (
|
|
132
|
+
children
|
|
132
133
|
)}
|
|
133
|
-
{children}
|
|
134
134
|
</div>
|
|
135
135
|
);
|
|
136
136
|
},
|
|
@@ -186,19 +186,23 @@ StepperDescription.displayName = "StepperDescription";
|
|
|
186
186
|
|
|
187
187
|
/* ── StepperConnector (li, visual line) ────────── */
|
|
188
188
|
|
|
189
|
-
type StepperConnectorProps = HTMLAttributes<HTMLLIElement
|
|
189
|
+
type StepperConnectorProps = HTMLAttributes<HTMLLIElement> & {
|
|
190
|
+
/** Mark the connector as filled (cyan) — used between two consecutive completed steps. */
|
|
191
|
+
completed?: boolean;
|
|
192
|
+
};
|
|
190
193
|
|
|
191
194
|
const StepperConnector = forwardRef<HTMLLIElement, StepperConnectorProps>(
|
|
192
|
-
({ className, ...rest }, ref) => {
|
|
195
|
+
({ className, completed, ...rest }, ref) => {
|
|
193
196
|
const { orientation } = useStepperContext();
|
|
194
197
|
return (
|
|
195
198
|
<li
|
|
196
199
|
ref={ref}
|
|
197
200
|
aria-hidden="true"
|
|
198
201
|
data-orientation={orientation}
|
|
202
|
+
data-completed={completed ? "" : undefined}
|
|
199
203
|
className={cn(
|
|
200
|
-
"relative overflow-hidden
|
|
201
|
-
orientation === "horizontal" ? "h-
|
|
204
|
+
"relative overflow-hidden flex-1 bg-edge data-[completed]:bg-accent transition-colors",
|
|
205
|
+
orientation === "horizontal" ? "h-px" : "w-px",
|
|
202
206
|
className,
|
|
203
207
|
)}
|
|
204
208
|
{...rest}
|