@srcroot/ui 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/registry/accordion.tsx +6 -2
- package/registry/badge.tsx +9 -25
- package/registry/breadcrumb.tsx +1 -1
- package/registry/button-group.tsx +9 -29
- package/registry/button.tsx +20 -46
- package/registry/card.tsx +21 -47
- package/registry/combobox.tsx +0 -3
- package/registry/command.tsx +6 -4
- package/registry/container.tsx +9 -25
- package/registry/drawer.tsx +36 -12
- package/registry/dropdown-menu.tsx +92 -44
- package/registry/hover-card.tsx +1 -1
- package/registry/image.tsx +2 -2
- package/registry/menubar.tsx +1 -1
- package/registry/resizable.tsx +164 -63
- package/registry/scroll-area.tsx +66 -7
- package/registry/sheet.tsx +62 -18
- package/registry/sidebar.tsx +7 -0
- package/registry/slider.tsx +101 -86
- package/registry/text.tsx +7 -16
package/package.json
CHANGED
package/registry/accordion.tsx
CHANGED
|
@@ -5,6 +5,7 @@ interface AccordionContextValue {
|
|
|
5
5
|
value: string[]
|
|
6
6
|
onValueChange: (value: string[]) => void
|
|
7
7
|
type: "single" | "multiple"
|
|
8
|
+
collapsible: boolean
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const AccordionContext = React.createContext<AccordionContextValue | null>(null)
|
|
@@ -37,14 +38,14 @@ interface AccordionProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
37
38
|
* </Accordion>
|
|
38
39
|
*/
|
|
39
40
|
const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
|
|
40
|
-
({ className, type = "single", value: controlledValue, onValueChange, defaultValue = [], children, ...props }, ref) => {
|
|
41
|
+
({ className, type = "single", value: controlledValue, onValueChange, defaultValue = [], collapsible = false, children, ...props }, ref) => {
|
|
41
42
|
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue)
|
|
42
43
|
|
|
43
44
|
const value = controlledValue !== undefined ? controlledValue : uncontrolledValue
|
|
44
45
|
const setValue = onValueChange || setUncontrolledValue
|
|
45
46
|
|
|
46
47
|
return (
|
|
47
|
-
<AccordionContext.Provider value={{ value, onValueChange: setValue, type }}>
|
|
48
|
+
<AccordionContext.Provider value={{ value, onValueChange: setValue, type, collapsible }}>
|
|
48
49
|
<div ref={ref} className={cn("", className)} {...props}>
|
|
49
50
|
{children}
|
|
50
51
|
</div>
|
|
@@ -54,6 +55,7 @@ const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
|
|
|
54
55
|
)
|
|
55
56
|
Accordion.displayName = "Accordion"
|
|
56
57
|
|
|
58
|
+
|
|
57
59
|
interface AccordionItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
58
60
|
value: string
|
|
59
61
|
}
|
|
@@ -67,6 +69,8 @@ const AccordionItem = React.forwardRef<HTMLDivElement, AccordionItemProps>(
|
|
|
67
69
|
|
|
68
70
|
const toggle = () => {
|
|
69
71
|
if (context.type === "single") {
|
|
72
|
+
// In single mode with collapsible=false, don't allow closing
|
|
73
|
+
if (isOpen && !context.collapsible) return
|
|
70
74
|
context.onValueChange(isOpen ? [] : [value])
|
|
71
75
|
} else {
|
|
72
76
|
context.onValueChange(
|
package/registry/badge.tsx
CHANGED
|
@@ -22,15 +22,12 @@ const badgeVariants = cva(
|
|
|
22
22
|
}
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
className?: string
|
|
29
|
-
children?: React.ReactNode
|
|
30
|
-
}
|
|
25
|
+
interface BadgeProps
|
|
26
|
+
extends React.HTMLAttributes<HTMLSpanElement>,
|
|
27
|
+
VariantProps<typeof badgeVariants> { }
|
|
31
28
|
|
|
32
29
|
/**
|
|
33
|
-
*
|
|
30
|
+
* Badge component for status indicators
|
|
34
31
|
*
|
|
35
32
|
* @example
|
|
36
33
|
* // Default badge
|
|
@@ -38,26 +35,13 @@ interface BadgeBaseProps extends BadgeVariants {
|
|
|
38
35
|
*
|
|
39
36
|
* // Destructive variant
|
|
40
37
|
* <Badge variant="destructive">Error</Badge>
|
|
41
|
-
*
|
|
42
|
-
* // As a link
|
|
43
|
-
* <Badge as="a" href="/status">View Status</Badge>
|
|
44
38
|
*/
|
|
45
|
-
const Badge = React.forwardRef(
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
as,
|
|
49
|
-
className,
|
|
50
|
-
variant,
|
|
51
|
-
...props
|
|
52
|
-
}: BadgeBaseProps & { as?: T } & Omit<React.ComponentPropsWithoutRef<T>, keyof BadgeBaseProps | "as">,
|
|
53
|
-
ref: React.ForwardedRef<React.ElementRef<T>>
|
|
54
|
-
) => {
|
|
55
|
-
const Comp = as || "span"
|
|
56
|
-
|
|
39
|
+
const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
|
|
40
|
+
({ className, variant, ...props }, ref) => {
|
|
57
41
|
return (
|
|
58
|
-
<
|
|
59
|
-
ref={ref
|
|
60
|
-
className={cn(badgeVariants({ variant, className
|
|
42
|
+
<span
|
|
43
|
+
ref={ref}
|
|
44
|
+
className={cn(badgeVariants({ variant }), className)}
|
|
61
45
|
{...props}
|
|
62
46
|
/>
|
|
63
47
|
)
|
package/registry/breadcrumb.tsx
CHANGED
|
@@ -33,15 +33,12 @@ const buttonGroupVariants = cva("inline-flex", {
|
|
|
33
33
|
},
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
className?: string
|
|
40
|
-
children?: React.ReactNode
|
|
41
|
-
}
|
|
36
|
+
interface ButtonGroupProps
|
|
37
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
38
|
+
VariantProps<typeof buttonGroupVariants> { }
|
|
42
39
|
|
|
43
40
|
/**
|
|
44
|
-
*
|
|
41
|
+
* ButtonGroup to group buttons together
|
|
45
42
|
*
|
|
46
43
|
* @example
|
|
47
44
|
* <ButtonGroup>
|
|
@@ -49,31 +46,14 @@ interface ButtonGroupBaseProps extends ButtonGroupVariants {
|
|
|
49
46
|
* <Button>Center</Button>
|
|
50
47
|
* <Button>Right</Button>
|
|
51
48
|
* </ButtonGroup>
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* <ButtonGroup attached={false}>
|
|
55
|
-
* <Button>Spaced</Button>
|
|
56
|
-
* <Button>Buttons</Button>
|
|
57
|
-
* </ButtonGroup>
|
|
58
49
|
*/
|
|
59
|
-
const ButtonGroup = React.forwardRef(
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
as,
|
|
63
|
-
className,
|
|
64
|
-
orientation,
|
|
65
|
-
attached,
|
|
66
|
-
...props
|
|
67
|
-
}: ButtonGroupBaseProps & { as?: T } & Omit<React.ComponentPropsWithoutRef<T>, keyof ButtonGroupBaseProps | "as">,
|
|
68
|
-
ref: React.ForwardedRef<React.ElementRef<T>>
|
|
69
|
-
) => {
|
|
70
|
-
const Comp = as || "div"
|
|
71
|
-
|
|
50
|
+
const ButtonGroup = React.forwardRef<HTMLDivElement, ButtonGroupProps>(
|
|
51
|
+
({ className, orientation, attached, ...props }, ref) => {
|
|
72
52
|
return (
|
|
73
|
-
<
|
|
74
|
-
ref={ref
|
|
53
|
+
<div
|
|
54
|
+
ref={ref}
|
|
75
55
|
role="group"
|
|
76
|
-
className={cn(buttonGroupVariants({ orientation, attached, className
|
|
56
|
+
className={cn(buttonGroupVariants({ orientation, attached }), className)}
|
|
77
57
|
{...props}
|
|
78
58
|
/>
|
|
79
59
|
)
|
package/registry/button.tsx
CHANGED
|
@@ -32,68 +32,42 @@ const buttonVariants = cva(
|
|
|
32
32
|
}
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
children?: React.ReactNode
|
|
35
|
+
interface ButtonProps
|
|
36
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
37
|
+
VariantProps<typeof buttonVariants> {
|
|
38
|
+
asChild?: boolean
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
/**
|
|
43
|
-
*
|
|
42
|
+
* Button component
|
|
44
43
|
*
|
|
45
44
|
* @example
|
|
46
|
-
* //
|
|
45
|
+
* // Default button
|
|
47
46
|
* <Button variant="outline">Click me</Button>
|
|
48
47
|
*
|
|
49
|
-
* // As a link
|
|
50
|
-
* <Button as="a" href="/home" variant="link">Go Home</Button>
|
|
51
|
-
*
|
|
52
48
|
* // With loading state
|
|
53
49
|
* <Button disabled>
|
|
54
50
|
* <LoadingSpinner /> Processing...
|
|
55
51
|
* </Button>
|
|
56
52
|
*/
|
|
57
|
-
const Button = React.forwardRef(
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
as
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}: ButtonBaseProps & { as?: T } & Omit<React.ComponentPropsWithoutRef<T>, keyof ButtonBaseProps | "as">,
|
|
66
|
-
ref: React.ForwardedRef<React.ElementRef<T>>
|
|
67
|
-
) => {
|
|
68
|
-
const Comp = as || "button"
|
|
69
|
-
|
|
70
|
-
// Ensure proper keyboard handling for non-button elements
|
|
71
|
-
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
72
|
-
if (Comp !== "button" && (e.key === "Enter" || e.key === " ")) {
|
|
73
|
-
e.preventDefault()
|
|
74
|
-
; (e.currentTarget as HTMLElement).click()
|
|
75
|
-
}
|
|
76
|
-
// Call original onKeyDown if provided
|
|
77
|
-
const originalOnKeyDown = (props as any).onKeyDown
|
|
78
|
-
if (originalOnKeyDown) {
|
|
79
|
-
originalOnKeyDown(e)
|
|
80
|
-
}
|
|
53
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
54
|
+
({ className, variant, size, asChild = false, children, ...props }, ref) => {
|
|
55
|
+
if (asChild && React.isValidElement(children)) {
|
|
56
|
+
return React.cloneElement(children as React.ReactElement<any>, {
|
|
57
|
+
ref,
|
|
58
|
+
className: cn(buttonVariants({ variant, size }), className),
|
|
59
|
+
...props,
|
|
60
|
+
})
|
|
81
61
|
}
|
|
82
62
|
|
|
83
|
-
// Add role="button" for non-button elements
|
|
84
|
-
const accessibilityProps = Comp !== "button" ? {
|
|
85
|
-
role: "button",
|
|
86
|
-
tabIndex: 0,
|
|
87
|
-
onKeyDown: handleKeyDown,
|
|
88
|
-
} : {}
|
|
89
|
-
|
|
90
63
|
return (
|
|
91
|
-
<
|
|
92
|
-
ref={ref
|
|
93
|
-
className={cn(buttonVariants({ variant, size, className
|
|
94
|
-
{...accessibilityProps}
|
|
64
|
+
<button
|
|
65
|
+
ref={ref}
|
|
66
|
+
className={cn(buttonVariants({ variant, size }), className)}
|
|
95
67
|
{...props}
|
|
96
|
-
|
|
68
|
+
>
|
|
69
|
+
{children}
|
|
70
|
+
</button>
|
|
97
71
|
)
|
|
98
72
|
}
|
|
99
73
|
)
|
package/registry/card.tsx
CHANGED
|
@@ -15,33 +15,17 @@ import { cn } from "@/lib/utils"
|
|
|
15
15
|
* </Card>
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
className
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}: CardBaseProps & { as?: T } & Omit<React.ComponentPropsWithoutRef<T>, keyof CardBaseProps | "as">,
|
|
30
|
-
ref: React.ForwardedRef<React.ElementRef<T>>
|
|
31
|
-
) => {
|
|
32
|
-
const Comp = as || "div"
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<Comp
|
|
36
|
-
ref={ref as any}
|
|
37
|
-
className={cn(
|
|
38
|
-
"rounded-xl border bg-card text-card-foreground shadow",
|
|
39
|
-
className
|
|
40
|
-
)}
|
|
41
|
-
{...props}
|
|
42
|
-
/>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
18
|
+
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
19
|
+
({ className, ...props }, ref) => (
|
|
20
|
+
<div
|
|
21
|
+
ref={ref}
|
|
22
|
+
className={cn(
|
|
23
|
+
"rounded-xl border bg-card text-card-foreground shadow",
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
45
29
|
)
|
|
46
30
|
Card.displayName = "Card"
|
|
47
31
|
|
|
@@ -57,26 +41,16 @@ const CardHeader = React.forwardRef<
|
|
|
57
41
|
))
|
|
58
42
|
CardHeader.displayName = "CardHeader"
|
|
59
43
|
|
|
60
|
-
const CardTitle = React.forwardRef
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<Comp
|
|
73
|
-
ref={ref as any}
|
|
74
|
-
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
75
|
-
{...props}
|
|
76
|
-
/>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
)
|
|
44
|
+
const CardTitle = React.forwardRef<
|
|
45
|
+
HTMLHeadingElement,
|
|
46
|
+
React.HTMLAttributes<HTMLHeadingElement>
|
|
47
|
+
>(({ className, ...props }, ref) => (
|
|
48
|
+
<h3
|
|
49
|
+
ref={ref}
|
|
50
|
+
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
))
|
|
80
54
|
CardTitle.displayName = "CardTitle"
|
|
81
55
|
|
|
82
56
|
const CardDescription = React.forwardRef<
|
package/registry/combobox.tsx
CHANGED
|
@@ -120,9 +120,6 @@ export function Combobox({
|
|
|
120
120
|
)
|
|
121
121
|
) : (
|
|
122
122
|
<div className="flex items-center gap-2">
|
|
123
|
-
{selectedOptions[0].icon && (
|
|
124
|
-
<selectedOptions[0].icon className="h-4 w-4 text-muted-foreground" />
|
|
125
|
-
) /* this effectively forces me to use a variable too */}
|
|
126
123
|
{(() => {
|
|
127
124
|
const Icon = selectedOptions[0].icon
|
|
128
125
|
return Icon ? <Icon className="h-4 w-4 text-muted-foreground" /> : null
|
package/registry/command.tsx
CHANGED
|
@@ -156,11 +156,13 @@ const CommandEmpty = React.forwardRef<HTMLDivElement, CommandEmptyProps>(
|
|
|
156
156
|
({ className, children, ...props }, ref) => {
|
|
157
157
|
const { search, items } = useCommandContext()
|
|
158
158
|
|
|
159
|
-
//
|
|
160
|
-
const
|
|
159
|
+
// Count how many items would be visible with the current search
|
|
160
|
+
const visibleCount = search
|
|
161
|
+
? items.filter(item => item.toLowerCase().includes(search.toLowerCase())).length
|
|
162
|
+
: items.length
|
|
161
163
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
// Only show empty message when user has typed something but no results match
|
|
165
|
+
if (!search || visibleCount > 0) {
|
|
164
166
|
return null
|
|
165
167
|
}
|
|
166
168
|
|
package/registry/container.tsx
CHANGED
|
@@ -18,38 +18,22 @@ const containerVariants = cva("mx-auto w-full px-4", {
|
|
|
18
18
|
},
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
className?: string
|
|
25
|
-
children?: React.ReactNode
|
|
26
|
-
}
|
|
21
|
+
interface ContainerProps
|
|
22
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
23
|
+
VariantProps<typeof containerVariants> { }
|
|
27
24
|
|
|
28
25
|
/**
|
|
29
|
-
*
|
|
26
|
+
* Container for max-width layouts
|
|
30
27
|
*
|
|
31
28
|
* @example
|
|
32
29
|
* <Container size="lg">Content</Container>
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* <Container as="section" size="md">Section content</Container>
|
|
36
30
|
*/
|
|
37
|
-
const Container = React.forwardRef(
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
as,
|
|
41
|
-
className,
|
|
42
|
-
size,
|
|
43
|
-
...props
|
|
44
|
-
}: ContainerBaseProps & { as?: T } & Omit<React.ComponentPropsWithoutRef<T>, keyof ContainerBaseProps | "as">,
|
|
45
|
-
ref: React.ForwardedRef<React.ElementRef<T>>
|
|
46
|
-
) => {
|
|
47
|
-
const Comp = as || "div"
|
|
48
|
-
|
|
31
|
+
const Container = React.forwardRef<HTMLDivElement, ContainerProps>(
|
|
32
|
+
({ className, size, ...props }, ref) => {
|
|
49
33
|
return (
|
|
50
|
-
<
|
|
51
|
-
ref={ref
|
|
52
|
-
className={cn(containerVariants({ size, className
|
|
34
|
+
<div
|
|
35
|
+
ref={ref}
|
|
36
|
+
className={cn(containerVariants({ size }), className)}
|
|
53
37
|
{...props}
|
|
54
38
|
/>
|
|
55
39
|
)
|
package/registry/drawer.tsx
CHANGED
|
@@ -88,19 +88,21 @@ const DrawerClose = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttribut
|
|
|
88
88
|
)
|
|
89
89
|
DrawerClose.displayName = "DrawerClose"
|
|
90
90
|
|
|
91
|
-
// Drawer Overlay
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
// Drawer Overlay (internal)
|
|
92
|
+
interface DrawerOverlayProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
93
|
+
isAnimating: boolean
|
|
94
|
+
}
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
const DrawerOverlay = React.forwardRef<HTMLDivElement, DrawerOverlayProps>(
|
|
97
|
+
({ className, isAnimating, ...props }, ref) => {
|
|
98
|
+
const { onOpenChange } = useDrawer()
|
|
97
99
|
|
|
98
100
|
return (
|
|
99
101
|
<div
|
|
100
102
|
ref={ref}
|
|
101
103
|
className={cn(
|
|
102
|
-
"fixed inset-0 z-50 bg-black/80",
|
|
103
|
-
"
|
|
104
|
+
"fixed inset-0 z-50 bg-black/80 transition-opacity duration-300",
|
|
105
|
+
isAnimating ? "opacity-100" : "opacity-0",
|
|
104
106
|
className
|
|
105
107
|
)}
|
|
106
108
|
onClick={() => onOpenChange(false)}
|
|
@@ -119,6 +121,28 @@ interface DrawerContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
119
121
|
const DrawerContent = React.forwardRef<HTMLDivElement, DrawerContentProps>(
|
|
120
122
|
({ className, children, side = "bottom", ...props }, ref) => {
|
|
121
123
|
const { open, onOpenChange } = useDrawer()
|
|
124
|
+
const [isVisible, setIsVisible] = React.useState(false)
|
|
125
|
+
const [isAnimating, setIsAnimating] = React.useState(false)
|
|
126
|
+
|
|
127
|
+
React.useEffect(() => {
|
|
128
|
+
if (open) {
|
|
129
|
+
// First make visible (off-screen)
|
|
130
|
+
setIsVisible(true)
|
|
131
|
+
// Use a small timeout to ensure the browser has painted the initial state
|
|
132
|
+
const timer = setTimeout(() => {
|
|
133
|
+
setIsAnimating(true)
|
|
134
|
+
}, 10)
|
|
135
|
+
return () => clearTimeout(timer)
|
|
136
|
+
} else {
|
|
137
|
+
// Start close animation
|
|
138
|
+
setIsAnimating(false)
|
|
139
|
+
// Wait for animation to complete before hiding
|
|
140
|
+
const timer = setTimeout(() => {
|
|
141
|
+
setIsVisible(false)
|
|
142
|
+
}, 300)
|
|
143
|
+
return () => clearTimeout(timer)
|
|
144
|
+
}
|
|
145
|
+
}, [open])
|
|
122
146
|
|
|
123
147
|
// Close on Escape
|
|
124
148
|
React.useEffect(() => {
|
|
@@ -142,11 +166,11 @@ const DrawerContent = React.forwardRef<HTMLDivElement, DrawerContentProps>(
|
|
|
142
166
|
}
|
|
143
167
|
}, [open])
|
|
144
168
|
|
|
145
|
-
if (!
|
|
169
|
+
if (!isVisible) return null
|
|
146
170
|
|
|
147
171
|
return (
|
|
148
172
|
<>
|
|
149
|
-
<DrawerOverlay />
|
|
173
|
+
<DrawerOverlay isAnimating={isAnimating} />
|
|
150
174
|
<div
|
|
151
175
|
ref={ref}
|
|
152
176
|
className={cn(
|
|
@@ -154,9 +178,9 @@ const DrawerContent = React.forwardRef<HTMLDivElement, DrawerContentProps>(
|
|
|
154
178
|
"transition-transform duration-300 ease-out",
|
|
155
179
|
side === "bottom" && "inset-x-0 bottom-0 rounded-t-xl border-t",
|
|
156
180
|
side === "top" && "inset-x-0 top-0 rounded-b-xl border-b",
|
|
157
|
-
// Animation
|
|
158
|
-
side === "bottom" && "
|
|
159
|
-
side === "top" && "
|
|
181
|
+
// Animation states
|
|
182
|
+
side === "bottom" && (isAnimating ? "translate-y-0" : "translate-y-full"),
|
|
183
|
+
side === "top" && (isAnimating ? "translate-y-0" : "-translate-y-full"),
|
|
160
184
|
className
|
|
161
185
|
)}
|
|
162
186
|
{...props}
|