diff --git a/apps/api/src/locales/@vitnode/core/en.json b/apps/api/src/locales/@vitnode/core/en.json index 5d2f42ed1..dbde4f715 100644 --- a/apps/api/src/locales/@vitnode/core/en.json +++ b/apps/api/src/locales/@vitnode/core/en.json @@ -1,6 +1,13 @@ { "core": { "global": { + "close": "Close", + "confirm": "Confirm", + "previous": "Previous", + "next": "Next", + "current_page": "Current page", + "go_to_page": "Go to page", + "remove": "Remove", "editor": { "undo": "Undo", "redo": "Redo", diff --git a/apps/docs/components.json b/apps/docs/components.json index 9a3fe27e5..58c323fd0 100644 --- a/apps/docs/components.json +++ b/apps/docs/components.json @@ -1,6 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema.json", - "style": "base-nova", + "style": "radix-vega", "rsc": true, "tsx": true, "tailwind": { diff --git a/apps/docs/content/docs/dev/email/components/button.mdx b/apps/docs/content/docs/dev/email/components/button.mdx index 150a8a590..1d5f31012 100644 --- a/apps/docs/content/docs/dev/email/components/button.mdx +++ b/apps/docs/content/docs/dev/email/components/button.mdx @@ -5,15 +5,15 @@ description: A button or link component for emails. ## Preview -import { ImgDocs } from '@/components/fumadocs/img'; -import buttonPreviewImg from './button-preview.png'; +import { ImgDocs } from "@/components/fumadocs/img"; +import buttonPreviewImg from "./button-preview.png"; ## Usage ```ts -import { EmailButton } from '@vitnode/core/emails/ui/button'; +import { EmailButton } from "@vitnode/core/emails/ui/button"; ``` ```tsx @@ -22,24 +22,24 @@ import { EmailButton } from '@vitnode/core/emails/ui/button'; ## Props -import { TypeTable } from 'fumadocs-ui/components/type-table'; +import { TypeTable } from "fumadocs-ui/components/type-table"; diff --git a/apps/docs/content/docs/ui/button.mdx b/apps/docs/content/docs/ui/button.mdx index 176ab8855..996682188 100644 --- a/apps/docs/content/docs/ui/button.mdx +++ b/apps/docs/content/docs/ui/button.mdx @@ -10,8 +10,8 @@ description: A button component for triggering actions in your application. ## Usage ```ts -import { Home } from 'lucide-react'; -import { Button } from '@vitnode/core/components/ui/button'; +import { Home } from "lucide-react"; +import { Button } from "@vitnode/core/components/ui/button"; ``` ```tsx @@ -23,19 +23,19 @@ import { Button } from '@vitnode/core/components/ui/button'; ## Props -import { TypeTable } from 'fumadocs-ui/components/type-table'; +import { TypeTable } from "fumadocs-ui/components/type-table"; diff --git a/apps/docs/package.json b/apps/docs/package.json index 81311561c..6859c6f7a 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -41,6 +41,7 @@ "react-dom": "^19.2.5", "react-hook-form": "^7.74.0", "react-use": "^17.6.0", + "shadcn": "^4.7.0", "sonner": "^2.0.7" }, "devDependencies": { diff --git a/apps/docs/src/app/global.css b/apps/docs/src/app/global.css index a3723c255..90890f9cd 100644 --- a/apps/docs/src/app/global.css +++ b/apps/docs/src/app/global.css @@ -1,7 +1,8 @@ @import "tailwindcss"; -@import "fumadocs-ui/css/shadcn.css"; +@import "fumadocs-ui/css/neutral.css"; @import "fumadocs-ui/css/preset.css"; @import "@vitnode/core/styles/tiptap.css"; +@import "shadcn/tailwind.css"; @import "tw-animate-css"; @@ -11,37 +12,37 @@ :root:not(.dark) { --background: oklch(1 0 0); - --foreground: oklch(0.141 0.005 285.823); + --foreground: oklch(0.145 0 0); --card: oklch(1 0 0); - --card-foreground: oklch(0.141 0.005 285.823); + --card-foreground: oklch(0.145 0 0); --popover: oklch(1 0 0); - --popover-foreground: oklch(0.141 0.005 285.823); - --primary: oklch(0.488 0.243 264.376); - --primary-foreground: oklch(0.97 0.014 254.604); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.51 0.16 262.61); + --primary-foreground: oklch(0.985 0 0); --secondary: oklch(0.967 0.001 286.375); --secondary-foreground: oklch(0.21 0.006 285.885); - --muted: oklch(0.967 0.001 286.375); - --muted-foreground: oklch(0.552 0.016 285.938); - --accent: oklch(0.967 0.001 286.375); - --accent-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.92 0.004 286.32); - --input: oklch(0.92 0.004 286.32); - --ring: oklch(0.705 0.015 286.067); - --chart-1: oklch(0.871 0.006 286.286); - --chart-2: oklch(0.552 0.016 285.938); - --chart-3: oklch(0.442 0.017 285.786); - --chart-4: oklch(0.37 0.013 285.805); - --chart-5: oklch(0.274 0.006 286.033); - --radius: 0.625rem; + --warn: oklch(0.54 0.12 82.58); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-foreground: oklch(0.145 0 0); --sidebar-primary: oklch(0.546 0.245 262.881); --sidebar-primary-foreground: oklch(0.97 0.014 254.604); - --sidebar-accent: oklch(0.967 0.001 286.375); - --sidebar-accent-foreground: oklch(0.21 0.006 285.885); - --sidebar-border: oklch(0.92 0.004 286.32); - --sidebar-ring: oklch(0.705 0.015 286.067); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); --dev-color: oklch(0.6 0.18 50); --ui-color: oklch(0.65 0.18 170); @@ -49,37 +50,38 @@ } .dark { - --background: oklch(0.141 0.005 285.823); + --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); - --card: oklch(0.21 0.006 285.885); + --card: oklch(0.205 0 0); --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.21 0.006 285.885); + --popover: oklch(0.205 0 0); --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.424 0.199 265.638); - --primary-foreground: oklch(0.97 0.014 254.604); + --primary: oklch(0.6 0.18 262.65); + --primary-foreground: oklch(0.98 0 0); --secondary: oklch(0.274 0.006 286.033); --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.274 0.006 286.033); - --muted-foreground: oklch(0.705 0.015 286.067); - --accent: oklch(0.274 0.006 286.033); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); --accent-foreground: oklch(0.985 0 0); --destructive: oklch(0.704 0.191 22.216); + --warn: oklch(0.76 0.18 81.84); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); - --ring: oklch(0.552 0.016 285.938); - --chart-1: oklch(0.871 0.006 286.286); - --chart-2: oklch(0.552 0.016 285.938); - --chart-3: oklch(0.442 0.017 285.786); - --chart-4: oklch(0.37 0.013 285.805); - --chart-5: oklch(0.274 0.006 286.033); - --sidebar: oklch(0.21 0.006 285.885); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.205 0 0); --sidebar-foreground: oklch(0.985 0 0); --sidebar-primary: oklch(0.623 0.214 259.815); --sidebar-primary-foreground: oklch(0.97 0.014 254.604); - --sidebar-accent: oklch(0.274 0.006 286.033); + --sidebar-accent: oklch(0.269 0 0); --sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.552 0.016 285.938); + --sidebar-ring: oklch(0.556 0 0); --dev-color: oklch(0.75 0.18 50); --ui-color: oklch(0.7 0.18 170); diff --git a/apps/docs/src/examples/button.tsx b/apps/docs/src/examples/button.tsx index b3b87f56c..be3b1d502 100644 --- a/apps/docs/src/examples/button.tsx +++ b/apps/docs/src/examples/button.tsx @@ -38,7 +38,7 @@ export default function ButtonExample() { aria-label="Delete" isLoading={isLoading} size="icon" - variant="destructiveGhost" + variant="destructive" > diff --git a/apps/docs/src/locales/@vitnode/core/en.json b/apps/docs/src/locales/@vitnode/core/en.json index 5d2f42ed1..dbde4f715 100644 --- a/apps/docs/src/locales/@vitnode/core/en.json +++ b/apps/docs/src/locales/@vitnode/core/en.json @@ -1,6 +1,13 @@ { "core": { "global": { + "close": "Close", + "confirm": "Confirm", + "previous": "Previous", + "next": "Next", + "current_page": "Current page", + "go_to_page": "Go to page", + "remove": "Remove", "editor": { "undo": "Undo", "redo": "Redo", diff --git a/packages/create-vitnode-app/copy-of-vitnode-app/root/src/app/global.css b/packages/create-vitnode-app/copy-of-vitnode-app/root/src/app/global.css index 734f04a10..5a1390c82 100644 --- a/packages/create-vitnode-app/copy-of-vitnode-app/root/src/app/global.css +++ b/packages/create-vitnode-app/copy-of-vitnode-app/root/src/app/global.css @@ -1,77 +1,79 @@ @import "tailwindcss"; @import "@vitnode/core/styles/tiptap.css"; @import "tw-animate-css"; +@import "shadcn/tailwind.css"; @source "../../node_modules/@vitnode/core/dist/src/components"; @source "../../node_modules/@vitnode/core/dist/src/views"; :root:not(.dark) { - --background: oklch(0.96 0.01 250); - --foreground: oklch(0.18 0.01 250); + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); --card: oklch(1 0 0); - --card-foreground: oklch(0.22 0.01 250); + --card-foreground: oklch(0.145 0 0); --popover: oklch(1 0 0); - --popover-foreground: oklch(0.22 0.01 250); + --popover-foreground: oklch(0.145 0 0); --primary: oklch(0.51 0.16 262.61); --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.94 0.02 254.94); - --secondary-foreground: oklch(0.25 0.01 250); - --muted: oklch(0.95 0.01 250); - --muted-foreground: oklch(0.53 0.01 250); - --accent: oklch(0.92 0.01 250); - --accent-foreground: oklch(0.25 0.01 250); - --destructive: oklch(0.6 0.2 24.45); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); --warn: oklch(0.54 0.12 82.58); - --border: oklch(0.9 0.01 250); - --input: oklch(0.9 0.01 250); - --ring: oklch(0.7 0.13 250); - --chart-1: oklch(0.65 0.13 250); - --chart-2: oklch(0.6 0.11 260); - --chart-3: oklch(0.45 0.09 250); - --chart-4: oklch(0.8 0.13 250); - --chart-5: oklch(0.75 0.13 250); - --sidebar: var(--card); - --sidebar-foreground: oklch(0.22 0.01 250); - --sidebar-primary: var(--primary); - --sidebar-primary-foreground: var(--primary-foreground); - --sidebar-accent: oklch(0.97 0.01 250); - --sidebar-accent-foreground: oklch(0.25 0.01 250); - --sidebar-border: oklch(0.91 0.01 250); - --sidebar-ring: oklch(0.7 0.13 250); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.546 0.245 262.881); + --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); } .dark { - --background: oklch(0.16 0.01 250); - --foreground: oklch(0.96 0.01 250); - --card: oklch(0.2 0.01 250); - --card-foreground: oklch(0.96 0.01 250); - --popover: oklch(0.22 0.01 250); - --popover-foreground: oklch(0.96 0.01 250); + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); --primary: oklch(0.6 0.18 262.65); --primary-foreground: oklch(0.98 0 0); - --secondary: oklch(0.2 0.01 250); - --secondary-foreground: oklch(0.96 0.01 250); - --muted: oklch(0.24 0.01 250); - --muted-foreground: oklch(0.7 0.01 250); - --accent: oklch(0.28 0.01 250); - --destructive: oklch(0.62 0.2 25.35); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); --warn: oklch(0.76 0.18 81.84); - --border: oklch(0.3 0.01 250); - --input: oklch(0.3 0.01 250); - --ring: oklch(0.54 0.13 250); - --chart-1: oklch(0.45 0.09 250); - --chart-2: oklch(0.6 0.11 260); - --chart-3: oklch(0.75 0.13 250); - --chart-4: oklch(0.8 0.13 250); - --chart-5: oklch(0.65 0.13 250); - --sidebar: var(--card); - --sidebar-foreground: oklch(0.96 0.01 250); - --sidebar-primary: var(--primary); - --sidebar-primary-foreground: var(--primary-foreground); - --sidebar-accent: oklch(0.23 0.01 250); - --sidebar-accent-foreground: oklch(0.96 0.01 250); - --sidebar-border: oklch(0.26 0.01 250); - --sidebar-ring: oklch(0.54 0.13 250); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.623 0.214 259.815); + --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); } :root { diff --git a/packages/create-vitnode-app/src/create/create-package-json.ts b/packages/create-vitnode-app/src/create/create-package-json.ts index 159da5622..35c21330c 100644 --- a/packages/create-vitnode-app/src/create/create-package-json.ts +++ b/packages/create-vitnode-app/src/create/create-package-json.ts @@ -131,6 +131,7 @@ const apiDeps = { react: versionsPackageJson.react, "react-dom": versionsPackageJson.reactDom, "use-intl": versionsPackageJson.useIntl, + shadcn: versionsPackageJson.shadcnUi, zod: versionsPackageJson.zod, }; diff --git a/packages/create-vitnode-app/src/create/package-versions.ts b/packages/create-vitnode-app/src/create/package-versions.ts index b80e164ff..886eedd33 100644 --- a/packages/create-vitnode-app/src/create/package-versions.ts +++ b/packages/create-vitnode-app/src/create/package-versions.ts @@ -43,4 +43,5 @@ export const versionsPackageJson = { swcCli: "^0.8.1", swcCore: "^1.15", concurrently: "^9.2.1", + shadcnUi: "^4", }; diff --git a/packages/vitnode/components.json b/packages/vitnode/components.json index 797c749cb..68fa65fe9 100644 --- a/packages/vitnode/components.json +++ b/packages/vitnode/components.json @@ -1,6 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema.json", - "style": "base-nova", + "style": "radix-vega", "rsc": true, "tsx": true, "tailwind": { diff --git a/packages/vitnode/package.json b/packages/vitnode/package.json index 4762347a5..76e93b209 100644 --- a/packages/vitnode/package.json +++ b/packages/vitnode/package.json @@ -109,6 +109,7 @@ }, "type": "module", "dependencies": { + "@base-ui/react": "^1.4.1", "@bprogress/next": "^3.2.12", "@dnd-kit/core": "^6.3.1", "@hono/swagger-ui": "^0.6.1", @@ -122,15 +123,21 @@ "clsx": "^2.1.1", "cmdk": "^1.1.1", "cron-parser": "^5.5.0", + "date-fns": "^4.1.0", "dotenv": "^17.4.2", + "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", "motion": "^12.38.0", "next-themes": "^0.4.6", "postgres": "^3.4.9", "radix-ui": "^1.4.3", "rate-limiter-flexible": "^11.0.1", + "react-day-picker": "^10.0.1", + "react-resizable-panels": "^4.11.1", "react-scan": "^0.5.3", + "recharts": "3.8.0", "server-only": "^0.0.1", + "shadcn": "^4.7.0", "tailwind-merge": "^3.5.0", "use-debounce": "^10.1.1", "use-intl": "^4.11.0", diff --git a/packages/vitnode/src/components/date-format.tsx b/packages/vitnode/src/components/date-format.tsx index 5825d591c..8886de441 100644 --- a/packages/vitnode/src/components/date-format.tsx +++ b/packages/vitnode/src/components/date-format.tsx @@ -2,12 +2,7 @@ import { useFormatter, useNow } from "next-intl"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "./ui/tooltip"; +import { TooltipWithContent } from "./ui/tooltip"; export const DateFormat = ({ date, @@ -44,15 +39,9 @@ export const DateFormat = ({ // When date is < 7 days if (now.getTime() - dateToFormat.getTime() < 604800000) { return ( - - - - {format.relativeTime(dateToFormat, now)} - - - {fullDate} - - + + {format.relativeTime(dateToFormat, now)} + ); } diff --git a/packages/vitnode/src/components/ui/accordion.tsx b/packages/vitnode/src/components/ui/accordion.tsx index 87172e9d7..4aaf7ad51 100644 --- a/packages/vitnode/src/components/ui/accordion.tsx +++ b/packages/vitnode/src/components/ui/accordion.tsx @@ -1,16 +1,22 @@ "use client"; -import type * as React from "react"; - -import { ChevronDownIcon } from "lucide-react"; +import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; import { Accordion as AccordionPrimitive } from "radix-ui"; +import * as React from "react"; import { cn } from "@/lib/utils"; function Accordion({ + className, ...props }: React.ComponentProps) { - return ; + return ( + + ); } function AccordionItem({ @@ -19,7 +25,7 @@ function AccordionItem({ }: React.ComponentProps) { return ( @@ -35,14 +41,21 @@ function AccordionTrigger({ svg]:rotate-180", + "group/accordion-trigger focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:after:border-ring **:data-[slot=accordion-trigger-icon]:text-muted-foreground relative flex flex-1 items-start justify-between rounded-md border border-transparent py-4 text-start text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-3 disabled:pointer-events-none disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ms-auto **:data-[slot=accordion-trigger-icon]:size-4", className, )} data-slot="accordion-trigger" {...props} > {children} - + + ); @@ -55,11 +68,18 @@ function AccordionContent({ }: React.ComponentProps) { return ( -
{children}
+
+ {children} +
); } diff --git a/packages/vitnode/src/components/ui/alert-dialog.tsx b/packages/vitnode/src/components/ui/alert-dialog.tsx index 29f58ff92..1218b04c1 100644 --- a/packages/vitnode/src/components/ui/alert-dialog.tsx +++ b/packages/vitnode/src/components/ui/alert-dialog.tsx @@ -2,8 +2,9 @@ import { AlertDialog as AlertDialogPrimitive } from "radix-ui"; import React from "react"; +import { useTranslations } from "use-intl"; -import { buttonVariants } from "@/components/ui/button"; +import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; import { Skeleton } from "./skeleton"; @@ -101,7 +102,10 @@ function AlertDialogHeader({ }: React.ComponentProps<"div">) { return (
@@ -115,7 +119,7 @@ function AlertDialogFooter({ return (
); } +function AlertDialogMedia({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ); +} function AlertDialogTitle({ className, @@ -149,7 +168,10 @@ function AlertDialogTitle({ }: React.ComponentProps) { return ( @@ -162,7 +184,10 @@ function AlertDialogDescription({ }: React.ComponentProps) { return ( @@ -171,25 +196,41 @@ function AlertDialogDescription({ function AlertDialogAction({ className, + variant = "default", + size = "default", ...props -}: React.ComponentProps) { +}: Pick, "size" | "variant"> & + React.ComponentProps) { + const t = useTranslations("core.global"); + return ( - + ); } function AlertDialogCancel({ className, + variant = "outline", + size = "default", ...props -}: React.ComponentProps) { +}: Pick, "size" | "variant"> & + React.ComponentProps) { + const t = useTranslations("core.global"); + return ( - + ); } @@ -202,6 +243,7 @@ export { AlertDialogFooter, AlertDialogFooterSkeleton, AlertDialogHeader, + AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, diff --git a/packages/vitnode/src/components/ui/alert.tsx b/packages/vitnode/src/components/ui/alert.tsx index 8b602d6dc..f2b59500d 100644 --- a/packages/vitnode/src/components/ui/alert.tsx +++ b/packages/vitnode/src/components/ui/alert.tsx @@ -1,17 +1,16 @@ -import type * as React from "react"; - import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react"; 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", + "group/alert relative grid w-full gap-0.5 rounded-lg border px-4 py-3 text-start text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", { 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: { @@ -39,7 +38,7 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { return (
svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3", className, )} data-slot="alert-title" @@ -55,7 +54,7 @@ function AlertDescription({ return (
) { + return ( +
+ ); +} + +export { Alert, AlertAction, AlertDescription, AlertTitle }; diff --git a/packages/vitnode/src/components/ui/aspect-ratio.tsx b/packages/vitnode/src/components/ui/aspect-ratio.tsx new file mode 100644 index 000000000..41720ca39 --- /dev/null +++ b/packages/vitnode/src/components/ui/aspect-ratio.tsx @@ -0,0 +1,11 @@ +"use client"; + +import { AspectRatio as AspectRatioPrimitive } from "radix-ui"; + +function AspectRatio({ + ...props +}: React.ComponentProps) { + return ; +} + +export { AspectRatio }; diff --git a/packages/vitnode/src/components/ui/avatar.tsx b/packages/vitnode/src/components/ui/avatar.tsx new file mode 100644 index 000000000..9d0ef6c76 --- /dev/null +++ b/packages/vitnode/src/components/ui/avatar.tsx @@ -0,0 +1,112 @@ +"use client"; + +import { Avatar as AvatarPrimitive } from "radix-ui"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +function Avatar({ + className, + size = "default", + ...props +}: React.ComponentProps & { + size?: "default" | "lg" | "sm"; +}) { + return ( + + ); +} + +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +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, + )} + data-slot="avatar-badge" + {...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, + )} + data-slot="avatar-group-count" + {...props} + /> + ); +} + +export { + Avatar, + AvatarBadge, + AvatarFallback, + AvatarGroup, + AvatarGroupCount, + AvatarImage, +}; diff --git a/packages/vitnode/src/components/ui/badge.tsx b/packages/vitnode/src/components/ui/badge.tsx index 17d21186e..6754970b8 100644 --- a/packages/vitnode/src/components/ui/badge.tsx +++ b/packages/vitnode/src/components/ui/badge.tsx @@ -1,23 +1,24 @@ -import type * as React from "react"; - import { cva, type VariantProps } from "class-variance-authority"; import { Slot } from "radix-ui"; +import * as React from "react"; import { cn } from "@/lib/utils"; const badgeVariants = cva( - "inline-flex items-center justify-center rounded-md 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", + "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 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", + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", secondary: - "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", 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", + "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20", outline: - "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", + "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", + ghost: + "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", + link: "text-primary underline-offset-4 hover:underline", }, }, defaultVariants: { @@ -28,7 +29,7 @@ const badgeVariants = cva( function Badge({ className, - variant, + variant = "default", asChild = false, ...props }: React.ComponentProps<"span"> & @@ -39,6 +40,7 @@ function Badge({ ); diff --git a/packages/vitnode/src/components/ui/breadcrumb.tsx b/packages/vitnode/src/components/ui/breadcrumb.tsx new file mode 100644 index 000000000..e3a023373 --- /dev/null +++ b/packages/vitnode/src/components/ui/breadcrumb.tsx @@ -0,0 +1,119 @@ +import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"; +import { Slot } from "radix-ui"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) { + return ( +