Skip to content

Commit c33e979

Browse files
committed
Moar shadcn
1 parent 3902bc9 commit c33e979

File tree

12 files changed

+601
-0
lines changed

12 files changed

+601
-0
lines changed

app/components/ui/alert.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {cva, type VariantProps} from 'class-variance-authority'
2+
import * as React from 'react'
3+
import {cn} from '~/lib/utils'
4+
5+
const alertVariants = cva(
6+
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',
7+
{
8+
variants: {
9+
variant: {
10+
default: 'bg-background text-foreground',
11+
destructive:
12+
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
13+
},
14+
},
15+
defaultVariants: {
16+
variant: 'default',
17+
},
18+
},
19+
)
20+
21+
const Alert = React.forwardRef<
22+
HTMLDivElement,
23+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
24+
>(({className, variant, ...props}, ref) => (
25+
<div
26+
ref={ref}
27+
role="alert"
28+
className={cn(alertVariants({variant}), className)}
29+
{...props}
30+
/>
31+
))
32+
Alert.displayName = 'Alert'
33+
34+
const AlertTitle = React.forwardRef<
35+
HTMLParagraphElement,
36+
React.HTMLAttributes<HTMLHeadingElement>
37+
>(({className, ...props}, ref) => (
38+
<h5
39+
ref={ref}
40+
className={cn('mb-1 font-medium leading-none tracking-tight', className)}
41+
{...props}
42+
/>
43+
))
44+
AlertTitle.displayName = 'AlertTitle'
45+
46+
const AlertDescription = React.forwardRef<
47+
HTMLParagraphElement,
48+
React.HTMLAttributes<HTMLParagraphElement>
49+
>(({className, ...props}, ref) => (
50+
<div
51+
ref={ref}
52+
className={cn('text-sm [&_p]:leading-relaxed', className)}
53+
{...props}
54+
/>
55+
))
56+
AlertDescription.displayName = 'AlertDescription'
57+
58+
export {Alert, AlertDescription, AlertTitle}

app/components/ui/badge.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {cva, type VariantProps} from 'class-variance-authority'
2+
import type * as React from 'react'
3+
import {cn} from '~/lib/utils'
4+
5+
const badgeVariants = cva(
6+
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
7+
{
8+
variants: {
9+
variant: {
10+
default:
11+
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
12+
secondary:
13+
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
14+
destructive:
15+
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
16+
outline: 'text-foreground',
17+
},
18+
},
19+
defaultVariants: {
20+
variant: 'default',
21+
},
22+
}
23+
)
24+
25+
export interface BadgeProps
26+
extends React.HTMLAttributes<HTMLDivElement>,
27+
VariantProps<typeof badgeVariants> {}
28+
29+
function Badge({className, variant, ...props}: BadgeProps) {
30+
return <div className={cn(badgeVariants({variant}), className)} {...props} />
31+
}
32+
33+
export {Badge, badgeVariants}

app/components/ui/button.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {Slot} from '@radix-ui/react-slot'
2+
import {cva, type VariantProps} from 'class-variance-authority'
3+
import * as React from 'react'
4+
import {cn} from '~/lib/utils'
5+
6+
const buttonVariants = cva(
7+
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
8+
{
9+
variants: {
10+
variant: {
11+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
12+
destructive:
13+
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
14+
outline:
15+
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
16+
secondary:
17+
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
18+
ghost: 'hover:bg-accent hover:text-accent-foreground',
19+
link: 'text-primary underline-offset-4 hover:underline',
20+
},
21+
size: {
22+
default: 'h-10 px-4 py-2',
23+
sm: 'h-9 rounded-md px-3',
24+
lg: 'h-11 rounded-md px-8',
25+
icon: 'h-10 w-10',
26+
},
27+
},
28+
defaultVariants: {
29+
variant: 'default',
30+
size: 'default',
31+
},
32+
}
33+
)
34+
35+
export interface ButtonProps
36+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
37+
VariantProps<typeof buttonVariants> {
38+
asChild?: boolean
39+
}
40+
41+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
42+
({className, variant, size, asChild = false, ...props}, ref) => {
43+
const Comp = asChild ? Slot : 'button'
44+
return (
45+
<Comp
46+
className={cn(buttonVariants({variant, size, className}))}
47+
ref={ref}
48+
{...props}
49+
/>
50+
)
51+
}
52+
)
53+
Button.displayName = 'Button'
54+
55+
export {Button, buttonVariants}

app/components/ui/card.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import * as React from 'react'
2+
import {cn} from '~/lib/utils'
3+
4+
const Card = React.forwardRef<
5+
HTMLDivElement,
6+
React.HTMLAttributes<HTMLDivElement>
7+
>(({className, ...props}, ref) => (
8+
<div
9+
ref={ref}
10+
className={cn(
11+
'rounded-lg border bg-card text-card-foreground shadow-sm',
12+
className
13+
)}
14+
{...props}
15+
/>
16+
))
17+
Card.displayName = 'Card'
18+
19+
const CardHeader = React.forwardRef<
20+
HTMLDivElement,
21+
React.HTMLAttributes<HTMLDivElement>
22+
>(({className, ...props}, ref) => (
23+
<div
24+
ref={ref}
25+
className={cn('flex flex-col space-y-1.5 p-6', className)}
26+
{...props}
27+
/>
28+
))
29+
CardHeader.displayName = 'CardHeader'
30+
31+
const CardTitle = React.forwardRef<
32+
HTMLParagraphElement,
33+
React.HTMLAttributes<HTMLHeadingElement>
34+
>(({className, ...props}, ref) => (
35+
<h3
36+
ref={ref}
37+
className={cn(
38+
'text-2xl font-semibold leading-none tracking-tight',
39+
className
40+
)}
41+
{...props}
42+
/>
43+
))
44+
CardTitle.displayName = 'CardTitle'
45+
46+
const CardDescription = React.forwardRef<
47+
HTMLParagraphElement,
48+
React.HTMLAttributes<HTMLParagraphElement>
49+
>(({className, ...props}, ref) => (
50+
<p
51+
ref={ref}
52+
className={cn('text-sm text-muted-foreground', className)}
53+
{...props}
54+
/>
55+
))
56+
CardDescription.displayName = 'CardDescription'
57+
58+
const CardContent = React.forwardRef<
59+
HTMLDivElement,
60+
React.HTMLAttributes<HTMLDivElement>
61+
>(({className, ...props}, ref) => (
62+
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
63+
))
64+
CardContent.displayName = 'CardContent'
65+
66+
const CardFooter = React.forwardRef<
67+
HTMLDivElement,
68+
React.HTMLAttributes<HTMLDivElement>
69+
>(({className, ...props}, ref) => (
70+
<div
71+
ref={ref}
72+
className={cn('flex items-center p-6 pt-0', className)}
73+
{...props}
74+
/>
75+
))
76+
CardFooter.displayName = 'CardFooter'
77+
78+
export {Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle}

app/components/ui/command.tsx

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import type {DialogProps} from '@radix-ui/react-dialog'
2+
import {Command as CommandPrimitive} from 'cmdk'
3+
import {Search} from 'lucide-react'
4+
import * as React from 'react'
5+
import {Dialog, DialogContent} from '~/components/ui/dialog'
6+
import {cn} from '~/lib/utils'
7+
8+
const Command = React.forwardRef<
9+
React.ElementRef<typeof CommandPrimitive>,
10+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
11+
>(({className, ...props}, ref) => (
12+
<CommandPrimitive
13+
ref={ref}
14+
className={cn(
15+
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
16+
className
17+
)}
18+
{...props}
19+
/>
20+
))
21+
Command.displayName = CommandPrimitive.displayName
22+
23+
interface CommandDialogProps extends DialogProps {}
24+
25+
const CommandDialog = ({children, ...props}: CommandDialogProps) => {
26+
return (
27+
<Dialog {...props}>
28+
<DialogContent className="overflow-hidden p-0 shadow-lg">
29+
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
30+
{children}
31+
</Command>
32+
</DialogContent>
33+
</Dialog>
34+
)
35+
}
36+
37+
const CommandInput = React.forwardRef<
38+
React.ElementRef<typeof CommandPrimitive.Input>,
39+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
40+
>(({className, ...props}, ref) => (
41+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
42+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
43+
<CommandPrimitive.Input
44+
ref={ref}
45+
className={cn(
46+
'flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
47+
className
48+
)}
49+
{...props}
50+
/>
51+
</div>
52+
))
53+
54+
CommandInput.displayName = CommandPrimitive.Input.displayName
55+
56+
const CommandList = React.forwardRef<
57+
React.ElementRef<typeof CommandPrimitive.List>,
58+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
59+
>(({className, ...props}, ref) => (
60+
<CommandPrimitive.List
61+
ref={ref}
62+
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
63+
{...props}
64+
/>
65+
))
66+
67+
CommandList.displayName = CommandPrimitive.List.displayName
68+
69+
const CommandEmpty = React.forwardRef<
70+
React.ElementRef<typeof CommandPrimitive.Empty>,
71+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
72+
>((props, ref) => (
73+
<CommandPrimitive.Empty
74+
ref={ref}
75+
className="py-6 text-center text-sm"
76+
{...props}
77+
/>
78+
))
79+
80+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
81+
82+
const CommandGroup = React.forwardRef<
83+
React.ElementRef<typeof CommandPrimitive.Group>,
84+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
85+
>(({className, ...props}, ref) => (
86+
<CommandPrimitive.Group
87+
ref={ref}
88+
className={cn(
89+
'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
90+
className
91+
)}
92+
{...props}
93+
/>
94+
))
95+
96+
CommandGroup.displayName = CommandPrimitive.Group.displayName
97+
98+
const CommandSeparator = React.forwardRef<
99+
React.ElementRef<typeof CommandPrimitive.Separator>,
100+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
101+
>(({className, ...props}, ref) => (
102+
<CommandPrimitive.Separator
103+
ref={ref}
104+
className={cn('-mx-1 h-px bg-border', className)}
105+
{...props}
106+
/>
107+
))
108+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
109+
110+
const CommandItem = React.forwardRef<
111+
React.ElementRef<typeof CommandPrimitive.Item>,
112+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
113+
>(({className, ...props}, ref) => (
114+
<CommandPrimitive.Item
115+
ref={ref}
116+
className={cn(
117+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50",
118+
className
119+
)}
120+
{...props}
121+
/>
122+
))
123+
124+
CommandItem.displayName = CommandPrimitive.Item.displayName
125+
126+
const CommandShortcut = ({
127+
className,
128+
...props
129+
}: React.HTMLAttributes<HTMLSpanElement>) => {
130+
return (
131+
<span
132+
className={cn(
133+
'ml-auto text-xs tracking-widest text-muted-foreground',
134+
className
135+
)}
136+
{...props}
137+
/>
138+
)
139+
}
140+
CommandShortcut.displayName = 'CommandShortcut'
141+
142+
export {
143+
Command,
144+
CommandDialog,
145+
CommandEmpty,
146+
CommandGroup,
147+
CommandInput,
148+
CommandItem,
149+
CommandList,
150+
CommandSeparator,
151+
CommandShortcut,
152+
}

0 commit comments

Comments
 (0)