@boyernick/standard-ui-react 0.1.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.
Files changed (67) hide show
  1. package/README.md +9 -0
  2. package/package.json +46 -0
  3. package/src/accordion.tsx +84 -0
  4. package/src/alert-dialog.tsx +101 -0
  5. package/src/attachment.tsx +138 -0
  6. package/src/autocomplete.tsx +281 -0
  7. package/src/avatar.tsx +56 -0
  8. package/src/badge.tsx +28 -0
  9. package/src/brand.tsx +70 -0
  10. package/src/breadcrumb.tsx +81 -0
  11. package/src/button.tsx +129 -0
  12. package/src/calendar.tsx +84 -0
  13. package/src/card.tsx +54 -0
  14. package/src/carousel.tsx +253 -0
  15. package/src/chart.tsx +185 -0
  16. package/src/checkbox-group.tsx +14 -0
  17. package/src/checkbox.tsx +31 -0
  18. package/src/code-block.tsx +124 -0
  19. package/src/collapsible.tsx +61 -0
  20. package/src/combobox.tsx +324 -0
  21. package/src/command.tsx +377 -0
  22. package/src/context-menu.tsx +250 -0
  23. package/src/dialog.tsx +78 -0
  24. package/src/drawer.tsx +156 -0
  25. package/src/empty.tsx +52 -0
  26. package/src/field.tsx +75 -0
  27. package/src/fieldset.tsx +25 -0
  28. package/src/form.tsx +14 -0
  29. package/src/icons.tsx +91 -0
  30. package/src/illustrations.tsx +167 -0
  31. package/src/image-modal.tsx +110 -0
  32. package/src/index.ts +833 -0
  33. package/src/input.tsx +68 -0
  34. package/src/lib/cn.ts +3 -0
  35. package/src/lib/motion.ts +23 -0
  36. package/src/markdown-editor.tsx +302 -0
  37. package/src/menu.tsx +205 -0
  38. package/src/menubar.tsx +22 -0
  39. package/src/meter.tsx +61 -0
  40. package/src/navigation-menu.tsx +217 -0
  41. package/src/number-field.tsx +119 -0
  42. package/src/orb.tsx +33 -0
  43. package/src/otp-field.tsx +45 -0
  44. package/src/pagination.tsx +91 -0
  45. package/src/popover.tsx +92 -0
  46. package/src/preview-card.tsx +103 -0
  47. package/src/progress.tsx +60 -0
  48. package/src/radio.tsx +43 -0
  49. package/src/scroll-area.tsx +67 -0
  50. package/src/select.tsx +161 -0
  51. package/src/separator.tsx +17 -0
  52. package/src/sidebar.tsx +82 -0
  53. package/src/skeleton.tsx +32 -0
  54. package/src/slider.tsx +56 -0
  55. package/src/sounds.tsx +270 -0
  56. package/src/spinner.tsx +45 -0
  57. package/src/switch.tsx +19 -0
  58. package/src/table.tsx +81 -0
  59. package/src/tabs.tsx +62 -0
  60. package/src/text-animate.tsx +155 -0
  61. package/src/textarea.tsx +58 -0
  62. package/src/ticker.tsx +74 -0
  63. package/src/toast.tsx +142 -0
  64. package/src/toggle.tsx +32 -0
  65. package/src/toolbar.tsx +75 -0
  66. package/src/tooltip.tsx +55 -0
  67. package/src/video-player.tsx +241 -0
@@ -0,0 +1,324 @@
1
+ "use client"
2
+
3
+ import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
4
+ import type { ComponentProps, ReactElement } from "react"
5
+ import { IconChevronDownSmall, IconCrossSmall } from "./icons"
6
+ import { cn } from "./lib/cn"
7
+ import { motion } from "./lib/motion"
8
+
9
+ export type ComboboxProps<
10
+ Value,
11
+ Multiple extends boolean | undefined = false,
12
+ > = ComponentProps<typeof BaseCombobox.Root<Value, Multiple>>
13
+ export type ComboboxLabelProps = ComponentProps<typeof BaseCombobox.Label>
14
+ export type ComboboxInputProps = ComponentProps<typeof BaseCombobox.Input>
15
+ export type ComboboxInputGroupProps = ComponentProps<
16
+ typeof BaseCombobox.InputGroup
17
+ >
18
+ export type ComboboxTriggerProps = ComponentProps<typeof BaseCombobox.Trigger>
19
+ export type ComboboxIconProps = ComponentProps<typeof BaseCombobox.Icon>
20
+ export type ComboboxClearProps = ComponentProps<typeof BaseCombobox.Clear>
21
+ export type ComboboxValueProps = ComponentProps<typeof BaseCombobox.Value>
22
+ export type ComboboxPortalProps = ComponentProps<typeof BaseCombobox.Portal>
23
+ export type ComboboxBackdropProps = ComponentProps<typeof BaseCombobox.Backdrop>
24
+ export type ComboboxPositionerProps = ComponentProps<
25
+ typeof BaseCombobox.Positioner
26
+ >
27
+ export type ComboboxPopupProps = ComponentProps<typeof BaseCombobox.Popup>
28
+ export type ComboboxArrowProps = ComponentProps<typeof BaseCombobox.Arrow>
29
+ export type ComboboxListProps = ComponentProps<typeof BaseCombobox.List>
30
+ export type ComboboxItemProps = ComponentProps<typeof BaseCombobox.Item>
31
+ export type ComboboxItemIndicatorProps = ComponentProps<
32
+ typeof BaseCombobox.ItemIndicator
33
+ >
34
+ export type ComboboxEmptyProps = ComponentProps<typeof BaseCombobox.Empty>
35
+ export type ComboboxStatusProps = ComponentProps<typeof BaseCombobox.Status>
36
+ export type ComboboxGroupProps = ComponentProps<typeof BaseCombobox.Group>
37
+ export type ComboboxGroupLabelProps = ComponentProps<
38
+ typeof BaseCombobox.GroupLabel
39
+ >
40
+ export type ComboboxSeparatorProps = ComponentProps<
41
+ typeof BaseCombobox.Separator
42
+ >
43
+ export type ComboboxCollectionProps = ComponentProps<
44
+ typeof BaseCombobox.Collection
45
+ >
46
+ export type ComboboxChipsProps = ComponentProps<typeof BaseCombobox.Chips>
47
+ export type ComboboxChipProps = ComponentProps<typeof BaseCombobox.Chip>
48
+ export type ComboboxChipRemoveProps = ComponentProps<
49
+ typeof BaseCombobox.ChipRemove
50
+ >
51
+ export type ComboboxRowProps = ComponentProps<typeof BaseCombobox.Row>
52
+
53
+ export const Combobox = <
54
+ Value,
55
+ Multiple extends boolean | undefined = false,
56
+ >(
57
+ props: ComboboxProps<Value, Multiple>,
58
+ ): ReactElement => <BaseCombobox.Root {...props} />
59
+
60
+ export const ComboboxLabel = ({ className, ...props }: ComboboxLabelProps) => (
61
+ <BaseCombobox.Label
62
+ className={cn("mb-1.5 block text-sm text-fg-primary", className)}
63
+ {...props}
64
+ />
65
+ )
66
+
67
+ const inputGroupAccessoryClassName = cn(
68
+ "inline-flex size-9 shrink-0 cursor-pointer items-center justify-center text-fg-tertiary outline-none",
69
+ motion.colors,
70
+ "hover:text-fg-primary focus-visible:bg-background-tertiary focus-visible:text-fg-primary focus-visible:outline-none data-disabled:cursor-not-allowed",
71
+ )
72
+
73
+ export const ComboboxInputGroup = ({
74
+ className,
75
+ ...props
76
+ }: ComboboxInputGroupProps) => (
77
+ <BaseCombobox.InputGroup
78
+ className={cn(
79
+ "relative flex min-h-9 w-full items-center rounded-md border border-border-secondary bg-surface inset-shadow-outline-top outline-none transition-[color,box-shadow]",
80
+ "has-[[data-popup-open]]:bg-background-tertiary/60",
81
+ "focus-within:border-ring focus-within:ring-[3px] focus-within:ring-offset-1 focus-within:ring-offset-background-primary focus-within:ring-ring/20",
82
+ "aria-invalid:border-destructive aria-invalid:focus-within:border-destructive aria-invalid:focus-within:ring-destructive/20",
83
+ "has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:focus-within:border-destructive has-[[aria-invalid=true]]:focus-within:ring-destructive/20",
84
+ "has-[:disabled]:opacity-50",
85
+ className,
86
+ )}
87
+ {...props}
88
+ />
89
+ )
90
+
91
+ export const ComboboxInput = ({ className, ...props }: ComboboxInputProps) => (
92
+ <BaseCombobox.Input
93
+ className={cn(
94
+ "h-9 min-w-0 flex-1 cursor-text rounded-md bg-transparent px-3 text-sm text-fg-primary outline-none placeholder:text-fg-quaternary focus-visible:ring-0",
95
+ className,
96
+ )}
97
+ {...props}
98
+ />
99
+ )
100
+
101
+ export const ComboboxTrigger = ({
102
+ className,
103
+ children,
104
+ ...props
105
+ }: ComboboxTriggerProps) => (
106
+ <BaseCombobox.Trigger
107
+ className={cn(inputGroupAccessoryClassName, className)}
108
+ {...props}
109
+ >
110
+ {children ?? <ComboboxIcon />}
111
+ </BaseCombobox.Trigger>
112
+ )
113
+
114
+ export const ComboboxIcon = ({
115
+ className,
116
+ children,
117
+ ...props
118
+ }: ComboboxIconProps) => (
119
+ <BaseCombobox.Icon
120
+ className={cn(
121
+ "flex shrink-0 text-fg-tertiary",
122
+ motion.transform,
123
+ "data-popup-open:rotate-180",
124
+ className,
125
+ )}
126
+ {...props}
127
+ >
128
+ {children ?? <IconChevronDownSmall size={16} className="size-4" aria-hidden />}
129
+ </BaseCombobox.Icon>
130
+ )
131
+
132
+ export const ComboboxClear = ({
133
+ className,
134
+ children,
135
+ ...props
136
+ }: ComboboxClearProps) => (
137
+ <BaseCombobox.Clear
138
+ className={cn(inputGroupAccessoryClassName, className)}
139
+ {...props}
140
+ >
141
+ {children ?? (
142
+ <IconCrossSmall size={14} className="size-3.5" aria-hidden />
143
+ )}
144
+ </BaseCombobox.Clear>
145
+ )
146
+
147
+ export const ComboboxValue = (props: ComboboxValueProps) => (
148
+ <BaseCombobox.Value {...props} />
149
+ )
150
+
151
+ export const ComboboxPortal = (props: ComboboxPortalProps) => (
152
+ <BaseCombobox.Portal {...props} />
153
+ )
154
+
155
+ export const ComboboxBackdrop = ({
156
+ className,
157
+ ...props
158
+ }: ComboboxBackdropProps) => (
159
+ <BaseCombobox.Backdrop className={cn(className)} {...props} />
160
+ )
161
+
162
+ export const ComboboxPositioner = ({
163
+ sideOffset = 4,
164
+ className,
165
+ ...props
166
+ }: ComboboxPositionerProps) => (
167
+ <BaseCombobox.Positioner
168
+ sideOffset={sideOffset}
169
+ className={cn("z-50 outline-none", className)}
170
+ {...props}
171
+ />
172
+ )
173
+
174
+ export const ComboboxPopup = ({ className, ...props }: ComboboxPopupProps) => (
175
+ <BaseCombobox.Popup
176
+ className={cn(
177
+ "z-50 max-h-[min(24rem,var(--available-height))] w-[var(--anchor-width)] overflow-hidden rounded-md border border-border-primary bg-surface shadow-md outline-none",
178
+ motion.popupAnchor,
179
+ className,
180
+ )}
181
+ {...props}
182
+ />
183
+ )
184
+
185
+ export const ComboboxArrow = ({ className, ...props }: ComboboxArrowProps) => (
186
+ <BaseCombobox.Arrow
187
+ className={cn(
188
+ "data-[side=bottom]:top-[-6px] data-[side=left]:right-[-6px] data-[side=right]:left-[-6px] data-[side=top]:bottom-[-6px]",
189
+ "size-2.5 rotate-45 border border-border-primary bg-surface",
190
+ "data-[side=bottom]:border-r-0 data-[side=bottom]:border-b-0",
191
+ "data-[side=top]:border-t-0 data-[side=top]:border-l-0",
192
+ "data-[side=left]:border-b-0 data-[side=left]:border-l-0",
193
+ "data-[side=right]:border-t-0 data-[side=right]:border-r-0",
194
+ className,
195
+ )}
196
+ {...props}
197
+ />
198
+ )
199
+
200
+ export const ComboboxList = ({ className, ...props }: ComboboxListProps) => (
201
+ <BaseCombobox.List
202
+ className={cn("max-h-[inherit] overflow-y-auto p-1 outline-none", className)}
203
+ {...props}
204
+ />
205
+ )
206
+
207
+ export const ComboboxItem = ({ className, ...props }: ComboboxItemProps) => (
208
+ <BaseCombobox.Item
209
+ className={cn(
210
+ "flex min-h-8 cursor-default items-center gap-2 rounded-xs px-2.5 py-1.5 text-sm text-fg-primary outline-none select-none",
211
+ motion.colors,
212
+ "data-disabled:cursor-not-allowed data-disabled:opacity-50 data-highlighted:bg-background-tertiary data-highlighted:text-fg-primary",
213
+ className,
214
+ )}
215
+ {...props}
216
+ />
217
+ )
218
+
219
+ export const ComboboxItemIndicator = ({
220
+ className,
221
+ children,
222
+ ...props
223
+ }: ComboboxItemIndicatorProps) => {
224
+ if (children == null) return null
225
+
226
+ return (
227
+ <BaseCombobox.ItemIndicator
228
+ className={cn(
229
+ "ml-auto flex size-4 shrink-0 items-center justify-center text-fg-primary data-unchecked:hidden",
230
+ className,
231
+ )}
232
+ {...props}
233
+ >
234
+ {children}
235
+ </BaseCombobox.ItemIndicator>
236
+ )
237
+ }
238
+
239
+ export const ComboboxEmpty = ({ className, ...props }: ComboboxEmptyProps) => (
240
+ <BaseCombobox.Empty
241
+ className={cn("px-2.5 py-2 text-sm text-fg-tertiary empty:hidden", className)}
242
+ {...props}
243
+ />
244
+ )
245
+
246
+ export const ComboboxStatus = ({ className, ...props }: ComboboxStatusProps) => (
247
+ <BaseCombobox.Status
248
+ className={cn("px-2.5 py-2 text-sm text-fg-tertiary", className)}
249
+ {...props}
250
+ />
251
+ )
252
+
253
+ export const ComboboxGroup = ({ className, ...props }: ComboboxGroupProps) => (
254
+ <BaseCombobox.Group className={cn(className)} {...props} />
255
+ )
256
+
257
+ export const ComboboxGroupLabel = ({
258
+ className,
259
+ ...props
260
+ }: ComboboxGroupLabelProps) => (
261
+ <BaseCombobox.GroupLabel
262
+ className={cn("px-2.5 py-1.5 text-xs text-fg-tertiary", className)}
263
+ {...props}
264
+ />
265
+ )
266
+
267
+ export const ComboboxSeparator = ({
268
+ className,
269
+ ...props
270
+ }: ComboboxSeparatorProps) => (
271
+ <BaseCombobox.Separator
272
+ className={cn("my-1 h-px bg-border-primary", className)}
273
+ {...props}
274
+ />
275
+ )
276
+
277
+ export const ComboboxCollection = (props: ComboboxCollectionProps) => (
278
+ <BaseCombobox.Collection {...props} />
279
+ )
280
+
281
+ export const ComboboxChips = ({ className, ...props }: ComboboxChipsProps) => (
282
+ <BaseCombobox.Chips
283
+ className={cn(
284
+ "flex min-w-0 flex-1 flex-wrap items-center gap-1 py-1 pl-2",
285
+ className,
286
+ )}
287
+ {...props}
288
+ />
289
+ )
290
+
291
+ export const ComboboxChip = ({ className, ...props }: ComboboxChipProps) => (
292
+ <BaseCombobox.Chip
293
+ className={cn(
294
+ "inline-flex h-6 items-center gap-1 rounded-xs bg-background-tertiary px-1.5 text-xs text-fg-primary",
295
+ className,
296
+ )}
297
+ {...props}
298
+ />
299
+ )
300
+
301
+ export const ComboboxChipRemove = ({
302
+ className,
303
+ children,
304
+ ...props
305
+ }: ComboboxChipRemoveProps) => (
306
+ <BaseCombobox.ChipRemove
307
+ className={cn(
308
+ "inline-flex size-3.5 cursor-pointer items-center justify-center text-fg-tertiary outline-none hover:text-fg-primary focus-visible:outline-none",
309
+ className,
310
+ )}
311
+ {...props}
312
+ >
313
+ {children ?? (
314
+ <IconCrossSmall size={12} className="size-3" aria-hidden />
315
+ )}
316
+ </BaseCombobox.ChipRemove>
317
+ )
318
+
319
+ export const ComboboxRow = ({ className, ...props }: ComboboxRowProps) => (
320
+ <BaseCombobox.Row className={cn(className)} {...props} />
321
+ )
322
+
323
+ export const useComboboxFilter = BaseCombobox.useFilter
324
+ export const useFilteredItems = BaseCombobox.useFilteredItems
@@ -0,0 +1,377 @@
1
+ "use client"
2
+
3
+ import { Dialog as BaseDialog } from "@base-ui/react/dialog"
4
+ import {
5
+ createContext,
6
+ useContext,
7
+ useId,
8
+ useMemo,
9
+ type ButtonHTMLAttributes,
10
+ type ComponentProps,
11
+ type HTMLAttributes,
12
+ type InputHTMLAttributes,
13
+ type ReactNode,
14
+ } from "react"
15
+ import { IconCrossSmall, IconMagnifyingGlass } from "./icons"
16
+ import { cn } from "./lib/cn"
17
+ import { motion } from "./lib/motion"
18
+
19
+ type CommandContextValue = {
20
+ listboxId: string
21
+ activeOptionId?: string
22
+ }
23
+
24
+ const CommandContext = createContext<CommandContextValue | null>(null)
25
+
26
+ const useCommandContext = () => {
27
+ const context = useContext(CommandContext)
28
+ if (!context) {
29
+ throw new Error("Command parts must be used within Command.")
30
+ }
31
+ return context
32
+ }
33
+
34
+ export type CommandProps = ComponentProps<typeof BaseDialog.Root> & {
35
+ activeOptionId?: string
36
+ }
37
+
38
+ export type CommandTriggerProps = ComponentProps<typeof BaseDialog.Trigger>
39
+ export type CommandPortalProps = ComponentProps<typeof BaseDialog.Portal>
40
+ export type CommandBackdropProps = ComponentProps<typeof BaseDialog.Backdrop>
41
+ export type CommandPopupProps = ComponentProps<typeof BaseDialog.Popup>
42
+ export type CommandToolbarProps = HTMLAttributes<HTMLDivElement>
43
+ export type CommandInputProps = Omit<
44
+ InputHTMLAttributes<HTMLInputElement>,
45
+ "type"
46
+ >
47
+ export type CommandActionsProps = HTMLAttributes<HTMLDivElement>
48
+ export type CommandClearProps = ButtonHTMLAttributes<HTMLButtonElement>
49
+ export type CommandCloseProps = ComponentProps<typeof BaseDialog.Close>
50
+ export type CommandDividerProps = HTMLAttributes<HTMLDivElement>
51
+ export type CommandContentProps = HTMLAttributes<HTMLDivElement>
52
+ export type CommandFiltersProps = HTMLAttributes<HTMLUListElement>
53
+ export type CommandFilterProps = ButtonHTMLAttributes<HTMLButtonElement> & {
54
+ selected?: boolean
55
+ }
56
+ export type CommandListProps = HTMLAttributes<HTMLUListElement>
57
+ export type CommandItemProps = HTMLAttributes<HTMLElement> & {
58
+ selected?: boolean
59
+ disabled?: boolean
60
+ href?: string
61
+ }
62
+ export type CommandEmptyProps = HTMLAttributes<HTMLDivElement>
63
+ export type CommandDialogTitleProps = ComponentProps<typeof BaseDialog.Title>
64
+
65
+ export const Command = ({
66
+ activeOptionId,
67
+ children,
68
+ ...props
69
+ }: CommandProps) => {
70
+ const listboxId = useId()
71
+ const value = useMemo(
72
+ () => ({ listboxId, activeOptionId }),
73
+ [activeOptionId, listboxId],
74
+ )
75
+
76
+ return (
77
+ <CommandContext.Provider value={value}>
78
+ <BaseDialog.Root {...props}>{children}</BaseDialog.Root>
79
+ </CommandContext.Provider>
80
+ )
81
+ }
82
+
83
+ export const CommandTrigger = ({
84
+ className,
85
+ ...props
86
+ }: CommandTriggerProps) => (
87
+ <BaseDialog.Trigger className={cn("cursor-pointer", className)} {...props} />
88
+ )
89
+
90
+ export const CommandPortal = (props: CommandPortalProps) => (
91
+ <BaseDialog.Portal {...props} />
92
+ )
93
+
94
+ export const CommandBackdrop = ({
95
+ className,
96
+ ...props
97
+ }: CommandBackdropProps) => (
98
+ <BaseDialog.Backdrop
99
+ className={cn(
100
+ "fixed inset-0 z-50 bg-black/[0.04] dark:bg-black/40",
101
+ motion.backdrop,
102
+ className,
103
+ )}
104
+ {...props}
105
+ />
106
+ )
107
+
108
+ export const CommandPopup = ({ className, ...props }: CommandPopupProps) => (
109
+ <BaseDialog.Popup
110
+ className={cn(
111
+ "fixed top-1/2 left-1/2 z-50 flex h-[min(80vh,32rem)] w-full max-w-xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-2xl border border-border-primary bg-surface-raised shadow-xl outline-none max-sm:max-w-[calc(100vw-2rem)]",
112
+ motion.popupCenter,
113
+ className,
114
+ )}
115
+ {...props}
116
+ />
117
+ )
118
+
119
+ export const CommandToolbar = ({
120
+ className,
121
+ ...props
122
+ }: CommandToolbarProps) => (
123
+ <div
124
+ className={cn("flex shrink-0 items-center gap-3 p-4", className)}
125
+ {...props}
126
+ />
127
+ )
128
+
129
+ export const CommandInput = ({
130
+ className,
131
+ id,
132
+ ...props
133
+ }: CommandInputProps) => {
134
+ const { listboxId, activeOptionId } = useCommandContext()
135
+ const fallbackId = useId()
136
+
137
+ return (
138
+ <input
139
+ id={id ?? fallbackId}
140
+ type="search"
141
+ role="combobox"
142
+ autoComplete="off"
143
+ spellCheck={false}
144
+ aria-autocomplete="list"
145
+ aria-controls={listboxId}
146
+ aria-expanded="true"
147
+ aria-activedescendant={activeOptionId}
148
+ className={cn(
149
+ "h-9 min-w-0 flex-1 cursor-text rounded-md bg-transparent px-2.5 text-base text-fg-primary outline-none placeholder:text-fg-quaternary",
150
+ "focus-visible:bg-background-tertiary/60 focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
151
+ "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none",
152
+ className,
153
+ )}
154
+ {...props}
155
+ />
156
+ )
157
+ }
158
+
159
+ export const CommandActions = ({
160
+ className,
161
+ ...props
162
+ }: CommandActionsProps) => (
163
+ <div
164
+ className={cn("flex shrink-0 items-center gap-1.5", className)}
165
+ {...props}
166
+ />
167
+ )
168
+
169
+ export const CommandClear = ({
170
+ className,
171
+ children = "Clear",
172
+ ...props
173
+ }: CommandClearProps) => (
174
+ <button
175
+ type="button"
176
+ className={cn(
177
+ "cursor-pointer rounded-full px-3 py-1.5 text-sm text-fg-quaternary outline-none",
178
+ motion.colors,
179
+ "hover:bg-background-tertiary hover:text-fg-primary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20 data-[active=true]:text-fg-primary",
180
+ className,
181
+ )}
182
+ {...props}
183
+ >
184
+ {children}
185
+ </button>
186
+ )
187
+
188
+ export const CommandDivider = ({
189
+ className,
190
+ ...props
191
+ }: CommandDividerProps) => (
192
+ <div
193
+ aria-hidden
194
+ className={cn("h-6 w-px shrink-0 rounded-full bg-border-primary", className)}
195
+ {...props}
196
+ />
197
+ )
198
+
199
+ export const CommandClose = ({
200
+ className,
201
+ children,
202
+ ...props
203
+ }: CommandCloseProps) => (
204
+ <BaseDialog.Close
205
+ className={cn(
206
+ "inline-flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full text-fg-primary outline-none",
207
+ motion.colors,
208
+ "hover:bg-background-tertiary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
209
+ className,
210
+ )}
211
+ aria-label={props["aria-label"] ?? "Close"}
212
+ {...props}
213
+ >
214
+ {children ?? (
215
+ <IconCrossSmall size={20} className="size-5" aria-hidden />
216
+ )}
217
+ </BaseDialog.Close>
218
+ )
219
+
220
+ export const CommandContent = ({
221
+ className,
222
+ ...props
223
+ }: CommandContentProps) => (
224
+ <div
225
+ className={cn(
226
+ "flex min-h-0 flex-1 flex-col gap-3 overflow-x-visible overflow-y-auto overscroll-contain px-4 pt-1 pb-5",
227
+ className,
228
+ )}
229
+ {...props}
230
+ />
231
+ )
232
+
233
+ export const CommandFilters = ({
234
+ className,
235
+ ...props
236
+ }: CommandFiltersProps) => (
237
+ <ul
238
+ role="list"
239
+ className={cn(
240
+ "flex shrink-0 flex-wrap justify-start gap-1.5 py-1.5",
241
+ className,
242
+ )}
243
+ {...props}
244
+ />
245
+ )
246
+
247
+ export const CommandFilter = ({
248
+ className,
249
+ selected = false,
250
+ children,
251
+ ...props
252
+ }: CommandFilterProps) => (
253
+ <li role="presentation" className="contents">
254
+ <button
255
+ type="button"
256
+ aria-pressed={selected}
257
+ data-selected={selected || undefined}
258
+ className={cn(
259
+ "cursor-pointer rounded-full px-4 py-2 text-sm text-fg-quaternary outline-none",
260
+ motion.colors,
261
+ "hover:text-fg-primary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
262
+ "data-selected:bg-background-tertiary data-selected:text-fg-primary",
263
+ className,
264
+ )}
265
+ {...props}
266
+ >
267
+ {children}
268
+ </button>
269
+ </li>
270
+ )
271
+
272
+ export const CommandList = ({ className, ...props }: CommandListProps) => {
273
+ const { listboxId } = useCommandContext()
274
+
275
+ return (
276
+ <ul
277
+ id={listboxId}
278
+ role="listbox"
279
+ className={cn(
280
+ "grid min-h-0 flex-1 content-start gap-0 overflow-visible overscroll-contain py-0.5",
281
+ className,
282
+ )}
283
+ {...props}
284
+ />
285
+ )
286
+ }
287
+
288
+ export const CommandItem = ({
289
+ className,
290
+ selected = false,
291
+ disabled = false,
292
+ href,
293
+ children,
294
+ id,
295
+ onClick,
296
+ ...props
297
+ }: CommandItemProps) => {
298
+ const itemClassName = cn(
299
+ "flex h-15 min-h-15 w-full cursor-pointer items-center justify-between gap-4 rounded-lg px-4 text-left text-sm font-medium text-fg-primary outline-none select-none",
300
+ motion.colors,
301
+ "hover:bg-background-tertiary data-selected:bg-background-tertiary",
302
+ "data-disabled:cursor-not-allowed data-disabled:opacity-50",
303
+ "focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
304
+ className,
305
+ )
306
+
307
+ return (
308
+ <li role="presentation" className="m-0">
309
+ {href ? (
310
+ <a
311
+ id={id}
312
+ href={disabled ? undefined : href}
313
+ role="option"
314
+ aria-selected={selected}
315
+ aria-disabled={disabled || undefined}
316
+ data-selected={selected || undefined}
317
+ data-disabled={disabled || undefined}
318
+ className={itemClassName}
319
+ onClick={onClick as never}
320
+ {...(props as HTMLAttributes<HTMLAnchorElement>)}
321
+ >
322
+ {children}
323
+ </a>
324
+ ) : (
325
+ <button
326
+ id={id}
327
+ type="button"
328
+ role="option"
329
+ aria-selected={selected}
330
+ disabled={disabled}
331
+ data-selected={selected || undefined}
332
+ data-disabled={disabled || undefined}
333
+ className={itemClassName}
334
+ onClick={onClick as never}
335
+ {...(props as ButtonHTMLAttributes<HTMLButtonElement>)}
336
+ >
337
+ {children}
338
+ </button>
339
+ )}
340
+ </li>
341
+ )
342
+ }
343
+
344
+ export const CommandEmpty = ({
345
+ className,
346
+ children,
347
+ ...props
348
+ }: CommandEmptyProps) => (
349
+ <div
350
+ role="presentation"
351
+ className={cn(
352
+ "flex flex-1 items-center justify-center gap-2 px-4 py-6 text-sm font-medium text-fg-quaternary",
353
+ className,
354
+ )}
355
+ aria-live="polite"
356
+ {...props}
357
+ >
358
+ <IconMagnifyingGlass size={20} className="size-5 shrink-0" aria-hidden />
359
+ <span>{children ?? "No results"}</span>
360
+ </div>
361
+ )
362
+
363
+ export type CommandTitleProps = {
364
+ children: ReactNode
365
+ className?: string
366
+ }
367
+
368
+ export const CommandTitle = ({ className, children }: CommandTitleProps) => (
369
+ <span className={cn("min-w-0 truncate", className)}>{children}</span>
370
+ )
371
+
372
+ export const CommandDialogTitle = ({
373
+ className,
374
+ ...props
375
+ }: CommandDialogTitleProps) => (
376
+ <BaseDialog.Title className={cn("sr-only", className)} {...props} />
377
+ )