@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,217 @@
1
+ "use client"
2
+
3
+ import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu"
4
+ import type { ComponentProps } from "react"
5
+ import { IconChevronDownSmall } from "./icons"
6
+ import { cn } from "./lib/cn"
7
+ import { motion } from "./lib/motion"
8
+
9
+ export type NavigationMenuProps = ComponentProps<typeof BaseNavigationMenu.Root>
10
+ export type NavigationMenuListProps = ComponentProps<
11
+ typeof BaseNavigationMenu.List
12
+ >
13
+ export type NavigationMenuItemProps = ComponentProps<
14
+ typeof BaseNavigationMenu.Item
15
+ >
16
+ export type NavigationMenuTriggerProps = ComponentProps<
17
+ typeof BaseNavigationMenu.Trigger
18
+ >
19
+ export type NavigationMenuContentProps = ComponentProps<
20
+ typeof BaseNavigationMenu.Content
21
+ >
22
+ export type NavigationMenuPortalProps = ComponentProps<
23
+ typeof BaseNavigationMenu.Portal
24
+ >
25
+ export type NavigationMenuPositionerProps = ComponentProps<
26
+ typeof BaseNavigationMenu.Positioner
27
+ >
28
+ export type NavigationMenuViewportProps = ComponentProps<
29
+ typeof BaseNavigationMenu.Viewport
30
+ >
31
+ export type NavigationMenuBackdropProps = ComponentProps<
32
+ typeof BaseNavigationMenu.Backdrop
33
+ >
34
+ export type NavigationMenuPopupProps = ComponentProps<
35
+ typeof BaseNavigationMenu.Popup
36
+ >
37
+ export type NavigationMenuArrowProps = ComponentProps<
38
+ typeof BaseNavigationMenu.Arrow
39
+ >
40
+ export type NavigationMenuLinkProps = ComponentProps<
41
+ typeof BaseNavigationMenu.Link
42
+ >
43
+ export type NavigationMenuIconProps = ComponentProps<
44
+ typeof BaseNavigationMenu.Icon
45
+ >
46
+
47
+ const navigationMenuTriggerClassName = cn(
48
+ "inline-flex h-9 cursor-pointer items-center gap-1 rounded-md px-3 text-sm text-fg-secondary outline-none",
49
+ motion.colors,
50
+ "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 data-popup-open:bg-background-tertiary data-popup-open:text-fg-primary",
51
+ )
52
+
53
+ export const NavigationMenu = ({
54
+ className,
55
+ ...props
56
+ }: NavigationMenuProps) => (
57
+ <BaseNavigationMenu.Root
58
+ className={cn("relative isolate z-10 flex max-w-max flex-1 items-center justify-center", className)}
59
+ {...props}
60
+ />
61
+ )
62
+
63
+ export const NavigationMenuList = ({
64
+ className,
65
+ ...props
66
+ }: NavigationMenuListProps) => (
67
+ <BaseNavigationMenu.List
68
+ className={cn(
69
+ "group flex flex-1 list-none items-center justify-center gap-0.5",
70
+ className,
71
+ )}
72
+ {...props}
73
+ />
74
+ )
75
+
76
+ export const NavigationMenuItem = ({
77
+ className,
78
+ ...props
79
+ }: NavigationMenuItemProps) => (
80
+ <BaseNavigationMenu.Item className={cn(className)} {...props} />
81
+ )
82
+
83
+ export const NavigationMenuTrigger = ({
84
+ className,
85
+ children,
86
+ ...props
87
+ }: NavigationMenuTriggerProps) => (
88
+ <BaseNavigationMenu.Trigger
89
+ className={cn(navigationMenuTriggerClassName, className)}
90
+ {...props}
91
+ >
92
+ {children}
93
+ <NavigationMenuIcon />
94
+ </BaseNavigationMenu.Trigger>
95
+ )
96
+
97
+ export const NavigationMenuIcon = ({
98
+ className,
99
+ children,
100
+ ...props
101
+ }: NavigationMenuIconProps) => (
102
+ <BaseNavigationMenu.Icon
103
+ className={cn(
104
+ "inline-flex text-fg-tertiary transition-transform duration-150 ease-out motion-reduce:transition-none data-popup-open:rotate-180",
105
+ className,
106
+ )}
107
+ {...props}
108
+ >
109
+ {children ?? (
110
+ <IconChevronDownSmall size={14} className="size-3.5" aria-hidden />
111
+ )}
112
+ </BaseNavigationMenu.Icon>
113
+ )
114
+
115
+ export const NavigationMenuContent = ({
116
+ className,
117
+ ...props
118
+ }: NavigationMenuContentProps) => (
119
+ <BaseNavigationMenu.Content
120
+ className={cn(
121
+ "w-auto p-2 data-ending-style:opacity-0 data-starting-style:opacity-0",
122
+ motion.colors,
123
+ className,
124
+ )}
125
+ {...props}
126
+ />
127
+ )
128
+
129
+ export const NavigationMenuLink = ({
130
+ className,
131
+ ...props
132
+ }: NavigationMenuLinkProps) => (
133
+ <BaseNavigationMenu.Link
134
+ className={cn(
135
+ "flex cursor-pointer flex-col gap-0.5 rounded-md p-2.5 text-sm text-fg-primary outline-none",
136
+ motion.colors,
137
+ "hover:bg-background-tertiary focus-visible:bg-background-tertiary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20 data-active:bg-background-tertiary",
138
+ className,
139
+ )}
140
+ {...props}
141
+ />
142
+ )
143
+
144
+ export const NavigationMenuPortal = (props: NavigationMenuPortalProps) => (
145
+ <BaseNavigationMenu.Portal {...props} />
146
+ )
147
+
148
+ export const NavigationMenuBackdrop = ({
149
+ className,
150
+ ...props
151
+ }: NavigationMenuBackdropProps) => (
152
+ <BaseNavigationMenu.Backdrop
153
+ className={cn(
154
+ "fixed inset-0 z-40 bg-transparent",
155
+ motion.backdrop,
156
+ className,
157
+ )}
158
+ {...props}
159
+ />
160
+ )
161
+
162
+ export const NavigationMenuPositioner = ({
163
+ sideOffset = 8,
164
+ className,
165
+ ...props
166
+ }: NavigationMenuPositionerProps) => (
167
+ <BaseNavigationMenu.Positioner
168
+ sideOffset={sideOffset}
169
+ className={cn("z-50 outline-none", className)}
170
+ {...props}
171
+ />
172
+ )
173
+
174
+ export const NavigationMenuPopup = ({
175
+ className,
176
+ ...props
177
+ }: NavigationMenuPopupProps) => (
178
+ <BaseNavigationMenu.Popup
179
+ className={cn(
180
+ "relative z-50 w-[var(--popup-width)] overflow-hidden rounded-xl border border-border-primary bg-surface shadow-md outline-none",
181
+ "h-[var(--popup-height)] transition-[width,height,opacity] duration-200 ease-out motion-reduce:transition-none",
182
+ "data-starting-style:opacity-0 data-ending-style:opacity-0",
183
+ className,
184
+ )}
185
+ {...props}
186
+ />
187
+ )
188
+
189
+ export const NavigationMenuViewport = ({
190
+ className,
191
+ ...props
192
+ }: NavigationMenuViewportProps) => (
193
+ <BaseNavigationMenu.Viewport
194
+ className={cn("relative size-full overflow-hidden", className)}
195
+ {...props}
196
+ />
197
+ )
198
+
199
+ export const NavigationMenuArrow = ({
200
+ className,
201
+ ...props
202
+ }: NavigationMenuArrowProps) => (
203
+ <BaseNavigationMenu.Arrow
204
+ className={cn(
205
+ "data-[side=bottom]:top-[-6px] data-[side=left]:right-[-6px] data-[side=right]:left-[-6px] data-[side=top]:bottom-[-6px]",
206
+ "size-2.5 rotate-45 border border-border-primary bg-surface",
207
+ "data-[side=bottom]:border-r-0 data-[side=bottom]:border-b-0",
208
+ "data-[side=top]:border-t-0 data-[side=top]:border-l-0",
209
+ "data-[side=left]:border-b-0 data-[side=left]:border-l-0",
210
+ "data-[side=right]:border-t-0 data-[side=right]:border-r-0",
211
+ className,
212
+ )}
213
+ {...props}
214
+ />
215
+ )
216
+
217
+ export { navigationMenuTriggerClassName }
@@ -0,0 +1,119 @@
1
+ "use client"
2
+
3
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field"
4
+ import type { ComponentProps } from "react"
5
+ import { IconMinus, IconPlus } from "./icons"
6
+ import { cn } from "./lib/cn"
7
+ import { motion } from "./lib/motion"
8
+
9
+ export type NumberFieldProps = ComponentProps<typeof BaseNumberField.Root>
10
+ export type NumberFieldGroupProps = ComponentProps<typeof BaseNumberField.Group>
11
+ export type NumberFieldInputProps = ComponentProps<typeof BaseNumberField.Input>
12
+ export type NumberFieldIncrementProps = ComponentProps<
13
+ typeof BaseNumberField.Increment
14
+ >
15
+ export type NumberFieldDecrementProps = ComponentProps<
16
+ typeof BaseNumberField.Decrement
17
+ >
18
+ export type NumberFieldScrubAreaProps = ComponentProps<
19
+ typeof BaseNumberField.ScrubArea
20
+ >
21
+ export type NumberFieldScrubAreaCursorProps = ComponentProps<
22
+ typeof BaseNumberField.ScrubAreaCursor
23
+ >
24
+
25
+ export const NumberField = ({ className, ...props }: NumberFieldProps) => (
26
+ <BaseNumberField.Root
27
+ className={cn("flex flex-col gap-1.5", className)}
28
+ {...props}
29
+ />
30
+ )
31
+
32
+ export const NumberFieldGroup = ({
33
+ className,
34
+ ...props
35
+ }: NumberFieldGroupProps) => (
36
+ <BaseNumberField.Group
37
+ className={cn(
38
+ "flex h-9 w-full items-stretch overflow-hidden rounded-md border border-border-secondary bg-surface inset-shadow-outline-top outline-none transition-[color,box-shadow]",
39
+ "focus-within:border-ring focus-within:ring-[3px] focus-within:ring-offset-1 focus-within:ring-offset-background-primary focus-within:ring-ring/20",
40
+ "aria-invalid:border-destructive aria-invalid:focus-within:border-destructive aria-invalid:focus-within:ring-destructive/20",
41
+ "has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:focus-within:border-destructive has-[[aria-invalid=true]]:focus-within:ring-destructive/20",
42
+ "has-[:disabled]:opacity-50",
43
+ className,
44
+ )}
45
+ {...props}
46
+ />
47
+ )
48
+
49
+ export const NumberFieldInput = ({
50
+ className,
51
+ ...props
52
+ }: NumberFieldInputProps) => (
53
+ <BaseNumberField.Input
54
+ className={cn(
55
+ "h-full min-w-0 flex-1 cursor-text border-x border-border-primary bg-transparent px-2 text-center text-sm tabular-nums text-fg-primary outline-none focus-visible:outline-none",
56
+ className,
57
+ )}
58
+ {...props}
59
+ />
60
+ )
61
+
62
+ const stepperClassName = cn(
63
+ "inline-flex size-9 shrink-0 cursor-pointer items-center justify-center text-fg-tertiary outline-none",
64
+ motion.colors,
65
+ "hover:bg-background-tertiary hover:text-fg-primary focus-visible:bg-background-tertiary focus-visible:text-fg-primary focus-visible:outline-none data-disabled:cursor-not-allowed data-disabled:opacity-50",
66
+ )
67
+
68
+ export const NumberFieldDecrement = ({
69
+ className,
70
+ children,
71
+ "aria-label": ariaLabel = "Decrease",
72
+ ...props
73
+ }: NumberFieldDecrementProps) => (
74
+ <BaseNumberField.Decrement
75
+ aria-label={ariaLabel}
76
+ className={cn(stepperClassName, className)}
77
+ {...props}
78
+ >
79
+ {children ?? <IconMinus size={16} className="size-4" aria-hidden />}
80
+ </BaseNumberField.Decrement>
81
+ )
82
+
83
+ export const NumberFieldIncrement = ({
84
+ className,
85
+ children,
86
+ "aria-label": ariaLabel = "Increase",
87
+ ...props
88
+ }: NumberFieldIncrementProps) => (
89
+ <BaseNumberField.Increment
90
+ aria-label={ariaLabel}
91
+ className={cn(stepperClassName, className)}
92
+ {...props}
93
+ >
94
+ {children ?? <IconPlus size={16} className="size-4" aria-hidden />}
95
+ </BaseNumberField.Increment>
96
+ )
97
+
98
+ export const NumberFieldScrubArea = ({
99
+ className,
100
+ ...props
101
+ }: NumberFieldScrubAreaProps) => (
102
+ <BaseNumberField.ScrubArea
103
+ className={cn(
104
+ "inline-flex cursor-ew-resize items-center gap-1 text-sm text-fg-secondary select-none",
105
+ className,
106
+ )}
107
+ {...props}
108
+ />
109
+ )
110
+
111
+ export const NumberFieldScrubAreaCursor = ({
112
+ className,
113
+ ...props
114
+ }: NumberFieldScrubAreaCursorProps) => (
115
+ <BaseNumberField.ScrubAreaCursor
116
+ className={cn(className)}
117
+ {...props}
118
+ />
119
+ )
package/src/orb.tsx ADDED
@@ -0,0 +1,33 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import type { ComponentProps } from "react";
3
+ import { cn } from "./lib/cn";
4
+
5
+ const orbVariants = cva(
6
+ "relative inline-flex shrink-0 animate-pulse rounded-full border border-brand-primary-border bg-brand-primary after:absolute after:inset-1/4 after:rounded-full after:bg-surface/70 after:blur-sm motion-reduce:animate-none",
7
+ {
8
+ variants: {
9
+ size: {
10
+ sm: "size-6",
11
+ md: "size-10",
12
+ lg: "size-16",
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ size: "md",
17
+ },
18
+ },
19
+ );
20
+
21
+ export type OrbProps = ComponentProps<"span"> &
22
+ VariantProps<typeof orbVariants>;
23
+
24
+ export const Orb = ({ className, size, ...props }: OrbProps) => (
25
+ <span
26
+ role="status"
27
+ aria-label="Loading"
28
+ className={cn(orbVariants({ size }), className)}
29
+ {...props}
30
+ />
31
+ );
32
+
33
+ export { orbVariants };
@@ -0,0 +1,45 @@
1
+ "use client"
2
+
3
+ import { OTPField as BaseOTPField } from "@base-ui/react/otp-field"
4
+ import type { ComponentProps } from "react"
5
+ import { cn } from "./lib/cn"
6
+ import { motion } from "./lib/motion"
7
+
8
+ export type OTPFieldProps = ComponentProps<typeof BaseOTPField.Root>
9
+ export type OTPFieldInputProps = ComponentProps<typeof BaseOTPField.Input>
10
+ export type OTPFieldSeparatorProps = ComponentProps<typeof BaseOTPField.Separator>
11
+
12
+ export const OTPField = ({ className, ...props }: OTPFieldProps) => (
13
+ <BaseOTPField.Root
14
+ className={cn("flex items-center gap-2", className)}
15
+ {...props}
16
+ />
17
+ )
18
+
19
+ export const OTPFieldInput = ({ className, ...props }: OTPFieldInputProps) => (
20
+ <BaseOTPField.Input
21
+ className={cn(
22
+ "size-10 rounded-md border border-border-secondary bg-surface text-center text-sm tabular-nums text-fg-primary inset-shadow-outline-top outline-none",
23
+ motion.colors,
24
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
25
+ "aria-invalid:border-destructive aria-invalid:focus-visible:border-destructive aria-invalid:focus-visible:ring-destructive/20",
26
+ "data-disabled:cursor-not-allowed data-disabled:opacity-50",
27
+ "data-filled:border-border-secondary",
28
+ className,
29
+ )}
30
+ {...props}
31
+ />
32
+ )
33
+
34
+ export const OTPFieldSeparator = ({
35
+ className,
36
+ ...props
37
+ }: OTPFieldSeparatorProps) => (
38
+ <BaseOTPField.Separator
39
+ className={cn(
40
+ "mx-0.5 h-px w-3 shrink-0 self-center bg-border-secondary",
41
+ className,
42
+ )}
43
+ {...props}
44
+ />
45
+ )
@@ -0,0 +1,91 @@
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">;
15
+
16
+ export const Pagination = ({ className, ...props }: PaginationProps) => (
17
+ <nav
18
+ aria-label="Pagination"
19
+ className={cn("flex w-full justify-center", className)}
20
+ {...props}
21
+ />
22
+ );
23
+
24
+ export const PaginationContent = ({
25
+ className,
26
+ ...props
27
+ }: PaginationContentProps) => (
28
+ <ul className={cn("flex items-center gap-1", className)} {...props} />
29
+ );
30
+
31
+ export const PaginationItem = ({
32
+ className,
33
+ ...props
34
+ }: PaginationItemProps) => <li className={cn("flex", className)} {...props} />;
35
+
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
+ );
54
+
55
+ export const PaginationPrevious = ({
56
+ children = "Previous",
57
+ className,
58
+ ...props
59
+ }: PaginationPreviousProps) => (
60
+ <PaginationLink className={cn("w-auto gap-1 px-3", className)} {...props}>
61
+ <IconChevronRightSmall className="rotate-180" aria-hidden />
62
+ {children}
63
+ </PaginationLink>
64
+ );
65
+
66
+ export const PaginationNext = ({
67
+ children = "Next",
68
+ className,
69
+ ...props
70
+ }: PaginationNextProps) => (
71
+ <PaginationLink className={cn("w-auto gap-1 px-3", className)} {...props}>
72
+ {children}
73
+ <IconChevronRightSmall aria-hidden />
74
+ </PaginationLink>
75
+ );
76
+
77
+ export const PaginationEllipsis = ({
78
+ className,
79
+ ...props
80
+ }: PaginationEllipsisProps) => (
81
+ <span
82
+ aria-hidden
83
+ className={cn(
84
+ "flex size-9 items-center justify-center text-sm text-fg-tertiary",
85
+ className,
86
+ )}
87
+ {...props}
88
+ >
89
+
90
+ </span>
91
+ );
@@ -0,0 +1,92 @@
1
+ "use client"
2
+
3
+ import { Popover as BasePopover } from "@base-ui/react/popover"
4
+ import type { ComponentProps } from "react"
5
+ import { cn } from "./lib/cn"
6
+ import { motion } from "./lib/motion"
7
+
8
+ export type PopoverProps = ComponentProps<typeof BasePopover.Root>
9
+ export type PopoverTriggerProps = ComponentProps<typeof BasePopover.Trigger>
10
+ export type PopoverPortalProps = ComponentProps<typeof BasePopover.Portal>
11
+ export type PopoverPositionerProps = ComponentProps<
12
+ typeof BasePopover.Positioner
13
+ >
14
+ export type PopoverPopupProps = ComponentProps<typeof BasePopover.Popup>
15
+ export type PopoverTitleProps = ComponentProps<typeof BasePopover.Title>
16
+ export type PopoverDescriptionProps = ComponentProps<
17
+ typeof BasePopover.Description
18
+ >
19
+ export type PopoverCloseProps = ComponentProps<typeof BasePopover.Close>
20
+ export type PopoverArrowProps = ComponentProps<typeof BasePopover.Arrow>
21
+
22
+ export const Popover = (props: PopoverProps) => <BasePopover.Root {...props} />
23
+
24
+ export const PopoverTrigger = ({
25
+ className,
26
+ ...props
27
+ }: PopoverTriggerProps) => (
28
+ <BasePopover.Trigger className={cn("cursor-pointer", className)} {...props} />
29
+ )
30
+
31
+ export const PopoverPortal = (props: PopoverPortalProps) => (
32
+ <BasePopover.Portal {...props} />
33
+ )
34
+
35
+ export const PopoverPositioner = ({
36
+ sideOffset = 4,
37
+ className,
38
+ ...props
39
+ }: PopoverPositionerProps) => (
40
+ <BasePopover.Positioner
41
+ sideOffset={sideOffset}
42
+ className={cn("z-50 outline-none", className)}
43
+ {...props}
44
+ />
45
+ )
46
+
47
+ export const PopoverPopup = ({ className, ...props }: PopoverPopupProps) => (
48
+ <BasePopover.Popup
49
+ 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
+ motion.popupAnchor,
52
+ className,
53
+ )}
54
+ {...props}
55
+ />
56
+ )
57
+
58
+ export const PopoverTitle = ({ className, ...props }: PopoverTitleProps) => (
59
+ <BasePopover.Title
60
+ className={cn("text-sm-strong text-fg-primary", className)}
61
+ {...props}
62
+ />
63
+ )
64
+
65
+ export const PopoverDescription = ({
66
+ className,
67
+ ...props
68
+ }: PopoverDescriptionProps) => (
69
+ <BasePopover.Description
70
+ className={cn("text-sm leading-relaxed text-fg-secondary", className)}
71
+ {...props}
72
+ />
73
+ )
74
+
75
+ export const PopoverClose = ({ className, ...props }: PopoverCloseProps) => (
76
+ <BasePopover.Close className={cn("cursor-pointer", className)} {...props} />
77
+ )
78
+
79
+ export const PopoverArrow = ({ className, ...props }: PopoverArrowProps) => (
80
+ <BasePopover.Arrow
81
+ className={cn(
82
+ "data-[side=bottom]:top-[-6px] data-[side=left]:right-[-6px] data-[side=right]:left-[-6px] data-[side=top]:bottom-[-6px]",
83
+ "size-2.5 rotate-45 border border-border-primary bg-surface",
84
+ "data-[side=bottom]:border-r-0 data-[side=bottom]:border-b-0",
85
+ "data-[side=top]:border-t-0 data-[side=top]:border-l-0",
86
+ "data-[side=left]:border-b-0 data-[side=left]:border-l-0",
87
+ "data-[side=right]:border-t-0 data-[side=right]:border-r-0",
88
+ className,
89
+ )}
90
+ {...props}
91
+ />
92
+ )
@@ -0,0 +1,103 @@
1
+ "use client"
2
+
3
+ import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card"
4
+ import type { ComponentProps } from "react"
5
+ import { cn } from "./lib/cn"
6
+ import { motion } from "./lib/motion"
7
+
8
+ export type PreviewCardProps = ComponentProps<typeof BasePreviewCard.Root>
9
+ export type PreviewCardTriggerProps = ComponentProps<
10
+ typeof BasePreviewCard.Trigger
11
+ >
12
+ export type PreviewCardPortalProps = ComponentProps<
13
+ typeof BasePreviewCard.Portal
14
+ >
15
+ export type PreviewCardBackdropProps = ComponentProps<
16
+ typeof BasePreviewCard.Backdrop
17
+ >
18
+ export type PreviewCardPositionerProps = ComponentProps<
19
+ typeof BasePreviewCard.Positioner
20
+ >
21
+ export type PreviewCardPopupProps = ComponentProps<typeof BasePreviewCard.Popup>
22
+ export type PreviewCardArrowProps = ComponentProps<typeof BasePreviewCard.Arrow>
23
+ export type PreviewCardViewportProps = ComponentProps<
24
+ typeof BasePreviewCard.Viewport
25
+ >
26
+
27
+ export const PreviewCard = (props: PreviewCardProps) => (
28
+ <BasePreviewCard.Root {...props} />
29
+ )
30
+
31
+ export const PreviewCardTrigger = ({
32
+ className,
33
+ ...props
34
+ }: PreviewCardTriggerProps) => (
35
+ <BasePreviewCard.Trigger
36
+ className={cn("cursor-pointer", className)}
37
+ {...props}
38
+ />
39
+ )
40
+
41
+ export const PreviewCardPortal = (props: PreviewCardPortalProps) => (
42
+ <BasePreviewCard.Portal {...props} />
43
+ )
44
+
45
+ export const PreviewCardBackdrop = ({
46
+ className,
47
+ ...props
48
+ }: PreviewCardBackdropProps) => (
49
+ <BasePreviewCard.Backdrop className={cn(className)} {...props} />
50
+ )
51
+
52
+ export const PreviewCardPositioner = ({
53
+ sideOffset = 8,
54
+ className,
55
+ ...props
56
+ }: PreviewCardPositionerProps) => (
57
+ <BasePreviewCard.Positioner
58
+ sideOffset={sideOffset}
59
+ className={cn("z-50 outline-none", className)}
60
+ {...props}
61
+ />
62
+ )
63
+
64
+ export const PreviewCardPopup = ({
65
+ className,
66
+ ...props
67
+ }: PreviewCardPopupProps) => (
68
+ <BasePreviewCard.Popup
69
+ className={cn(
70
+ "z-50 w-72 overflow-hidden rounded-xl border border-border-primary bg-surface p-4 shadow-md outline-none",
71
+ motion.popupAnchor,
72
+ className,
73
+ )}
74
+ {...props}
75
+ />
76
+ )
77
+
78
+ export const PreviewCardArrow = ({
79
+ className,
80
+ ...props
81
+ }: PreviewCardArrowProps) => (
82
+ <BasePreviewCard.Arrow
83
+ className={cn(
84
+ "data-[side=bottom]:top-[-6px] data-[side=left]:right-[-6px] data-[side=right]:left-[-6px] data-[side=top]:bottom-[-6px]",
85
+ "size-2.5 rotate-45 border border-border-primary bg-surface",
86
+ "data-[side=bottom]:border-r-0 data-[side=bottom]:border-b-0",
87
+ "data-[side=top]:border-t-0 data-[side=top]:border-l-0",
88
+ "data-[side=left]:border-b-0 data-[side=left]:border-l-0",
89
+ "data-[side=right]:border-t-0 data-[side=right]:border-r-0",
90
+ className,
91
+ )}
92
+ {...props}
93
+ />
94
+ )
95
+
96
+ export const PreviewCardViewport = ({
97
+ className,
98
+ ...props
99
+ }: PreviewCardViewportProps) => (
100
+ <BasePreviewCard.Viewport className={cn(className)} {...props} />
101
+ )
102
+
103
+ export const createPreviewCardHandle = BasePreviewCard.createHandle