Skip to content

Commit c930432

Browse files
committed
✨ Add new Shadcn components
1 parent 1d95d01 commit c930432

30 files changed

+1875
-997
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import * as React from "react"
2+
import { cva, type VariantProps } from "class-variance-authority"
3+
4+
import { cn } from "@/lib/utils"
5+
6+
const alertVariants = cva(
7+
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
8+
{
9+
variants: {
10+
variant: {
11+
default: "bg-card text-card-foreground",
12+
destructive:
13+
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
14+
},
15+
},
16+
defaultVariants: {
17+
variant: "default",
18+
},
19+
}
20+
)
21+
22+
function Alert({
23+
className,
24+
variant,
25+
...props
26+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
27+
return (
28+
<div
29+
data-slot="alert"
30+
role="alert"
31+
className={cn(alertVariants({ variant }), className)}
32+
{...props}
33+
/>
34+
)
35+
}
36+
37+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38+
return (
39+
<div
40+
data-slot="alert-title"
41+
className={cn(
42+
"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
43+
className
44+
)}
45+
{...props}
46+
/>
47+
)
48+
}
49+
50+
function AlertDescription({
51+
className,
52+
...props
53+
}: React.ComponentProps<"div">) {
54+
return (
55+
<div
56+
data-slot="alert-description"
57+
className={cn(
58+
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
59+
className
60+
)}
61+
{...props}
62+
/>
63+
)
64+
}
65+
66+
export { Alert, AlertTitle, AlertDescription }
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import * as React from "react"
2+
import * as AvatarPrimitive from "@radix-ui/react-avatar"
3+
4+
import { cn } from "@/lib/utils"
5+
6+
function Avatar({
7+
className,
8+
...props
9+
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
10+
return (
11+
<AvatarPrimitive.Root
12+
data-slot="avatar"
13+
className={cn(
14+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
15+
className
16+
)}
17+
{...props}
18+
/>
19+
)
20+
}
21+
22+
function AvatarImage({
23+
className,
24+
...props
25+
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
26+
return (
27+
<AvatarPrimitive.Image
28+
data-slot="avatar-image"
29+
className={cn("aspect-square size-full", className)}
30+
{...props}
31+
/>
32+
)
33+
}
34+
35+
function AvatarFallback({
36+
className,
37+
...props
38+
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
39+
return (
40+
<AvatarPrimitive.Fallback
41+
data-slot="avatar-fallback"
42+
className={cn(
43+
"bg-muted flex size-full items-center justify-center rounded-full",
44+
className
45+
)}
46+
{...props}
47+
/>
48+
)
49+
}
50+
51+
export { Avatar, AvatarImage, AvatarFallback }
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const badgeVariants = cva(
8+
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
9+
{
10+
variants: {
11+
variant: {
12+
default:
13+
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
14+
secondary:
15+
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
16+
destructive:
17+
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
18+
outline:
19+
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20+
},
21+
},
22+
defaultVariants: {
23+
variant: "default",
24+
},
25+
}
26+
)
27+
28+
function Badge({
29+
className,
30+
variant,
31+
asChild = false,
32+
...props
33+
}: React.ComponentProps<"span"> &
34+
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
35+
const Comp = asChild ? Slot : "span"
36+
37+
return (
38+
<Comp
39+
data-slot="badge"
40+
className={cn(badgeVariants({ variant }), className)}
41+
{...props}
42+
/>
43+
)
44+
}
45+
46+
export { Badge, badgeVariants }
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { Slot } from "@radix-ui/react-slot"
2+
import { cva, type VariantProps } from "class-variance-authority"
3+
4+
import { cn } from "@/lib/utils"
5+
import { Separator } from "@/components/ui/separator"
6+
7+
const buttonGroupVariants = cva(
8+
"flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
9+
{
10+
variants: {
11+
orientation: {
12+
horizontal:
13+
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
14+
vertical:
15+
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
16+
},
17+
},
18+
defaultVariants: {
19+
orientation: "horizontal",
20+
},
21+
}
22+
)
23+
24+
function ButtonGroup({
25+
className,
26+
orientation,
27+
...props
28+
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
29+
return (
30+
<div
31+
role="group"
32+
data-slot="button-group"
33+
data-orientation={orientation}
34+
className={cn(buttonGroupVariants({ orientation }), className)}
35+
{...props}
36+
/>
37+
)
38+
}
39+
40+
function ButtonGroupText({
41+
className,
42+
asChild = false,
43+
...props
44+
}: React.ComponentProps<"div"> & {
45+
asChild?: boolean
46+
}) {
47+
const Comp = asChild ? Slot : "div"
48+
49+
return (
50+
<Comp
51+
className={cn(
52+
"bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
53+
className
54+
)}
55+
{...props}
56+
/>
57+
)
58+
}
59+
60+
function ButtonGroupSeparator({
61+
className,
62+
orientation = "vertical",
63+
...props
64+
}: React.ComponentProps<typeof Separator>) {
65+
return (
66+
<Separator
67+
data-slot="button-group-separator"
68+
orientation={orientation}
69+
className={cn(
70+
"bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
71+
className
72+
)}
73+
{...props}
74+
/>
75+
)
76+
}
77+
78+
export {
79+
ButtonGroup,
80+
ButtonGroupSeparator,
81+
ButtonGroupText,
82+
buttonGroupVariants,
83+
}
Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,60 @@
1-
import type { ButtonProps as ChakraButtonProps } from "@chakra-ui/react"
2-
import {
3-
AbsoluteCenter,
4-
Button as ChakraButton,
5-
Span,
6-
Spinner,
7-
} from "@chakra-ui/react"
81
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
94

10-
interface ButtonLoadingProps {
11-
loading?: boolean
12-
loadingText?: React.ReactNode
13-
}
14-
15-
export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {}
5+
import { cn } from "@/lib/utils"
166

17-
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
18-
function Button(props, ref) {
19-
const { loading, disabled, loadingText, children, ...rest } = props
20-
return (
21-
<ChakraButton disabled={loading || disabled} ref={ref} {...rest}>
22-
{loading && !loadingText ? (
23-
<>
24-
<AbsoluteCenter display="inline-flex">
25-
<Spinner size="inherit" color="inherit" />
26-
</AbsoluteCenter>
27-
<Span opacity={0}>{children}</Span>
28-
</>
29-
) : loading && loadingText ? (
30-
<>
31-
<Spinner size="inherit" color="inherit" />
32-
{loadingText}
33-
</>
34-
) : (
35-
children
36-
)}
37-
</ChakraButton>
38-
)
39-
},
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9+
{
10+
variants: {
11+
variant: {
12+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
13+
destructive:
14+
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
15+
outline:
16+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
17+
secondary:
18+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
19+
ghost:
20+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
21+
link: "text-primary underline-offset-4 hover:underline",
22+
},
23+
size: {
24+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
25+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
26+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
27+
icon: "size-9",
28+
"icon-sm": "size-8",
29+
"icon-lg": "size-10",
30+
},
31+
},
32+
defaultVariants: {
33+
variant: "default",
34+
size: "default",
35+
},
36+
}
4037
)
38+
39+
function Button({
40+
className,
41+
variant,
42+
size,
43+
asChild = false,
44+
...props
45+
}: React.ComponentProps<"button"> &
46+
VariantProps<typeof buttonVariants> & {
47+
asChild?: boolean
48+
}) {
49+
const Comp = asChild ? Slot : "button"
50+
51+
return (
52+
<Comp
53+
data-slot="button"
54+
className={cn(buttonVariants({ variant, size, className }))}
55+
{...props}
56+
/>
57+
)
58+
}
59+
60+
export { Button, buttonVariants }

0 commit comments

Comments
 (0)