From cde8adc6bd93d2b8f57a457239f2acc14d3403ec Mon Sep 17 00:00:00 2001 From: Sahaj Jain <82111591+jnsahaj@users.noreply.github.com> Date: Thu, 5 Mar 2026 21:22:27 +0530 Subject: [PATCH] Chore/update shadcn components (#266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: update shadcn/ui components to v3.8.5 and migrate to unified radix-ui - Update shadcn CLI from 2.5.0 to 3.8.5 - Update 45 standard UI components to latest versions - Migrate from 28 individual @radix-ui/react-* packages to unified radix-ui - Update react-resizable-panels from v2 to v4 (direction→orientation, onLayout→onLayoutChanged, ref→panelRef, numeric sizes→percentage strings) - Fix revola.tsx runtime error by sharing shouldUseDialog via React context instead of independent useMediaQuery calls in each sub-component - Preserve custom components: sidebar.tsx, base-ui-tabs.tsx, revola.tsx - Re-apply button accent variant after component update - Fix direct Radix imports in theme-toggle, user-profile-dropdown, data-table-view-options - Fix registryItemSchema import (shadcn/registry→shadcn/schema) - Fix ScrollArea viewPortClassName removal (use data-slot CSS selector) Co-Authored-By: Claude Opus 4.6 * fix: resolve CSS specificity regressions from shadcn v3.8.5 update - button: remove has-[>svg]:px-* variants that override custom padding, restore lg px-8 - dialog: revert sm:max-w-lg to max-w-lg so consumer max-w overrides work - separator: use JS conditionals instead of data-attribute variants for orientation - tabs: restore old TabsTrigger styles to prevent dark mode border overrides - select consumers: use size="sm" prop instead of className h-8 override Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- app/r/themes/[id]/route.ts | 2 +- components/block-viewer.tsx | 16 +- .../action-bar/components/theme-toggle.tsx | 2 +- components/editor/css-import-dialog.tsx | 2 +- components/editor/editor.tsx | 10 +- components/editor/font-picker.tsx | 2 +- components/examples/mail/components/mail.tsx | 29 +- .../components/data-table-pagination.tsx | 2 +- .../components/data-table-view-options.tsx | 2 +- components/ui/accordion.tsx | 107 +- components/ui/alert-dialog.tsx | 277 +- components/ui/alert.tsx | 93 +- components/ui/aspect-ratio.tsx | 12 +- components/ui/avatar.tsx | 147 +- components/ui/badge.tsx | 46 +- components/ui/breadcrumb.tsx | 168 +- components/ui/button.tsx | 72 +- components/ui/calendar.tsx | 251 +- components/ui/card.tsx | 137 +- components/ui/carousel.tsx | 349 +- components/ui/chart.tsx | 372 +- components/ui/checkbox.tsx | 52 +- components/ui/collapsible.tsx | 51 +- components/ui/command.tsx | 279 +- components/ui/context-menu.tsx | 377 +- components/ui/dialog.tsx | 222 +- components/ui/drawer.tsx | 186 +- components/ui/dropdown-menu.tsx | 388 +- components/ui/form.tsx | 155 +- components/ui/hover-card.tsx | 61 +- components/ui/input-otp.tsx | 106 +- components/ui/input.tsx | 37 +- components/ui/label.tsx | 40 +- components/ui/menubar.tsx | 432 ++- components/ui/navigation-menu.tsx | 260 +- components/ui/pagination.tsx | 191 +- components/ui/popover.tsx | 104 +- components/ui/progress.tsx | 51 +- components/ui/radio-group.tsx | 55 +- components/ui/resizable.tsx | 76 +- components/ui/revola.tsx | 46 +- components/ui/scroll-area.tsx | 96 +- components/ui/select.tsx | 292 +- components/ui/separator.tsx | 47 +- components/ui/sheet.tsx | 236 +- components/ui/sidebar.tsx | 12 +- components/ui/skeleton.tsx | 14 +- components/ui/slider.tsx | 83 +- components/ui/sonner.tsx | 45 +- components/ui/switch.tsx | 52 +- components/ui/table.tsx | 193 +- components/ui/tabs.tsx | 129 +- components/ui/textarea.tsx | 20 +- components/ui/toast.tsx | 2 +- components/ui/toggle-group.tsx | 100 +- components/ui/toggle.tsx | 54 +- components/ui/tooltip.tsx | 75 +- components/user-profile-dropdown.tsx | 2 +- package.json | 37 +- pnpm-lock.yaml | 3283 ++++++++++++++--- 60 files changed, 6533 insertions(+), 3506 deletions(-) diff --git a/app/r/themes/[id]/route.ts b/app/r/themes/[id]/route.ts index 0baed515..a6c4d8d2 100644 --- a/app/r/themes/[id]/route.ts +++ b/app/r/themes/[id]/route.ts @@ -2,7 +2,7 @@ import { NextResponse } from "next/server"; import { getTheme } from "@/actions/themes"; import { generateThemeRegistryItemFromStyles } from "@/utils/registry/themes"; -import { registryItemSchema } from "shadcn/registry"; +import { registryItemSchema } from "shadcn/schema"; import { getBuiltInThemeStyles } from "@/utils/theme-preset-helper"; import { ThemeStyles } from "@/types/theme"; diff --git a/components/block-viewer.tsx b/components/block-viewer.tsx index 949e929f..4026a31c 100644 --- a/components/block-viewer.tsx +++ b/components/block-viewer.tsx @@ -1,7 +1,7 @@ "use client"; import { Monitor, Smartphone, Tablet } from "lucide-react"; import React from "react"; -import { ImperativePanelHandle } from "react-resizable-panels"; +import { PanelImperativeHandle } from "react-resizable-panels"; import { ComponentErrorBoundary } from "@/components/error-boundary"; import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable"; @@ -9,7 +9,7 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { cn } from "@/lib/utils"; type BlockViewerContext = { - resizablePanelRef: React.RefObject; + resizablePanelRef: React.RefObject; toggleValue: string; setToggleValue: (value: string) => void; }; @@ -25,7 +25,7 @@ function useBlockViewer() { } function BlockViewerProvider({ children }: { children: React.ReactNode }) { - const resizablePanelRef = React.useRef(null); + const resizablePanelRef = React.useRef(null); const [toggleValue, setToggleValue] = React.useState("100"); return ( @@ -151,20 +151,20 @@ export function BlockViewerDisplay({ className={cn("size-full min-h-0 gap-4 overflow-hidden", className)} {...props} > - +
{children} - +
diff --git a/components/editor/action-bar/components/theme-toggle.tsx b/components/editor/action-bar/components/theme-toggle.tsx index 3938c8ef..8be2ecfd 100644 --- a/components/editor/action-bar/components/theme-toggle.tsx +++ b/components/editor/action-bar/components/theme-toggle.tsx @@ -1,7 +1,7 @@ import { useTheme } from "@/components/theme-provider"; import { TooltipWrapper } from "@/components/tooltip-wrapper"; import { cn } from "@/lib/utils"; -import * as SwitchPrimitives from "@radix-ui/react-switch"; +import { Switch as SwitchPrimitives } from "radix-ui"; import { Moon, Sun } from "lucide-react"; export function ThemeToggle() { diff --git a/components/editor/css-import-dialog.tsx b/components/editor/css-import-dialog.tsx index dcd10e83..206bbf90 100644 --- a/components/editor/css-import-dialog.tsx +++ b/components/editor/css-import-dialog.tsx @@ -58,7 +58,7 @@ const CssImportDialog: React.FC = ({ open, onOpenChange, o return ( - + Import Custom CSS diff --git a/components/editor/editor.tsx b/components/editor/editor.tsx index 5ac35fa3..41b97b5f 100644 --- a/components/editor/editor.tsx +++ b/components/editor/editor.tsx @@ -105,11 +105,11 @@ const Editor: React.FC = ({ themePromise }) => {
- +
@@ -121,7 +121,7 @@ const Editor: React.FC = ({ themePromise }) => {
- +
diff --git a/components/editor/font-picker.tsx b/components/editor/font-picker.tsx index 341fbd8a..492d42d2 100644 --- a/components/editor/font-picker.tsx +++ b/components/editor/font-picker.tsx @@ -210,7 +210,7 @@ export function FontPicker({ value={selectedCategory} onValueChange={(value) => setSelectedCategory(value as FilterFontCategory)} > - + diff --git a/components/examples/mail/components/mail.tsx b/components/examples/mail/components/mail.tsx index 36f17fba..72d2ead7 100644 --- a/components/examples/mail/components/mail.tsx +++ b/components/examples/mail/components/mail.tsx @@ -51,25 +51,22 @@ export function Mail({ return ( { - document.cookie = `react-resizable-panels:layout:mail=${JSON.stringify(sizes)}`; + orientation="horizontal" + onLayoutChanged={(layout) => { + document.cookie = `react-resizable-panels:layout:mail=${JSON.stringify(layout)}`; }} className="h-full max-h-[800px] items-stretch" > { - setIsCollapsed(true); - document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(true)}`; - }} - onResize={() => { - setIsCollapsed(false); - document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(false)}`; + minSize="15%" + maxSize="20%" + onResize={(panelSize) => { + const collapsed = panelSize.asPercentage <= navCollapsedSize; + setIsCollapsed(collapsed); + document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(collapsed)}`; }} className={cn(isCollapsed && "min-w-[50px] transition-all duration-300 ease-in-out")} > @@ -161,7 +158,7 @@ export function Mail({ /> - +

Inbox

@@ -188,7 +185,7 @@ export function Mail({ - + item.id === mail.selected) || null} /> diff --git a/components/examples/tasks/components/data-table-pagination.tsx b/components/examples/tasks/components/data-table-pagination.tsx index 03ceeb7f..03a0ffc0 100644 --- a/components/examples/tasks/components/data-table-pagination.tsx +++ b/components/examples/tasks/components/data-table-pagination.tsx @@ -37,7 +37,7 @@ export function DataTablePagination({ table.setPageSize(Number(value)); }} > - + diff --git a/components/examples/tasks/components/data-table-view-options.tsx b/components/examples/tasks/components/data-table-view-options.tsx index 7244ab4c..aeb67881 100644 --- a/components/examples/tasks/components/data-table-view-options.tsx +++ b/components/examples/tasks/components/data-table-view-options.tsx @@ -1,4 +1,4 @@ -import { DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu"; +import { DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Table } from "@tanstack/react-table"; import { Settings2 } from "lucide-react"; diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx index 26c5ac99..91e3a250 100644 --- a/components/ui/accordion.tsx +++ b/components/ui/accordion.tsx @@ -1,55 +1,66 @@ -import * as React from "react"; -import * as AccordionPrimitive from "@radix-ui/react-accordion"; -import { ChevronDown } from "lucide-react"; +"use client" -import { cn } from "@/lib/utils"; +import * as React from "react" +import { ChevronDownIcon } from "lucide-react" +import { Accordion as AccordionPrimitive } from "radix-ui" -const Accordion = AccordionPrimitive.Root; +import { cn } from "@/lib/utils" -const AccordionItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AccordionItem.displayName = "AccordionItem"; +function Accordion({ + ...props +}: React.ComponentProps) { + return +} -const AccordionTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - svg]:rotate-180", - className - )} +function AccordionItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AccordionTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + + ) +} + +function AccordionContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + - {children} - - - -)); -AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; +
{children}
+ + ) +} -const AccordionContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - -
{children}
-
-)); -AccordionContent.displayName = AccordionPrimitive.Content.displayName; - -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx index e961379a..dad32734 100644 --- a/components/ui/alert-dialog.tsx +++ b/components/ui/alert-dialog.tsx @@ -1,131 +1,196 @@ -import * as React from "react"; -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; +"use client" -import { cn } from "@/lib/utils"; -import { buttonVariants } from "@/components/ui/button"; +import * as React from "react" +import { AlertDialog as AlertDialogPrimitive } from "radix-ui" -const AlertDialog = AlertDialogPrimitive.Root; +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" -const AlertDialogTrigger = AlertDialogPrimitive.Trigger; +function AlertDialog({ + ...props +}: React.ComponentProps) { + return +} -const AlertDialogPortal = AlertDialogPrimitive.Portal; +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - ) { + return ( + - -)); -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; + ) +} -const AlertDialogHeader = ({ +function AlertDialogContent({ + className, + size = "default", + ...props +}: React.ComponentProps & { + size?: "default" | "sm" +}) { + return ( + + + + + ) +} + +function AlertDialogHeader({ className, ...props -}: React.HTMLAttributes) => ( -
-); -AlertDialogHeader.displayName = "AlertDialogHeader"; +}: React.ComponentProps<"div">) { + return ( +
+ ) +} -const AlertDialogFooter = ({ +function AlertDialogFooter({ className, ...props -}: React.HTMLAttributes) => ( -
-); -AlertDialogFooter.displayName = "AlertDialogFooter"; +}: React.ComponentProps<"div">) { + return ( +
+ ) +} -const AlertDialogTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogAction = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; +function AlertDialogMedia({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} -const AlertDialogCancel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; +function AlertDialogAction({ + className, + variant = "default", + size = "default", + ...props +}: React.ComponentProps & + Pick, "variant" | "size">) { + return ( + + ) +} + +function AlertDialogCancel({ + className, + variant = "outline", + size = "default", + ...props +}: React.ComponentProps & + Pick, "variant" | "size">) { + return ( + + ) +} export { AlertDialog, - AlertDialogPortal, - AlertDialogOverlay, - AlertDialogTrigger, - AlertDialogContent, - AlertDialogHeader, - AlertDialogFooter, - AlertDialogTitle, - AlertDialogDescription, AlertDialogAction, AlertDialogCancel, -}; + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogMedia, + AlertDialogOverlay, + AlertDialogPortal, + AlertDialogTitle, + AlertDialogTrigger, +} diff --git a/components/ui/alert.tsx b/components/ui/alert.tsx index 13219e77..f99164ed 100644 --- a/components/ui/alert.tsx +++ b/components/ui/alert.tsx @@ -1,59 +1,66 @@ -import * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const alertVariants = cva( - "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", + "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-background text-foreground", + default: "bg-card text-card-foreground", destructive: - "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current", }, }, defaultVariants: { variant: "default", }, - }, -); + } +) -const Alert = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes & VariantProps ->(({ className, variant, ...props }, ref) => ( -
-)); -Alert.displayName = "Alert"; +function Alert({ + className, + variant, + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} -const AlertTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -AlertTitle.displayName = "AlertTitle"; +function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} -const AlertDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -AlertDescription.displayName = "AlertDescription"; +function AlertDescription({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} -export { Alert, AlertTitle, AlertDescription }; +export { Alert, AlertTitle, AlertDescription } diff --git a/components/ui/aspect-ratio.tsx b/components/ui/aspect-ratio.tsx index c9e6f4bf..57e38fa9 100644 --- a/components/ui/aspect-ratio.tsx +++ b/components/ui/aspect-ratio.tsx @@ -1,5 +1,11 @@ -import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; +"use client" -const AspectRatio = AspectRatioPrimitive.Root; +import { AspectRatio as AspectRatioPrimitive } from "radix-ui" -export { AspectRatio }; +function AspectRatio({ + ...props +}: React.ComponentProps) { + return +} + +export { AspectRatio } diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx index 444b1dba..ea658505 100644 --- a/components/ui/avatar.tsx +++ b/components/ui/avatar.tsx @@ -1,48 +1,109 @@ -import * as React from "react"; -import * as AvatarPrimitive from "@radix-ui/react-avatar"; +"use client" -import { cn } from "@/lib/utils"; +import * as React from "react" +import { Avatar as AvatarPrimitive } from "radix-ui" -const Avatar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -Avatar.displayName = AvatarPrimitive.Root.displayName; +import { cn } from "@/lib/utils" -const AvatarImage = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AvatarImage.displayName = AvatarPrimitive.Image.displayName; +function Avatar({ + className, + size = "default", + ...props +}: React.ComponentProps & { + size?: "default" | "sm" | "lg" +}) { + return ( + + ) +} -const AvatarFallback = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} -export { Avatar, AvatarImage, AvatarFallback }; +function AvatarFallback({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) { + return ( + 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 ( +
+ ) +} + +function AvatarGroupCount({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
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, + AvatarBadge, + AvatarGroup, + AvatarGroupCount, +} diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx index 1ccbb185..6eb2a057 100644 --- a/components/ui/badge.tsx +++ b/components/ui/badge.tsx @@ -1,34 +1,48 @@ -import * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from "radix-ui" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" const badgeVariants = cva( - "inline-flex items-center rounded-md 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", + "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 shadow hover:bg-primary/80", + default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90", secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", destructive: - "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", - outline: "text-inherit", + "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: { variant: "default", }, } -); +) -export interface BadgeProps - extends React.HTMLAttributes, - VariantProps {} +function Badge({ + className, + variant = "default", + asChild = false, + ...props +}: React.ComponentProps<"span"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot.Root : "span" -function Badge({ className, variant, ...props }: BadgeProps) { - return
; + return ( + + ) } -export { Badge, badgeVariants }; +export { Badge, badgeVariants } diff --git a/components/ui/breadcrumb.tsx b/components/ui/breadcrumb.tsx index 6934f83b..004bb63a 100644 --- a/components/ui/breadcrumb.tsx +++ b/components/ui/breadcrumb.tsx @@ -1,108 +1,102 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { ChevronRight, MoreHorizontal } from "lucide-react"; +import * as React from "react" +import { ChevronRight, MoreHorizontal } from "lucide-react" +import { Slot } from "radix-ui" -import { cn } from "@/lib/utils"; +import { cn } from "@/lib/utils" -const Breadcrumb = React.forwardRef< - HTMLElement, - React.ComponentPropsWithoutRef<"nav"> & { - separator?: React.ReactNode; - } ->(({ ...props }, ref) =>