Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 74 additions & 14 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components/ui/accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import * as React from 'react';

import * as AccordionPrimitive from '@radix-ui/react-accordion';
import { ChevronDownIcon } from 'lucide-react';
import { Accordion as AccordionPrimitive } from 'radix-ui';

import { cn } from '@/lib/utils';

Expand Down
88 changes: 66 additions & 22 deletions components/ui/alert-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import * as React from 'react';

import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
import { AlertDialog as AlertDialogPrimitive } from 'radix-ui';

import { cn } from '@/lib/utils';

import { buttonVariants } from '@/components/ui/button';
import { Button } from '@/components/ui/button';

function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
Expand All @@ -30,7 +30,7 @@ function AlertDialogOverlay({
<AlertDialogPrimitive.Overlay
data-slot="alert-dialog-overlay"
className={cn(
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
className
)}
{...props}
Expand All @@ -40,15 +40,19 @@ function AlertDialogOverlay({

function AlertDialogContent({
className,
size = 'default',
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
}: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {
size?: 'default' | 'sm';
}) {
return (
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
data-slot="alert-dialog-content"
data-size={size}
className={cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
'group/alert-dialog-content bg-background data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg',
className
)}
{...props}
Expand All @@ -61,7 +65,10 @@ function AlertDialogHeader({ className, ...props }: React.ComponentProps<'div'>)
return (
<div
data-slot="alert-dialog-header"
className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
className={cn(
'grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]',
className
)}
{...props}
/>
);
Expand All @@ -71,7 +78,10 @@ function AlertDialogFooter({ className, ...props }: React.ComponentProps<'div'>)
return (
<div
data-slot="alert-dialog-footer"
className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
className={cn(
'flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end',
className
)}
{...props}
/>
);
Expand All @@ -84,7 +94,10 @@ function AlertDialogTitle({
return (
<AlertDialogPrimitive.Title
data-slot="alert-dialog-title"
className={cn('text-lg font-semibold', className)}
className={cn(
'text-lg font-semibold sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2',
className
)}
{...props}
/>
);
Expand All @@ -103,35 +116,66 @@ function AlertDialogDescription({
);
}

function AlertDialogMedia({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="alert-dialog-media"
className={cn(
"bg-muted mb-2 inline-flex size-16 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8",
className
)}
{...props}
/>
);
}

function AlertDialogAction({
className,
variant = 'default',
size = 'default',
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
return <AlertDialogPrimitive.Action className={cn(buttonVariants(), className)} {...props} />;
}: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>) {
return (
<Button variant={variant} size={size} asChild>
<AlertDialogPrimitive.Action
data-slot="alert-dialog-action"
className={cn(className)}
{...props}
/>
</Button>
);
}

function AlertDialogCancel({
className,
variant = 'outline',
size = 'default',
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>) {
return (
<AlertDialogPrimitive.Cancel
className={cn(buttonVariants({ variant: 'outline' }), className)}
{...props}
/>
<Button variant={variant} size={size} asChild>
<AlertDialogPrimitive.Cancel
data-slot="alert-dialog-cancel"
className={cn(className)}
{...props}
/>
</Button>
);
}

export {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogHeader,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogOverlay,
AlertDialogPortal,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
AlertDialogTrigger,
};
4 changes: 2 additions & 2 deletions components/ui/alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { type VariantProps, cva } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const alertVariants = cva(
'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',
'relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
{
variants: {
variant: {
default: 'bg-card text-card-foreground',
destructive:
'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',
'bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current',
},
},
defaultVariants: {
Expand Down
2 changes: 1 addition & 1 deletion components/ui/aspect-ratio.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio';
import { AspectRatio as AspectRatioPrimitive } from 'radix-ui';

function AspectRatio({ ...props }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />;
Expand Down
65 changes: 60 additions & 5 deletions components/ui/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@

import * as React from 'react';

import * as AvatarPrimitive from '@radix-ui/react-avatar';
import { Avatar as AvatarPrimitive } from 'radix-ui';

import { cn } from '@/lib/utils';

function Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
function Avatar({
className,
size = 'default',
...props
}: React.ComponentProps<typeof AvatarPrimitive.Root> & {
size?: 'default' | 'sm' | 'lg';
}) {
return (
<AvatarPrimitive.Root
data-slot="avatar"
className={cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', className)}
data-size={size}
className={cn(
'group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6',
className
)}
{...props}
/>
);
Expand All @@ -33,10 +43,55 @@ function AvatarFallback({
return (
<AvatarPrimitive.Fallback
data-slot="avatar-fallback"
className={cn('bg-muted flex size-full items-center justify-center rounded-full', className)}
className={cn(
'bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs',
className
)}
{...props}
/>
);
}

function AvatarBadge({ className, ...props }: React.ComponentProps<'span'>) {
return (
<span
data-slot="avatar-badge"
className={cn(
'bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full ring-2 select-none',
'group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden',
'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2',
'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2',
className
)}
{...props}
/>
);
}

function AvatarGroup({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="avatar-group"
className={cn(
'group/avatar-group *:data-[slot=avatar]:ring-background flex -space-x-2 *:data-[slot=avatar]:ring-2',
className
)}
{...props}
/>
);
}

function AvatarGroupCount({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="avatar-group-count"
className={cn(
'bg-muted text-muted-foreground ring-background relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3',
className
)}
{...props}
/>
);
}

export { Avatar, AvatarImage, AvatarFallback };
export { Avatar, AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup, AvatarGroupCount };
27 changes: 17 additions & 10 deletions components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import * as React from 'react';

import { Slot } from '@radix-ui/react-slot';
import { type VariantProps, cva } from 'class-variance-authority';
import { Slot } from 'radix-ui';

import { cn } from '@/lib/utils';

const badgeVariants = cva(
'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',
'inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3',
{
variants: {
variant: {
default: 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
secondary:
'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
default: 'bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
secondary: 'bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
destructive:
'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',
outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
'bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90',
outline:
'border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
ghost: '[a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
link: 'text-primary underline-offset-4 [a&]:hover:underline',
},
},
defaultVariants: {
Expand All @@ -26,14 +28,19 @@ const badgeVariants = cva(

function Badge({
className,
variant,
variant = 'default',
asChild = false,
...props
}: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : 'span';
const Comp = asChild ? Slot.Root : 'span';

return (
<Comp data-slot="badge" className={cn(badgeVariants({ variant }), className)} {...props} />
<Comp
data-slot="badge"
data-variant={variant}
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
);
}

Expand Down
4 changes: 2 additions & 2 deletions components/ui/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';

import { Slot } from '@radix-ui/react-slot';
import { ChevronRight, MoreHorizontal } from 'lucide-react';
import { Slot } from 'radix-ui';

import { cn } from '@/lib/utils';

Expand Down Expand Up @@ -39,7 +39,7 @@ function BreadcrumbLink({
}: React.ComponentProps<'a'> & {
asChild?: boolean;
}) {
const Comp = asChild ? Slot : 'a';
const Comp = asChild ? Slot.Root : 'a';

return (
<Comp
Expand Down
8 changes: 4 additions & 4 deletions components/ui/button-group.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Slot } from '@radix-ui/react-slot';
import { type VariantProps, cva } from 'class-variance-authority';
import { Slot } from 'radix-ui';

import { cn } from '@/lib/utils';

import { Separator } from '@/components/ui/separator';

const buttonGroupVariants = cva(
"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",
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
{
variants: {
orientation: {
Expand Down Expand Up @@ -45,7 +45,7 @@ function ButtonGroupText({
}: React.ComponentProps<'div'> & {
asChild?: boolean;
}) {
const Comp = asChild ? Slot : 'div';
const Comp = asChild ? Slot.Root : 'div';

return (
<Comp
Expand All @@ -68,7 +68,7 @@ function ButtonGroupSeparator({
data-slot="button-group-separator"
orientation={orientation}
className={cn(
'bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto',
'bg-input relative m-0! self-stretch data-[orientation=vertical]:h-auto',
className
)}
{...props}
Expand Down
Loading