@boyernick/standard-ui-react 0.1.1-canary.9 → 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 +5 -3
- package/src/accordion.tsx +5 -2
- package/src/alert-dialog.tsx +1 -1
- package/src/attachment.tsx +5 -2
- package/src/autocomplete.tsx +4 -3
- package/src/block-editor.tsx +1747 -0
- package/src/brand.tsx +2 -2
- package/src/breadcrumb.tsx +14 -7
- package/src/button.tsx +22 -11
- package/src/calendar.tsx +6 -3
- package/src/carousel.tsx +220 -53
- package/src/checkbox.tsx +3 -2
- package/src/code-block.tsx +66 -5
- package/src/collapsible.tsx +4 -2
- package/src/combobox.tsx +4 -3
- package/src/command.tsx +27 -12
- package/src/dialog.tsx +33 -10
- package/src/empty.tsx +4 -4
- package/src/field.tsx +4 -3
- package/src/filter-group.tsx +143 -0
- package/src/icons.tsx +28 -1
- package/src/illustrations.tsx +219 -141
- package/src/index.ts +238 -18
- package/src/input.tsx +8 -5
- package/src/kbd.tsx +10 -4
- package/src/lib/focus.ts +41 -0
- package/src/lib/popup.ts +1 -1
- package/src/lifeline/company-icon.tsx +71 -0
- package/src/lifeline/index.ts +42 -0
- package/src/lifeline/lifeline-data.ts +97 -0
- package/src/lifeline/lifeline-desktop.tsx +204 -0
- package/src/lifeline/lifeline-event.tsx +108 -0
- package/src/lifeline/lifeline-fireworks.tsx +302 -0
- package/src/lifeline/lifeline-hover-image.tsx +269 -0
- package/src/lifeline/lifeline-icons.tsx +39 -0
- package/src/lifeline/lifeline-intro-timing.ts +105 -0
- package/src/lifeline/lifeline-labels.tsx +24 -0
- package/src/lifeline/lifeline-layout.ts +1 -0
- package/src/lifeline/lifeline-legend.tsx +31 -0
- package/src/lifeline/lifeline-lightbox.tsx +309 -0
- package/src/lifeline/lifeline-marker.tsx +183 -0
- package/src/lifeline/lifeline-people.tsx +99 -0
- package/src/lifeline/lifeline-photos.tsx +366 -0
- package/src/lifeline/lifeline-shell.tsx +135 -0
- package/src/lifeline/lifeline-utils.ts +83 -0
- package/src/lifeline/lifeline-vertical.tsx +482 -0
- package/src/lifeline/lifeline.tsx +69 -0
- package/src/lifeline/types.ts +112 -0
- package/src/lifeline/use-lifeline-intro.ts +130 -0
- package/src/lifeline/use-lifeline-scroll.ts +1011 -0
- package/src/lifeline/use-lifeline-vertical-scroll.ts +271 -0
- package/src/menubar.tsx +9 -2
- package/src/minimap.tsx +296 -0
- package/src/modal.tsx +608 -0
- package/src/navigation-menu.tsx +338 -67
- package/src/number-field.tsx +336 -61
- package/src/otp-field.tsx +4 -3
- package/src/pagination.tsx +262 -42
- package/src/password-protection.tsx +345 -0
- package/src/popover.tsx +1 -1
- package/src/progress.tsx +5 -0
- package/src/questionnaire.tsx +284 -0
- package/src/radio.tsx +4 -2
- package/src/scroll-area.tsx +4 -1
- package/src/select.tsx +5 -2
- package/src/sidebar.tsx +113 -28
- package/src/slider.tsx +66 -6
- package/src/sounds.tsx +6 -10
- package/src/spinner.tsx +105 -32
- package/src/switch.tsx +4 -1
- package/src/table.tsx +82 -15
- package/src/tabs.tsx +189 -38
- package/src/text-animate.tsx +71 -28
- package/src/textarea.tsx +6 -1
- package/src/timeline.tsx +378 -0
- package/src/toast.tsx +214 -35
- package/src/toggle.tsx +4 -2
- package/src/toolbar.tsx +12 -7
- package/src/tooltip.tsx +43 -3
- package/src/video-player.tsx +396 -127
- package/src/image-modal.tsx +0 -110
- package/src/markdown-editor.tsx +0 -302
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Questionnaire as BaseQuestionnaire } from "@shadcn/react/questionnaire"
|
|
4
|
+
import type { VariantProps } from "class-variance-authority"
|
|
5
|
+
import type { ComponentProps } from "react"
|
|
6
|
+
import { buttonVariants } from "./button"
|
|
7
|
+
import { inputVariants } from "./input"
|
|
8
|
+
import { cn } from "./lib/cn"
|
|
9
|
+
import { focusRing, focusRingBorder } from "./lib/focus"
|
|
10
|
+
|
|
11
|
+
type StyledProps<T> = Omit<T, "className"> & { className?: string }
|
|
12
|
+
|
|
13
|
+
export type QuestionnaireProps = StyledProps<
|
|
14
|
+
ComponentProps<typeof BaseQuestionnaire.Root>
|
|
15
|
+
>
|
|
16
|
+
export type QuestionnaireProgressProps = StyledProps<
|
|
17
|
+
ComponentProps<typeof BaseQuestionnaire.Progress>
|
|
18
|
+
>
|
|
19
|
+
export type QuestionnaireItemProps = StyledProps<
|
|
20
|
+
ComponentProps<typeof BaseQuestionnaire.Item>
|
|
21
|
+
>
|
|
22
|
+
export type QuestionnaireTitleProps = StyledProps<
|
|
23
|
+
ComponentProps<typeof BaseQuestionnaire.Title>
|
|
24
|
+
>
|
|
25
|
+
export type QuestionnaireDescriptionProps = StyledProps<
|
|
26
|
+
ComponentProps<typeof BaseQuestionnaire.Description>
|
|
27
|
+
>
|
|
28
|
+
export type QuestionnaireChoicesProps = StyledProps<
|
|
29
|
+
ComponentProps<typeof BaseQuestionnaire.Choices>
|
|
30
|
+
>
|
|
31
|
+
export type QuestionnaireChoiceInputProps = StyledProps<
|
|
32
|
+
ComponentProps<typeof BaseQuestionnaire.ChoiceInput>
|
|
33
|
+
>
|
|
34
|
+
export type QuestionnaireChoiceLabelProps = StyledProps<
|
|
35
|
+
ComponentProps<typeof BaseQuestionnaire.ChoiceLabel>
|
|
36
|
+
>
|
|
37
|
+
export type QuestionnaireChoiceShortcutProps = StyledProps<
|
|
38
|
+
ComponentProps<typeof BaseQuestionnaire.ChoiceShortcut>
|
|
39
|
+
>
|
|
40
|
+
export type QuestionnaireChoiceProps = StyledProps<
|
|
41
|
+
ComponentProps<typeof BaseQuestionnaire.Choice>
|
|
42
|
+
> & {
|
|
43
|
+
inputProps?: QuestionnaireChoiceInputProps
|
|
44
|
+
labelProps?: QuestionnaireChoiceLabelProps
|
|
45
|
+
shortcutProps?: QuestionnaireChoiceShortcutProps
|
|
46
|
+
}
|
|
47
|
+
export type QuestionnaireInputProps = StyledProps<
|
|
48
|
+
Omit<ComponentProps<typeof BaseQuestionnaire.Input>, "size">
|
|
49
|
+
> &
|
|
50
|
+
VariantProps<typeof inputVariants>
|
|
51
|
+
export type QuestionnaireErrorProps = StyledProps<
|
|
52
|
+
ComponentProps<typeof BaseQuestionnaire.Error>
|
|
53
|
+
>
|
|
54
|
+
export type QuestionnaireActionsProps = ComponentProps<"div">
|
|
55
|
+
|
|
56
|
+
type QuestionnaireNavigationProps<T> = StyledProps<
|
|
57
|
+
Omit<T, "size" | "variant">
|
|
58
|
+
> &
|
|
59
|
+
VariantProps<typeof buttonVariants>
|
|
60
|
+
|
|
61
|
+
export type QuestionnairePreviousProps = QuestionnaireNavigationProps<
|
|
62
|
+
ComponentProps<typeof BaseQuestionnaire.Previous>
|
|
63
|
+
>
|
|
64
|
+
export type QuestionnaireSkipProps = QuestionnaireNavigationProps<
|
|
65
|
+
ComponentProps<typeof BaseQuestionnaire.Skip>
|
|
66
|
+
>
|
|
67
|
+
export type QuestionnaireNextProps = QuestionnaireNavigationProps<
|
|
68
|
+
ComponentProps<typeof BaseQuestionnaire.Next>
|
|
69
|
+
>
|
|
70
|
+
export type QuestionnaireSubmitProps = QuestionnaireNavigationProps<
|
|
71
|
+
ComponentProps<typeof BaseQuestionnaire.Submit>
|
|
72
|
+
>
|
|
73
|
+
|
|
74
|
+
export const Questionnaire = ({ className, ...props }: QuestionnaireProps) => (
|
|
75
|
+
<BaseQuestionnaire.Root
|
|
76
|
+
className={cn("flex w-full flex-col gap-6", className)}
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
export const QuestionnaireProgress = ({
|
|
82
|
+
className,
|
|
83
|
+
...props
|
|
84
|
+
}: QuestionnaireProgressProps) => (
|
|
85
|
+
<BaseQuestionnaire.Progress
|
|
86
|
+
className={cn("text-sm text-fg-secondary tabular-nums", className)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
export const QuestionnaireItem = ({
|
|
92
|
+
className,
|
|
93
|
+
...props
|
|
94
|
+
}: QuestionnaireItemProps) => (
|
|
95
|
+
<BaseQuestionnaire.Item
|
|
96
|
+
className={cn(
|
|
97
|
+
"m-0 min-w-0 border-0 p-0",
|
|
98
|
+
focusRingBorder,
|
|
99
|
+
focusRing,
|
|
100
|
+
className,
|
|
101
|
+
)}
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
export const QuestionnaireTitle = ({
|
|
107
|
+
className,
|
|
108
|
+
...props
|
|
109
|
+
}: QuestionnaireTitleProps) => (
|
|
110
|
+
<BaseQuestionnaire.Title
|
|
111
|
+
className={cn("heading-sm text-fg-primary", className)}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
export const QuestionnaireDescription = ({
|
|
117
|
+
className,
|
|
118
|
+
...props
|
|
119
|
+
}: QuestionnaireDescriptionProps) => (
|
|
120
|
+
<BaseQuestionnaire.Description
|
|
121
|
+
className={cn("text-sm mt-1 text-fg-secondary", className)}
|
|
122
|
+
{...props}
|
|
123
|
+
/>
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
export const QuestionnaireChoices = ({
|
|
127
|
+
className,
|
|
128
|
+
...props
|
|
129
|
+
}: QuestionnaireChoicesProps) => (
|
|
130
|
+
<BaseQuestionnaire.Choices
|
|
131
|
+
className={cn("mt-5 grid gap-2", className)}
|
|
132
|
+
{...props}
|
|
133
|
+
/>
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
export const QuestionnaireChoiceInput = ({
|
|
137
|
+
className,
|
|
138
|
+
...props
|
|
139
|
+
}: QuestionnaireChoiceInputProps) => (
|
|
140
|
+
<BaseQuestionnaire.ChoiceInput
|
|
141
|
+
className={cn(
|
|
142
|
+
"mt-0.5 size-4 shrink-0 cursor-pointer accent-brand-primary disabled:cursor-not-allowed",
|
|
143
|
+
focusRingBorder,
|
|
144
|
+
focusRing,
|
|
145
|
+
className,
|
|
146
|
+
)}
|
|
147
|
+
{...props}
|
|
148
|
+
/>
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
export const QuestionnaireChoiceLabel = ({
|
|
152
|
+
className,
|
|
153
|
+
...props
|
|
154
|
+
}: QuestionnaireChoiceLabelProps) => (
|
|
155
|
+
<BaseQuestionnaire.ChoiceLabel
|
|
156
|
+
className={cn("text-sm min-w-0 text-fg-primary", className)}
|
|
157
|
+
{...props}
|
|
158
|
+
/>
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
export const QuestionnaireChoiceShortcut = ({
|
|
162
|
+
className,
|
|
163
|
+
...props
|
|
164
|
+
}: QuestionnaireChoiceShortcutProps) => (
|
|
165
|
+
<BaseQuestionnaire.ChoiceShortcut
|
|
166
|
+
className={cn(
|
|
167
|
+
"text-xs flex min-w-5 items-center justify-center rounded border border-border-secondary bg-background-secondary px-1 py-0.5 text-fg-tertiary",
|
|
168
|
+
className,
|
|
169
|
+
)}
|
|
170
|
+
{...props}
|
|
171
|
+
/>
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
export const QuestionnaireChoice = ({
|
|
175
|
+
className,
|
|
176
|
+
children,
|
|
177
|
+
inputProps,
|
|
178
|
+
labelProps,
|
|
179
|
+
shortcutProps,
|
|
180
|
+
...props
|
|
181
|
+
}: QuestionnaireChoiceProps) => (
|
|
182
|
+
<BaseQuestionnaire.Choice
|
|
183
|
+
className={cn(
|
|
184
|
+
"group grid cursor-pointer grid-cols-[auto_minmax(0,1fr)_auto] items-start gap-3 rounded-lg border border-border-secondary bg-surface px-3.5 py-3 text-fg-primary outline-none transition-[background-color,border-color,box-shadow] duration-[var(--duration-sm)] ease-enter hover:bg-background-secondary has-[:focus-visible]:border-ring has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-offset-1 has-[:focus-visible]:ring-offset-background-primary has-[:focus-visible]:ring-ring/20 data-checked:border-brand-primary data-checked:bg-background-secondary data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
185
|
+
className,
|
|
186
|
+
)}
|
|
187
|
+
{...props}
|
|
188
|
+
>
|
|
189
|
+
<QuestionnaireChoiceInput {...inputProps} />
|
|
190
|
+
<QuestionnaireChoiceLabel {...labelProps}>
|
|
191
|
+
{children}
|
|
192
|
+
</QuestionnaireChoiceLabel>
|
|
193
|
+
<QuestionnaireChoiceShortcut {...shortcutProps} />
|
|
194
|
+
</BaseQuestionnaire.Choice>
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
export const QuestionnaireInput = ({
|
|
198
|
+
className,
|
|
199
|
+
variant,
|
|
200
|
+
size,
|
|
201
|
+
invalid,
|
|
202
|
+
...props
|
|
203
|
+
}: QuestionnaireInputProps) => (
|
|
204
|
+
<BaseQuestionnaire.Input
|
|
205
|
+
className={cn(inputVariants({ variant, size, invalid }), "mt-5", className)}
|
|
206
|
+
{...props}
|
|
207
|
+
/>
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
export const QuestionnaireError = ({
|
|
211
|
+
className,
|
|
212
|
+
...props
|
|
213
|
+
}: QuestionnaireErrorProps) => (
|
|
214
|
+
<BaseQuestionnaire.Error
|
|
215
|
+
className={cn("text-sm mt-2 text-destructive", className)}
|
|
216
|
+
{...props}
|
|
217
|
+
/>
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
export const QuestionnaireActions = ({
|
|
221
|
+
className,
|
|
222
|
+
...props
|
|
223
|
+
}: QuestionnaireActionsProps) => (
|
|
224
|
+
<div
|
|
225
|
+
className={cn("flex min-h-9 items-center justify-end gap-2", className)}
|
|
226
|
+
{...props}
|
|
227
|
+
/>
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
export const QuestionnairePrevious = ({
|
|
231
|
+
className,
|
|
232
|
+
variant = "outline",
|
|
233
|
+
size,
|
|
234
|
+
...props
|
|
235
|
+
}: QuestionnairePreviousProps) => (
|
|
236
|
+
<BaseQuestionnaire.Previous
|
|
237
|
+
className={cn(buttonVariants({ variant, size }), "mr-auto", className)}
|
|
238
|
+
{...props}
|
|
239
|
+
/>
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
export const QuestionnaireSkip = ({
|
|
243
|
+
className,
|
|
244
|
+
variant = "ghost",
|
|
245
|
+
size,
|
|
246
|
+
...props
|
|
247
|
+
}: QuestionnaireSkipProps) => (
|
|
248
|
+
<BaseQuestionnaire.Skip
|
|
249
|
+
className={cn(buttonVariants({ variant, size }), className)}
|
|
250
|
+
{...props}
|
|
251
|
+
/>
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
export const QuestionnaireNext = ({
|
|
255
|
+
className,
|
|
256
|
+
variant = "primary",
|
|
257
|
+
size,
|
|
258
|
+
...props
|
|
259
|
+
}: QuestionnaireNextProps) => (
|
|
260
|
+
<BaseQuestionnaire.Next
|
|
261
|
+
className={cn(buttonVariants({ variant, size }), className)}
|
|
262
|
+
{...props}
|
|
263
|
+
/>
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
export const QuestionnaireSubmit = ({
|
|
267
|
+
className,
|
|
268
|
+
variant = "primary",
|
|
269
|
+
size,
|
|
270
|
+
...props
|
|
271
|
+
}: QuestionnaireSubmitProps) => (
|
|
272
|
+
<BaseQuestionnaire.Submit
|
|
273
|
+
className={cn(buttonVariants({ variant, size }), className)}
|
|
274
|
+
{...props}
|
|
275
|
+
/>
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
export type {
|
|
279
|
+
QuestionnaireChoiceDefinition,
|
|
280
|
+
QuestionnaireInputType,
|
|
281
|
+
QuestionnaireItemDefinition,
|
|
282
|
+
QuestionnaireItemStatus,
|
|
283
|
+
QuestionnaireShortcutMode,
|
|
284
|
+
} from "@shadcn/react/questionnaire"
|
package/src/radio.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { Radio as BaseRadio } from "@base-ui/react/radio"
|
|
|
4
4
|
import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group"
|
|
5
5
|
import type { ComponentProps } from "react"
|
|
6
6
|
import { cn } from "./lib/cn"
|
|
7
|
+
import { focusRing } from "./lib/focus"
|
|
7
8
|
import { motion } from "./lib/motion"
|
|
8
9
|
|
|
9
10
|
export type RadioGroupProps = ComponentProps<typeof BaseRadioGroup>
|
|
@@ -20,9 +21,10 @@ export const RadioGroup = ({ className, ...props }: RadioGroupProps) => (
|
|
|
20
21
|
export const Radio = ({ className, ...props }: RadioProps) => (
|
|
21
22
|
<BaseRadio.Root
|
|
22
23
|
className={cn(
|
|
23
|
-
"flex size-4 shrink-0 items-center justify-center rounded-full border border-border-secondary bg-surface
|
|
24
|
+
"flex size-4 shrink-0 items-center justify-center rounded-full border border-border-secondary bg-surface",
|
|
24
25
|
motion.colors,
|
|
25
|
-
|
|
26
|
+
focusRing,
|
|
27
|
+
"data-checked:border-brand-primary data-checked:bg-brand-primary data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
26
28
|
className,
|
|
27
29
|
)}
|
|
28
30
|
{...props}
|
package/src/scroll-area.tsx
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area"
|
|
4
4
|
import type { ComponentProps } from "react"
|
|
5
5
|
import { cn } from "./lib/cn"
|
|
6
|
+
import { focusRing, focusRingBorder } from "./lib/focus"
|
|
6
7
|
|
|
7
8
|
export type ScrollAreaProps = ComponentProps<typeof BaseScrollArea.Root>
|
|
8
9
|
export type ScrollAreaViewportProps = ComponentProps<
|
|
@@ -29,7 +30,9 @@ export const ScrollAreaViewport = ({
|
|
|
29
30
|
}: ScrollAreaViewportProps) => (
|
|
30
31
|
<BaseScrollArea.Viewport
|
|
31
32
|
className={cn(
|
|
32
|
-
"size-full rounded-[inherit]
|
|
33
|
+
"size-full rounded-[inherit]",
|
|
34
|
+
focusRingBorder,
|
|
35
|
+
focusRing,
|
|
33
36
|
className,
|
|
34
37
|
)}
|
|
35
38
|
{...props}
|
package/src/select.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { Select as BaseSelect } from "@base-ui/react/select"
|
|
|
4
4
|
import type { ComponentProps } from "react"
|
|
5
5
|
import { IconChevronDownSmall } from "./icons"
|
|
6
6
|
import { cn } from "./lib/cn"
|
|
7
|
+
import { focusRing, focusRingInvalid } from "./lib/focus"
|
|
7
8
|
import { motion } from "./lib/motion"
|
|
8
9
|
import { popupInset, popupItem, popupLabel, popupSurface } from "./lib/popup"
|
|
9
10
|
|
|
@@ -32,9 +33,11 @@ export const SelectTrigger = ({
|
|
|
32
33
|
}: SelectTriggerProps) => (
|
|
33
34
|
<BaseSelect.Trigger
|
|
34
35
|
className={cn(
|
|
35
|
-
"flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border border-border-secondary bg-surface px-3 text-sm text-fg-primary inset-shadow-outline-top
|
|
36
|
+
"flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border border-border-secondary bg-surface px-3 text-sm text-fg-primary inset-shadow-outline-top",
|
|
36
37
|
motion.all,
|
|
37
|
-
|
|
38
|
+
focusRing,
|
|
39
|
+
focusRingInvalid,
|
|
40
|
+
"data-disabled:cursor-not-allowed data-disabled:opacity-50 data-placeholder:text-fg-quaternary data-popup-open:border-border-secondary",
|
|
38
41
|
className,
|
|
39
42
|
)}
|
|
40
43
|
{...props}
|
package/src/sidebar.tsx
CHANGED
|
@@ -1,56 +1,119 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
import type { ComponentProps } from "react"
|
|
3
|
+
import { cn } from "./lib/cn"
|
|
4
|
+
import { focusRing } from "./lib/focus"
|
|
5
|
+
import { motion } from "./lib/motion"
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
const sidebarVariants = cva(
|
|
8
|
+
"flex h-full shrink-0 flex-col overflow-hidden text-fg-primary",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "border-r border-border-primary bg-surface",
|
|
13
|
+
inset: "rounded-lg bg-background-secondary",
|
|
14
|
+
floating:
|
|
15
|
+
"rounded-xl border border-border-primary bg-surface-raised shadow-sm",
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
sm: "w-52",
|
|
19
|
+
md: "w-60",
|
|
20
|
+
lg: "w-72",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: "default",
|
|
25
|
+
size: "md",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
)
|
|
15
29
|
|
|
16
|
-
|
|
30
|
+
const sidebarNavItemVariants = cva(
|
|
31
|
+
cn(
|
|
32
|
+
"group/nav-item relative flex w-full cursor-pointer items-center gap-2 border border-transparent text-left text-fg-secondary disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0",
|
|
33
|
+
focusRing,
|
|
34
|
+
),
|
|
35
|
+
{
|
|
36
|
+
variants: {
|
|
37
|
+
variant: {
|
|
38
|
+
default:
|
|
39
|
+
"rounded-md hover:bg-background-tertiary hover:text-fg-primary data-[active]:bg-background-tertiary data-[active]:font-medium data-[active]:text-fg-primary",
|
|
40
|
+
pill: "rounded-full hover:bg-background-tertiary hover:text-fg-primary data-[active]:border-brand-primary-border data-[active]:bg-brand-primary data-[active]:font-medium data-[active]:text-brand-foreground",
|
|
41
|
+
indicator:
|
|
42
|
+
"rounded-md before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-transparent before:content-[''] hover:bg-background-tertiary hover:text-fg-primary data-[active]:bg-background-tertiary data-[active]:font-medium data-[active]:text-fg-primary data-[active]:before:bg-brand-primary",
|
|
43
|
+
},
|
|
44
|
+
size: {
|
|
45
|
+
sm: "h-8 px-2.5 text-xs",
|
|
46
|
+
md: "h-9 px-3 text-sm",
|
|
47
|
+
lg: "h-10 px-3.5 text-sm",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
defaultVariants: {
|
|
51
|
+
variant: "default",
|
|
52
|
+
size: "md",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
export type SidebarProps = Omit<ComponentProps<"aside">, "size"> &
|
|
58
|
+
VariantProps<typeof sidebarVariants>
|
|
59
|
+
export type SidebarHeaderProps = ComponentProps<"div">
|
|
60
|
+
export type SidebarContentProps = ComponentProps<"div">
|
|
61
|
+
export type SidebarFooterProps = ComponentProps<"div">
|
|
62
|
+
export type SidebarNavProps = ComponentProps<"nav">
|
|
63
|
+
export type SidebarNavItemProps = Omit<ComponentProps<"button">, "size"> &
|
|
64
|
+
VariantProps<typeof sidebarNavItemVariants> & {
|
|
65
|
+
active?: boolean
|
|
66
|
+
}
|
|
67
|
+
export type SidebarNavItemLabelProps = ComponentProps<"span">
|
|
68
|
+
export type SidebarNavBadgeProps = ComponentProps<"span">
|
|
69
|
+
export type SidebarGroupProps = ComponentProps<"div">
|
|
70
|
+
export type SidebarGroupLabelProps = ComponentProps<"h3">
|
|
71
|
+
|
|
72
|
+
export const Sidebar = ({
|
|
73
|
+
className,
|
|
74
|
+
variant,
|
|
75
|
+
size,
|
|
76
|
+
...props
|
|
77
|
+
}: SidebarProps) => (
|
|
17
78
|
<aside
|
|
18
|
-
className={cn(
|
|
19
|
-
"flex h-full w-60 shrink-0 flex-col border-r border-border-primary bg-surface",
|
|
20
|
-
className,
|
|
21
|
-
)}
|
|
79
|
+
className={cn(sidebarVariants({ variant, size }), className)}
|
|
22
80
|
{...props}
|
|
23
81
|
/>
|
|
24
|
-
)
|
|
82
|
+
)
|
|
25
83
|
|
|
26
84
|
export const SidebarHeader = ({ className, ...props }: SidebarHeaderProps) => (
|
|
27
85
|
<div
|
|
28
86
|
className={cn("border-b border-border-primary p-4", className)}
|
|
29
87
|
{...props}
|
|
30
88
|
/>
|
|
31
|
-
)
|
|
89
|
+
)
|
|
32
90
|
|
|
33
91
|
export const SidebarContent = ({
|
|
34
92
|
className,
|
|
35
93
|
...props
|
|
36
94
|
}: SidebarContentProps) => (
|
|
37
|
-
<div
|
|
38
|
-
)
|
|
95
|
+
<div
|
|
96
|
+
className={cn("min-h-0 flex-1 overflow-y-auto p-3", className)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
39
100
|
|
|
40
101
|
export const SidebarFooter = ({ className, ...props }: SidebarFooterProps) => (
|
|
41
102
|
<div
|
|
42
103
|
className={cn("border-t border-border-primary p-3", className)}
|
|
43
104
|
{...props}
|
|
44
105
|
/>
|
|
45
|
-
)
|
|
106
|
+
)
|
|
46
107
|
|
|
47
108
|
export const SidebarNav = ({ className, ...props }: SidebarNavProps) => (
|
|
48
109
|
<nav className={cn("flex flex-col gap-1", className)} {...props} />
|
|
49
|
-
)
|
|
110
|
+
)
|
|
50
111
|
|
|
51
112
|
export const SidebarNavItem = ({
|
|
52
113
|
className,
|
|
53
114
|
active = false,
|
|
115
|
+
variant,
|
|
116
|
+
size,
|
|
54
117
|
type = "button",
|
|
55
118
|
...props
|
|
56
119
|
}: SidebarNavItemProps) => (
|
|
@@ -59,17 +122,37 @@ export const SidebarNavItem = ({
|
|
|
59
122
|
data-active={active || undefined}
|
|
60
123
|
aria-current={active ? "page" : undefined}
|
|
61
124
|
className={cn(
|
|
62
|
-
|
|
125
|
+
sidebarNavItemVariants({ variant, size }),
|
|
63
126
|
motion.colors,
|
|
64
127
|
className,
|
|
65
128
|
)}
|
|
66
129
|
{...props}
|
|
67
130
|
/>
|
|
68
|
-
)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
export const SidebarNavItemLabel = ({
|
|
134
|
+
className,
|
|
135
|
+
...props
|
|
136
|
+
}: SidebarNavItemLabelProps) => (
|
|
137
|
+
<span className={cn("min-w-0 flex-1 truncate", className)} {...props} />
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
export const SidebarNavBadge = ({
|
|
141
|
+
className,
|
|
142
|
+
...props
|
|
143
|
+
}: SidebarNavBadgeProps) => (
|
|
144
|
+
<span
|
|
145
|
+
className={cn(
|
|
146
|
+
"text-2xs-strong ml-auto inline-flex min-w-5 shrink-0 items-center justify-center rounded-full border border-border-primary bg-surface px-1.5 py-0.5 text-fg-secondary",
|
|
147
|
+
className,
|
|
148
|
+
)}
|
|
149
|
+
{...props}
|
|
150
|
+
/>
|
|
151
|
+
)
|
|
69
152
|
|
|
70
153
|
export const SidebarGroup = ({ className, ...props }: SidebarGroupProps) => (
|
|
71
154
|
<div className={cn("flex flex-col gap-1 py-2", className)} {...props} />
|
|
72
|
-
)
|
|
155
|
+
)
|
|
73
156
|
|
|
74
157
|
export const SidebarGroupLabel = ({
|
|
75
158
|
className,
|
|
@@ -79,4 +162,6 @@ export const SidebarGroupLabel = ({
|
|
|
79
162
|
className={cn("px-3 py-1.5 text-xs-strong text-fg-tertiary", className)}
|
|
80
163
|
{...props}
|
|
81
164
|
/>
|
|
82
|
-
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
export { sidebarNavItemVariants, sidebarVariants }
|
package/src/slider.tsx
CHANGED
|
@@ -1,21 +1,52 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import { Slider as BaseSlider } from "@base-ui/react/slider"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
5
|
import type { ComponentProps } from "react"
|
|
5
6
|
import { cn } from "./lib/cn"
|
|
7
|
+
import { focusRing } from "./lib/focus"
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
const sliderVariants = cva(
|
|
10
|
+
"group/slider relative flex w-full data-disabled:opacity-50 data-[orientation=vertical]:h-48 data-[orientation=vertical]:w-fit",
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
size: {
|
|
14
|
+
sm: "[--slider-thumb-size:0.875rem] [--slider-track-size:0.25rem]",
|
|
15
|
+
md: "[--slider-thumb-size:1rem] [--slider-track-size:0.375rem]",
|
|
16
|
+
lg: "[--slider-thumb-size:1.25rem] [--slider-track-size:0.5rem]",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
size: "md",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
export type SliderProps = Omit<
|
|
26
|
+
ComponentProps<typeof BaseSlider.Root>,
|
|
27
|
+
"size"
|
|
28
|
+
> &
|
|
29
|
+
VariantProps<typeof sliderVariants>
|
|
8
30
|
export type SliderControlProps = ComponentProps<typeof BaseSlider.Control>
|
|
9
31
|
export type SliderTrackProps = ComponentProps<typeof BaseSlider.Track>
|
|
10
32
|
export type SliderIndicatorProps = ComponentProps<typeof BaseSlider.Indicator>
|
|
11
33
|
export type SliderThumbProps = ComponentProps<typeof BaseSlider.Thumb>
|
|
34
|
+
export type SliderTicksProps = ComponentProps<"div"> & {
|
|
35
|
+
/** Number of evenly spaced marks, including both ends. */
|
|
36
|
+
count?: number
|
|
37
|
+
}
|
|
12
38
|
|
|
13
|
-
export const Slider = (props: SliderProps) =>
|
|
39
|
+
export const Slider = ({ className, size, ...props }: SliderProps) => (
|
|
40
|
+
<BaseSlider.Root
|
|
41
|
+
className={cn(sliderVariants({ size }), className)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
14
45
|
|
|
15
46
|
export const SliderControl = ({ className, ...props }: SliderControlProps) => (
|
|
16
47
|
<BaseSlider.Control
|
|
17
48
|
className={cn(
|
|
18
|
-
"flex w-full touch-none items-center py-3 select-none",
|
|
49
|
+
"flex w-full touch-none items-center py-3 select-none data-disabled:cursor-not-allowed data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:px-3 data-[orientation=vertical]:py-0",
|
|
19
50
|
className,
|
|
20
51
|
)}
|
|
21
52
|
{...props}
|
|
@@ -25,7 +56,7 @@ export const SliderControl = ({ className, ...props }: SliderControlProps) => (
|
|
|
25
56
|
export const SliderTrack = ({ className, ...props }: SliderTrackProps) => (
|
|
26
57
|
<BaseSlider.Track
|
|
27
58
|
className={cn(
|
|
28
|
-
"relative h-
|
|
59
|
+
"relative h-[var(--slider-track-size)] w-full rounded-full bg-background-quaternary transition-colors duration-[var(--duration-sm)] group-hover/slider:bg-background-active data-[orientation=vertical]:h-full data-[orientation=vertical]:w-[var(--slider-track-size)]",
|
|
29
60
|
className,
|
|
30
61
|
)}
|
|
31
62
|
{...props}
|
|
@@ -38,7 +69,7 @@ export const SliderIndicator = ({
|
|
|
38
69
|
}: SliderIndicatorProps) => (
|
|
39
70
|
<BaseSlider.Indicator
|
|
40
71
|
className={cn(
|
|
41
|
-
"absolute h-full rounded-full bg-brand-primary
|
|
72
|
+
"absolute h-full rounded-full bg-brand-primary data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-full",
|
|
42
73
|
className,
|
|
43
74
|
)}
|
|
44
75
|
{...props}
|
|
@@ -48,9 +79,38 @@ export const SliderIndicator = ({
|
|
|
48
79
|
export const SliderThumb = ({ className, ...props }: SliderThumbProps) => (
|
|
49
80
|
<BaseSlider.Thumb
|
|
50
81
|
className={cn(
|
|
51
|
-
"size-
|
|
82
|
+
"flex size-[var(--slider-thumb-size)] cursor-grab items-center justify-center rounded-full border border-brand-primary-border bg-surface shadow-sm transition-[scale,box-shadow,background-color,border-color] duration-[var(--duration-sm)] ease-enter after:size-1 after:rounded-full after:bg-brand-primary after:content-[''] hover:scale-110 hover:bg-background-secondary active:scale-105 data-dragging:cursor-grabbing data-dragging:scale-110 data-disabled:cursor-not-allowed data-disabled:hover:scale-100",
|
|
83
|
+
focusRing,
|
|
52
84
|
className,
|
|
53
85
|
)}
|
|
54
86
|
{...props}
|
|
55
87
|
/>
|
|
56
88
|
)
|
|
89
|
+
|
|
90
|
+
export const SliderTicks = ({
|
|
91
|
+
count = 5,
|
|
92
|
+
className,
|
|
93
|
+
...props
|
|
94
|
+
}: SliderTicksProps) => {
|
|
95
|
+
const tickCount = Number.isFinite(count) ? Math.max(2, Math.floor(count)) : 2
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div
|
|
99
|
+
aria-hidden
|
|
100
|
+
className={cn(
|
|
101
|
+
"pointer-events-none absolute inset-0 flex items-center justify-between group-data-[orientation=vertical]/slider:flex-col",
|
|
102
|
+
className,
|
|
103
|
+
)}
|
|
104
|
+
{...props}
|
|
105
|
+
>
|
|
106
|
+
{Array.from({ length: tickCount }, (_, index) => (
|
|
107
|
+
<span
|
|
108
|
+
key={index}
|
|
109
|
+
className="h-2 w-px rounded-full bg-surface/70 group-data-[orientation=vertical]/slider:h-px group-data-[orientation=vertical]/slider:w-2"
|
|
110
|
+
/>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { sliderVariants }
|