@boyernick/standard-ui-react 0.1.1-canary.2 → 0.1.1-canary.22

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 (56) hide show
  1. package/package.json +5 -3
  2. package/src/accordion.tsx +1 -1
  3. package/src/alert-dialog.tsx +1 -1
  4. package/src/autocomplete.tsx +12 -11
  5. package/src/badge.tsx +73 -9
  6. package/src/brand.tsx +2 -2
  7. package/src/breadcrumb.tsx +38 -20
  8. package/src/button.tsx +2 -2
  9. package/src/calendar.tsx +22 -11
  10. package/src/card.tsx +57 -14
  11. package/src/carousel.tsx +163 -6
  12. package/src/checkbox.tsx +35 -13
  13. package/src/collapsible.tsx +4 -2
  14. package/src/combobox.tsx +13 -12
  15. package/src/command.tsx +38 -14
  16. package/src/context-menu.tsx +6 -3
  17. package/src/date-picker.tsx +174 -0
  18. package/src/dialog.tsx +33 -10
  19. package/src/drawer.tsx +1 -1
  20. package/src/empty.tsx +4 -4
  21. package/src/field.tsx +1 -1
  22. package/src/filter-group.tsx +139 -0
  23. package/src/icons.tsx +39 -0
  24. package/src/illustrations.tsx +219 -141
  25. package/src/image-modal.tsx +440 -49
  26. package/src/index.ts +188 -0
  27. package/src/input.tsx +1 -1
  28. package/src/kbd.tsx +49 -0
  29. package/src/lib/motion.ts +128 -18
  30. package/src/lib/popup.ts +45 -0
  31. package/src/menu.tsx +7 -4
  32. package/src/menubar.tsx +5 -0
  33. package/src/meter.tsx +1 -1
  34. package/src/minimap.tsx +267 -0
  35. package/src/navigation-menu.tsx +336 -67
  36. package/src/number-field.tsx +327 -61
  37. package/src/pagination.tsx +258 -42
  38. package/src/popover.tsx +3 -1
  39. package/src/preview-card.tsx +3 -1
  40. package/src/progress.tsx +6 -1
  41. package/src/questionnaire.tsx +279 -0
  42. package/src/scroll-area.tsx +1 -1
  43. package/src/select.tsx +8 -6
  44. package/src/sidebar.tsx +109 -28
  45. package/src/slider.tsx +64 -6
  46. package/src/sounds.tsx +6 -10
  47. package/src/spinner.tsx +105 -32
  48. package/src/switch.tsx +2 -2
  49. package/src/table.tsx +82 -15
  50. package/src/tabs.tsx +184 -38
  51. package/src/text-animate.tsx +71 -28
  52. package/src/textarea.tsx +1 -1
  53. package/src/timeline.tsx +321 -0
  54. package/src/toast.tsx +156 -23
  55. package/src/tooltip.tsx +43 -3
  56. package/src/video-player.tsx +296 -120
@@ -1,17 +1,89 @@
1
- import type { ComponentProps } from "react";
2
- import { IconChevronRightSmall } from "./icons";
3
- import { cn } from "./lib/cn";
4
- import { motion } from "./lib/motion";
5
-
6
- export type PaginationProps = ComponentProps<"nav">;
7
- export type PaginationContentProps = ComponentProps<"ul">;
8
- export type PaginationItemProps = ComponentProps<"li">;
9
- export type PaginationLinkProps = ComponentProps<"button"> & {
10
- active?: boolean;
11
- };
12
- export type PaginationPreviousProps = PaginationLinkProps;
13
- export type PaginationNextProps = PaginationLinkProps;
14
- export type PaginationEllipsisProps = ComponentProps<"span">;
1
+ "use client"
2
+
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+ import type { ComponentProps } from "react"
5
+ import { IconChevronRightSmall } from "./icons"
6
+ import { cn } from "./lib/cn"
7
+ import { motion } from "./lib/motion"
8
+
9
+ const paginationLinkVariants = cva(
10
+ "inline-flex cursor-pointer items-center justify-center rounded-md border border-transparent text-fg-secondary outline-none hover:bg-background-tertiary hover:text-fg-primary focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20 aria-disabled:pointer-events-none aria-disabled:opacity-50 disabled:cursor-not-allowed disabled:opacity-50 data-[active]:border-border-primary data-[active]:bg-surface data-[active]:text-fg-primary [&_svg]:size-4 [&_svg]:shrink-0",
11
+ {
12
+ variants: {
13
+ size: {
14
+ sm: "size-8 text-xs",
15
+ md: "size-9 text-sm",
16
+ lg: "size-10 text-sm",
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ size: "md",
21
+ },
22
+ },
23
+ )
24
+
25
+ const paginationDirectionVariants = cva("", {
26
+ variants: {
27
+ size: {
28
+ sm: "",
29
+ md: "",
30
+ lg: "",
31
+ },
32
+ iconOnly: {
33
+ true: "",
34
+ false: "w-auto gap-1",
35
+ },
36
+ },
37
+ compoundVariants: [
38
+ { size: "sm", iconOnly: false, class: "px-2.5" },
39
+ { size: "md", iconOnly: false, class: "px-3" },
40
+ { size: "lg", iconOnly: false, class: "px-3.5" },
41
+ ],
42
+ defaultVariants: {
43
+ size: "md",
44
+ iconOnly: false,
45
+ },
46
+ })
47
+
48
+ export type PaginationSize = NonNullable<
49
+ VariantProps<typeof paginationLinkVariants>["size"]
50
+ >
51
+
52
+ type PaginationLinkCommonProps = VariantProps<typeof paginationLinkVariants> & {
53
+ active?: boolean
54
+ }
55
+
56
+ export type PaginationButtonProps = Omit<ComponentProps<"button">, "size"> &
57
+ PaginationLinkCommonProps & {
58
+ href?: never
59
+ }
60
+ export type PaginationAnchorProps = Omit<ComponentProps<"a">, "size"> &
61
+ PaginationLinkCommonProps & {
62
+ href: string
63
+ disabled?: boolean
64
+ }
65
+ export type PaginationLinkProps =
66
+ | PaginationButtonProps
67
+ | PaginationAnchorProps
68
+ export type PaginationProps = ComponentProps<"nav">
69
+ export type PaginationContentProps = ComponentProps<"ul">
70
+ export type PaginationItemProps = ComponentProps<"li">
71
+ export type PaginationPreviousProps = PaginationLinkProps & {
72
+ iconOnly?: boolean
73
+ }
74
+ export type PaginationNextProps = PaginationPreviousProps
75
+ export type PaginationFirstProps = PaginationPreviousProps
76
+ export type PaginationLastProps = PaginationPreviousProps
77
+ export type PaginationEllipsisProps = ComponentProps<"span">
78
+ export type PaginationStatusProps = ComponentProps<"span"> & {
79
+ page: number
80
+ totalPages: number
81
+ }
82
+ export type PaginationRangeProps = ComponentProps<"span"> & {
83
+ start: number
84
+ end: number
85
+ total: number
86
+ }
15
87
 
16
88
  export const Pagination = ({ className, ...props }: PaginationProps) => (
17
89
  <nav
@@ -19,60 +91,169 @@ export const Pagination = ({ className, ...props }: PaginationProps) => (
19
91
  className={cn("flex w-full justify-center", className)}
20
92
  {...props}
21
93
  />
22
- );
94
+ )
23
95
 
24
96
  export const PaginationContent = ({
25
97
  className,
26
98
  ...props
27
99
  }: PaginationContentProps) => (
28
100
  <ul className={cn("flex items-center gap-1", className)} {...props} />
29
- );
101
+ )
30
102
 
31
103
  export const PaginationItem = ({
32
104
  className,
33
105
  ...props
34
- }: PaginationItemProps) => <li className={cn("flex", className)} {...props} />;
106
+ }: PaginationItemProps) => (
107
+ <li className={cn("flex items-center", className)} {...props} />
108
+ )
35
109
 
36
- export const PaginationLink = ({
37
- className,
38
- active = false,
39
- type = "button",
40
- ...props
41
- }: PaginationLinkProps) => (
42
- <button
43
- type={type}
44
- aria-current={active ? "page" : undefined}
45
- data-active={active || undefined}
46
- className={cn(
47
- "inline-flex size-9 cursor-pointer items-center justify-center rounded-md border border-transparent text-sm text-fg-secondary outline-none hover:bg-background-tertiary hover:text-fg-primary focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20 disabled:cursor-not-allowed disabled:opacity-50 data-[active]:border-border-primary data-[active]:bg-surface data-[active]:text-fg-primary",
48
- motion.colors,
49
- className,
50
- )}
51
- {...props}
52
- />
53
- );
110
+ export const PaginationLink = (props: PaginationLinkProps) => {
111
+ const { className, active = false, size, ...linkProps } = props
112
+ const classes = cn(
113
+ paginationLinkVariants({ size }),
114
+ motion.colors,
115
+ className,
116
+ )
117
+
118
+ if ("href" in linkProps && typeof linkProps.href === "string") {
119
+ const {
120
+ disabled = false,
121
+ onClick,
122
+ tabIndex,
123
+ ...anchorProps
124
+ } = linkProps as PaginationAnchorProps
125
+
126
+ return (
127
+ <a
128
+ {...anchorProps}
129
+ aria-current={active ? "page" : undefined}
130
+ aria-disabled={disabled || undefined}
131
+ data-active={active || undefined}
132
+ tabIndex={disabled ? -1 : tabIndex}
133
+ className={classes}
134
+ onClick={(event) => {
135
+ if (disabled) {
136
+ event.preventDefault()
137
+ return
138
+ }
139
+ onClick?.(event)
140
+ }}
141
+ />
142
+ )
143
+ }
144
+
145
+ const { type = "button", ...buttonProps } =
146
+ linkProps as PaginationButtonProps
147
+
148
+ return (
149
+ <button
150
+ type={type}
151
+ aria-current={active ? "page" : undefined}
152
+ data-active={active || undefined}
153
+ className={classes}
154
+ {...buttonProps}
155
+ />
156
+ )
157
+ }
158
+
159
+ const DoubleChevron = ({ direction }: { direction: "first" | "last" }) => (
160
+ <span className="flex -space-x-2" aria-hidden>
161
+ <IconChevronRightSmall
162
+ className={direction === "first" ? "rotate-180" : undefined}
163
+ />
164
+ <IconChevronRightSmall
165
+ className={direction === "first" ? "rotate-180" : undefined}
166
+ />
167
+ </span>
168
+ )
54
169
 
55
170
  export const PaginationPrevious = ({
56
171
  children = "Previous",
57
172
  className,
173
+ iconOnly = false,
174
+ size = "md",
175
+ "aria-label": ariaLabel,
58
176
  ...props
59
177
  }: PaginationPreviousProps) => (
60
- <PaginationLink className={cn("w-auto gap-1 px-3", className)} {...props}>
178
+ <PaginationLink
179
+ aria-label={ariaLabel ?? (iconOnly ? "Previous page" : undefined)}
180
+ className={cn(
181
+ paginationDirectionVariants({ size, iconOnly }),
182
+ className,
183
+ )}
184
+ size={size}
185
+ {...props}
186
+ >
61
187
  <IconChevronRightSmall className="rotate-180" aria-hidden />
62
- {children}
188
+ {iconOnly ? null : children}
63
189
  </PaginationLink>
64
- );
190
+ )
65
191
 
66
192
  export const PaginationNext = ({
67
193
  children = "Next",
68
194
  className,
195
+ iconOnly = false,
196
+ size = "md",
197
+ "aria-label": ariaLabel,
69
198
  ...props
70
199
  }: PaginationNextProps) => (
71
- <PaginationLink className={cn("w-auto gap-1 px-3", className)} {...props}>
72
- {children}
200
+ <PaginationLink
201
+ aria-label={ariaLabel ?? (iconOnly ? "Next page" : undefined)}
202
+ className={cn(
203
+ paginationDirectionVariants({ size, iconOnly }),
204
+ className,
205
+ )}
206
+ size={size}
207
+ {...props}
208
+ >
209
+ {iconOnly ? null : children}
73
210
  <IconChevronRightSmall aria-hidden />
74
211
  </PaginationLink>
75
- );
212
+ )
213
+
214
+ export const PaginationFirst = ({
215
+ children = "First",
216
+ className,
217
+ iconOnly = false,
218
+ size = "md",
219
+ "aria-label": ariaLabel,
220
+ ...props
221
+ }: PaginationFirstProps) => (
222
+ <PaginationLink
223
+ aria-label={ariaLabel ?? (iconOnly ? "First page" : undefined)}
224
+ className={cn(
225
+ paginationDirectionVariants({ size, iconOnly }),
226
+ className,
227
+ )}
228
+ size={size}
229
+ {...props}
230
+ >
231
+ <DoubleChevron direction="first" />
232
+ {iconOnly ? null : children}
233
+ </PaginationLink>
234
+ )
235
+
236
+ export const PaginationLast = ({
237
+ children = "Last",
238
+ className,
239
+ iconOnly = false,
240
+ size = "md",
241
+ "aria-label": ariaLabel,
242
+ ...props
243
+ }: PaginationLastProps) => (
244
+ <PaginationLink
245
+ aria-label={ariaLabel ?? (iconOnly ? "Last page" : undefined)}
246
+ className={cn(
247
+ paginationDirectionVariants({ size, iconOnly }),
248
+ className,
249
+ )}
250
+ size={size}
251
+ {...props}
252
+ >
253
+ {iconOnly ? null : children}
254
+ <DoubleChevron direction="last" />
255
+ </PaginationLink>
256
+ )
76
257
 
77
258
  export const PaginationEllipsis = ({
78
259
  className,
@@ -88,4 +269,39 @@ export const PaginationEllipsis = ({
88
269
  >
89
270
  …
90
271
  </span>
91
- );
272
+ )
273
+
274
+ export const PaginationStatus = ({
275
+ page,
276
+ totalPages,
277
+ children,
278
+ className,
279
+ ...props
280
+ }: PaginationStatusProps) => (
281
+ <span
282
+ aria-live="polite"
283
+ className={cn("whitespace-nowrap text-sm text-fg-secondary tabular-nums", className)}
284
+ {...props}
285
+ >
286
+ {children ?? `Page ${page} of ${totalPages}`}
287
+ </span>
288
+ )
289
+
290
+ export const PaginationRange = ({
291
+ start,
292
+ end,
293
+ total,
294
+ children,
295
+ className,
296
+ ...props
297
+ }: PaginationRangeProps) => (
298
+ <span
299
+ aria-live="polite"
300
+ className={cn("whitespace-nowrap text-sm text-fg-secondary tabular-nums", className)}
301
+ {...props}
302
+ >
303
+ {children ?? `${start}–${end} of ${total}`}
304
+ </span>
305
+ )
306
+
307
+ export { paginationDirectionVariants, paginationLinkVariants }
package/src/popover.tsx CHANGED
@@ -4,6 +4,7 @@ import { Popover as BasePopover } from "@base-ui/react/popover"
4
4
  import type { ComponentProps } from "react"
5
5
  import { cn } from "./lib/cn"
6
6
  import { motion } from "./lib/motion"
7
+ import { popupSurface } from "./lib/popup"
7
8
 
8
9
  export type PopoverProps = ComponentProps<typeof BasePopover.Root>
9
10
  export type PopoverTriggerProps = ComponentProps<typeof BasePopover.Trigger>
@@ -47,7 +48,8 @@ export const PopoverPositioner = ({
47
48
  export const PopoverPopup = ({ className, ...props }: PopoverPopupProps) => (
48
49
  <BasePopover.Popup
49
50
  className={cn(
50
- "z-50 flex w-72 flex-col gap-1 rounded-xl border border-border-primary bg-surface p-4 shadow-md outline-none",
51
+ "z-50 flex w-72 flex-col gap-0.5 px-4 py-3",
52
+ popupSurface,
51
53
  motion.popupAnchor,
52
54
  className,
53
55
  )}
@@ -4,6 +4,7 @@ import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card"
4
4
  import type { ComponentProps } from "react"
5
5
  import { cn } from "./lib/cn"
6
6
  import { motion } from "./lib/motion"
7
+ import { popupSurface } from "./lib/popup"
7
8
 
8
9
  export type PreviewCardProps = ComponentProps<typeof BasePreviewCard.Root>
9
10
  export type PreviewCardTriggerProps = ComponentProps<
@@ -67,7 +68,8 @@ export const PreviewCardPopup = ({
67
68
  }: PreviewCardPopupProps) => (
68
69
  <BasePreviewCard.Popup
69
70
  className={cn(
70
- "z-50 w-72 overflow-hidden rounded-xl border border-border-primary bg-surface p-4 shadow-md outline-none",
71
+ "z-50 w-72 overflow-hidden p-4",
72
+ popupSurface,
71
73
  motion.popupAnchor,
72
74
  className,
73
75
  )}
package/src/progress.tsx CHANGED
@@ -52,7 +52,12 @@ export const ProgressIndicator = ({
52
52
  }: ProgressIndicatorProps) => (
53
53
  <BaseProgress.Indicator
54
54
  className={cn(
55
- "h-full rounded-full bg-brand-primary transition-[width] duration-300 ease-out motion-reduce:transition-none",
55
+ "h-full rounded-full bg-brand-primary transition-[width] duration-[var(--duration-lg)] ease-enter motion-reduce:transition-none",
56
+ // Base UI flags a null value with data-indeterminate and leaves the
57
+ // indicator full width, so without this the bar reads as complete.
58
+ // A quarter-width stripe crossing the track on the passive curve —
59
+ // ambient, system-initiated movement.
60
+ "data-indeterminate:w-1/4 data-indeterminate:animate-[progress-indeterminate_1.4s_var(--ease-passive)_infinite] motion-reduce:animate-none",
56
61
  className,
57
62
  )}
58
63
  {...props}
@@ -0,0 +1,279 @@
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
+
10
+ type StyledProps<T> = Omit<T, "className"> & { className?: string }
11
+
12
+ export type QuestionnaireProps = StyledProps<
13
+ ComponentProps<typeof BaseQuestionnaire.Root>
14
+ >
15
+ export type QuestionnaireProgressProps = StyledProps<
16
+ ComponentProps<typeof BaseQuestionnaire.Progress>
17
+ >
18
+ export type QuestionnaireItemProps = StyledProps<
19
+ ComponentProps<typeof BaseQuestionnaire.Item>
20
+ >
21
+ export type QuestionnaireTitleProps = StyledProps<
22
+ ComponentProps<typeof BaseQuestionnaire.Title>
23
+ >
24
+ export type QuestionnaireDescriptionProps = StyledProps<
25
+ ComponentProps<typeof BaseQuestionnaire.Description>
26
+ >
27
+ export type QuestionnaireChoicesProps = StyledProps<
28
+ ComponentProps<typeof BaseQuestionnaire.Choices>
29
+ >
30
+ export type QuestionnaireChoiceInputProps = StyledProps<
31
+ ComponentProps<typeof BaseQuestionnaire.ChoiceInput>
32
+ >
33
+ export type QuestionnaireChoiceLabelProps = StyledProps<
34
+ ComponentProps<typeof BaseQuestionnaire.ChoiceLabel>
35
+ >
36
+ export type QuestionnaireChoiceShortcutProps = StyledProps<
37
+ ComponentProps<typeof BaseQuestionnaire.ChoiceShortcut>
38
+ >
39
+ export type QuestionnaireChoiceProps = StyledProps<
40
+ ComponentProps<typeof BaseQuestionnaire.Choice>
41
+ > & {
42
+ inputProps?: QuestionnaireChoiceInputProps
43
+ labelProps?: QuestionnaireChoiceLabelProps
44
+ shortcutProps?: QuestionnaireChoiceShortcutProps
45
+ }
46
+ export type QuestionnaireInputProps = StyledProps<
47
+ Omit<ComponentProps<typeof BaseQuestionnaire.Input>, "size">
48
+ > &
49
+ VariantProps<typeof inputVariants>
50
+ export type QuestionnaireErrorProps = StyledProps<
51
+ ComponentProps<typeof BaseQuestionnaire.Error>
52
+ >
53
+ export type QuestionnaireActionsProps = ComponentProps<"div">
54
+
55
+ type QuestionnaireNavigationProps<T> = StyledProps<
56
+ Omit<T, "size" | "variant">
57
+ > &
58
+ VariantProps<typeof buttonVariants>
59
+
60
+ export type QuestionnairePreviousProps = QuestionnaireNavigationProps<
61
+ ComponentProps<typeof BaseQuestionnaire.Previous>
62
+ >
63
+ export type QuestionnaireSkipProps = QuestionnaireNavigationProps<
64
+ ComponentProps<typeof BaseQuestionnaire.Skip>
65
+ >
66
+ export type QuestionnaireNextProps = QuestionnaireNavigationProps<
67
+ ComponentProps<typeof BaseQuestionnaire.Next>
68
+ >
69
+ export type QuestionnaireSubmitProps = QuestionnaireNavigationProps<
70
+ ComponentProps<typeof BaseQuestionnaire.Submit>
71
+ >
72
+
73
+ export const Questionnaire = ({ className, ...props }: QuestionnaireProps) => (
74
+ <BaseQuestionnaire.Root
75
+ className={cn("flex w-full flex-col gap-6", className)}
76
+ {...props}
77
+ />
78
+ )
79
+
80
+ export const QuestionnaireProgress = ({
81
+ className,
82
+ ...props
83
+ }: QuestionnaireProgressProps) => (
84
+ <BaseQuestionnaire.Progress
85
+ className={cn("text-sm text-fg-secondary tabular-nums", className)}
86
+ {...props}
87
+ />
88
+ )
89
+
90
+ export const QuestionnaireItem = ({
91
+ className,
92
+ ...props
93
+ }: QuestionnaireItemProps) => (
94
+ <BaseQuestionnaire.Item
95
+ className={cn(
96
+ "m-0 min-w-0 border-0 p-0 outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20",
97
+ className,
98
+ )}
99
+ {...props}
100
+ />
101
+ )
102
+
103
+ export const QuestionnaireTitle = ({
104
+ className,
105
+ ...props
106
+ }: QuestionnaireTitleProps) => (
107
+ <BaseQuestionnaire.Title
108
+ className={cn("heading-sm text-fg-primary", className)}
109
+ {...props}
110
+ />
111
+ )
112
+
113
+ export const QuestionnaireDescription = ({
114
+ className,
115
+ ...props
116
+ }: QuestionnaireDescriptionProps) => (
117
+ <BaseQuestionnaire.Description
118
+ className={cn("text-sm mt-1 text-fg-secondary", className)}
119
+ {...props}
120
+ />
121
+ )
122
+
123
+ export const QuestionnaireChoices = ({
124
+ className,
125
+ ...props
126
+ }: QuestionnaireChoicesProps) => (
127
+ <BaseQuestionnaire.Choices
128
+ className={cn("mt-5 grid gap-2", className)}
129
+ {...props}
130
+ />
131
+ )
132
+
133
+ export const QuestionnaireChoiceInput = ({
134
+ className,
135
+ ...props
136
+ }: QuestionnaireChoiceInputProps) => (
137
+ <BaseQuestionnaire.ChoiceInput
138
+ className={cn(
139
+ "mt-0.5 size-4 shrink-0 cursor-pointer accent-brand-primary outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:cursor-not-allowed",
140
+ className,
141
+ )}
142
+ {...props}
143
+ />
144
+ )
145
+
146
+ export const QuestionnaireChoiceLabel = ({
147
+ className,
148
+ ...props
149
+ }: QuestionnaireChoiceLabelProps) => (
150
+ <BaseQuestionnaire.ChoiceLabel
151
+ className={cn("text-sm min-w-0 text-fg-primary", className)}
152
+ {...props}
153
+ />
154
+ )
155
+
156
+ export const QuestionnaireChoiceShortcut = ({
157
+ className,
158
+ ...props
159
+ }: QuestionnaireChoiceShortcutProps) => (
160
+ <BaseQuestionnaire.ChoiceShortcut
161
+ className={cn(
162
+ "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",
163
+ className,
164
+ )}
165
+ {...props}
166
+ />
167
+ )
168
+
169
+ export const QuestionnaireChoice = ({
170
+ className,
171
+ children,
172
+ inputProps,
173
+ labelProps,
174
+ shortcutProps,
175
+ ...props
176
+ }: QuestionnaireChoiceProps) => (
177
+ <BaseQuestionnaire.Choice
178
+ className={cn(
179
+ "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-ring/20 data-checked:border-brand-primary data-checked:bg-background-secondary data-disabled:cursor-not-allowed data-disabled:opacity-50",
180
+ className,
181
+ )}
182
+ {...props}
183
+ >
184
+ <QuestionnaireChoiceInput {...inputProps} />
185
+ <QuestionnaireChoiceLabel {...labelProps}>
186
+ {children}
187
+ </QuestionnaireChoiceLabel>
188
+ <QuestionnaireChoiceShortcut {...shortcutProps} />
189
+ </BaseQuestionnaire.Choice>
190
+ )
191
+
192
+ export const QuestionnaireInput = ({
193
+ className,
194
+ variant,
195
+ size,
196
+ invalid,
197
+ ...props
198
+ }: QuestionnaireInputProps) => (
199
+ <BaseQuestionnaire.Input
200
+ className={cn(inputVariants({ variant, size, invalid }), "mt-5", className)}
201
+ {...props}
202
+ />
203
+ )
204
+
205
+ export const QuestionnaireError = ({
206
+ className,
207
+ ...props
208
+ }: QuestionnaireErrorProps) => (
209
+ <BaseQuestionnaire.Error
210
+ className={cn("text-sm mt-2 text-destructive", className)}
211
+ {...props}
212
+ />
213
+ )
214
+
215
+ export const QuestionnaireActions = ({
216
+ className,
217
+ ...props
218
+ }: QuestionnaireActionsProps) => (
219
+ <div
220
+ className={cn("flex min-h-9 items-center justify-end gap-2", className)}
221
+ {...props}
222
+ />
223
+ )
224
+
225
+ export const QuestionnairePrevious = ({
226
+ className,
227
+ variant = "outline",
228
+ size,
229
+ ...props
230
+ }: QuestionnairePreviousProps) => (
231
+ <BaseQuestionnaire.Previous
232
+ className={cn(buttonVariants({ variant, size }), "mr-auto", className)}
233
+ {...props}
234
+ />
235
+ )
236
+
237
+ export const QuestionnaireSkip = ({
238
+ className,
239
+ variant = "ghost",
240
+ size,
241
+ ...props
242
+ }: QuestionnaireSkipProps) => (
243
+ <BaseQuestionnaire.Skip
244
+ className={cn(buttonVariants({ variant, size }), className)}
245
+ {...props}
246
+ />
247
+ )
248
+
249
+ export const QuestionnaireNext = ({
250
+ className,
251
+ variant = "primary",
252
+ size,
253
+ ...props
254
+ }: QuestionnaireNextProps) => (
255
+ <BaseQuestionnaire.Next
256
+ className={cn(buttonVariants({ variant, size }), className)}
257
+ {...props}
258
+ />
259
+ )
260
+
261
+ export const QuestionnaireSubmit = ({
262
+ className,
263
+ variant = "primary",
264
+ size,
265
+ ...props
266
+ }: QuestionnaireSubmitProps) => (
267
+ <BaseQuestionnaire.Submit
268
+ className={cn(buttonVariants({ variant, size }), className)}
269
+ {...props}
270
+ />
271
+ )
272
+
273
+ export type {
274
+ QuestionnaireChoiceDefinition,
275
+ QuestionnaireInputType,
276
+ QuestionnaireItemDefinition,
277
+ QuestionnaireItemStatus,
278
+ QuestionnaireShortcutMode,
279
+ } from "@shadcn/react/questionnaire"
@@ -49,7 +49,7 @@ export const ScrollAreaScrollbar = ({
49
49
  }: ScrollAreaScrollbarProps) => (
50
50
  <BaseScrollArea.Scrollbar
51
51
  className={cn(
52
- "flex touch-none p-0.5 opacity-100 transition-opacity duration-150 ease-out motion-reduce:transition-none data-[orientation=horizontal]:h-2 data-[orientation=vertical]:w-2",
52
+ "flex touch-none p-0.5 opacity-100 transition-opacity duration-[var(--duration-sm)] ease-enter motion-reduce:transition-none data-[orientation=horizontal]:h-2 data-[orientation=vertical]:w-2",
53
53
  className,
54
54
  )}
55
55
  {...props}