@@ -73,7 +94,10 @@ exports[`Button/Secondary matches snapshot 1`] = `
exports[`Button/Small matches snapshot 1`] = `
diff --git a/webui2/src/components/ui/__snapshots__/input.test.tsx.snap b/webui2/src/components/ui/__snapshots__/input.test.tsx.snap
index 30885d314672e89505f692c5663c1154446a50a5..c53c94eabbed52da74b6689413898d94439af176 100644
--- a/webui2/src/components/ui/__snapshots__/input.test.tsx.snap
+++ b/webui2/src/components/ui/__snapshots__/input.test.tsx.snap
@@ -3,7 +3,9 @@
exports[`Input/Default matches snapshot 1`] = `
@@ -12,8 +14,11 @@ exports[`Input/Default matches snapshot 1`] = `
exports[`Input/Disabled matches snapshot 1`] = `
@@ -22,7 +27,9 @@ exports[`Input/Disabled matches snapshot 1`] = `
exports[`Input/Password matches snapshot 1`] = `
@@ -32,7 +39,9 @@ exports[`Input/Password matches snapshot 1`] = `
exports[`Input/WithValue matches snapshot 1`] = `
diff --git a/webui2/src/components/ui/__snapshots__/separator.test.tsx.snap b/webui2/src/components/ui/__snapshots__/separator.test.tsx.snap
index 66dbdd59abca171cd4e4a0752e85c480f06f650b..44a07b3015b76c3648920ff5443c2e54077f4732 100644
--- a/webui2/src/components/ui/__snapshots__/separator.test.tsx.snap
+++ b/webui2/src/components/ui/__snapshots__/separator.test.tsx.snap
@@ -11,9 +11,11 @@ exports[`Separator/Horizontal matches snapshot 1`] = `
Above
@@ -25,7 +28,8 @@ exports[`Skeleton/Card matches snapshot 1`] = `
exports[`Skeleton/Circle matches snapshot 1`] = `
`;
@@ -33,7 +37,8 @@ exports[`Skeleton/Circle matches snapshot 1`] = `
exports[`Skeleton/Default matches snapshot 1`] = `
`;
diff --git a/webui2/src/components/ui/__snapshots__/textarea.test.tsx.snap b/webui2/src/components/ui/__snapshots__/textarea.test.tsx.snap
index 23fc03004b1fc7944aa9c8afd73af4d120475878..be9c1056be5ccf7989dd068cadde5fe1dc209a17 100644
--- a/webui2/src/components/ui/__snapshots__/textarea.test.tsx.snap
+++ b/webui2/src/components/ui/__snapshots__/textarea.test.tsx.snap
@@ -3,7 +3,8 @@
exports[`Textarea/Default matches snapshot 1`] = `
@@ -12,7 +13,8 @@ exports[`Textarea/Default matches snapshot 1`] = `
exports[`Textarea/Disabled matches snapshot 1`] = `
@@ -22,7 +24,8 @@ exports[`Textarea/Disabled matches snapshot 1`] = `
exports[`Textarea/WithValue matches snapshot 1`] = `
diff --git a/webui2/src/components/ui/avatar.tsx b/webui2/src/components/ui/avatar.tsx
index ea9224450e0d1c82cbcf89597c14ed39cc003783..e92a2f48dbfd5b7d05b0aac948b39d99e1e4b36f 100644
--- a/webui2/src/components/ui/avatar.tsx
+++ b/webui2/src/components/ui/avatar.tsx
@@ -1,45 +1,107 @@
-import { Avatar as AvatarPrimitive } from "radix-ui";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const Avatar = React.forwardRef<
- React.ElementRef
,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-Avatar.displayName = AvatarPrimitive.Root.displayName;
-
-const AvatarImage = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-AvatarImage.displayName = AvatarPrimitive.Image.displayName;
-
-const AvatarFallback = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
-
-export { Avatar, AvatarImage, AvatarFallback };
+import * as React from "react"
+import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar"
+
+import { cn } from "@/lib/utils"
+
+function Avatar({
+ className,
+ size = "default",
+ ...props
+}: AvatarPrimitive.Root.Props & {
+ size?: "default" | "sm" | "lg"
+}) {
+ return (
+
+ )
+}
+
+function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
+ return (
+
+ )
+}
+
+function AvatarFallback({
+ className,
+ ...props
+}: AvatarPrimitive.Fallback.Props) {
+ 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,
+ AvatarGroup,
+ AvatarGroupCount,
+ AvatarBadge,
+}
diff --git a/webui2/src/components/ui/badge.tsx b/webui2/src/components/ui/badge.tsx
index 224c9a64a16af1af75dc9d1d57fb0bd774e086fc..b20959dd775e40754a5f66940c62ee4f7feaef36 100644
--- a/webui2/src/components/ui/badge.tsx
+++ b/webui2/src/components/ui/badge.tsx
@@ -1,33 +1,52 @@
-import { cva, type VariantProps } from "class-variance-authority";
-import * as React from "react";
+import { mergeProps } from "@base-ui/react/merge-props"
+import { useRender } from "@base-ui/react/use-render"
+import { cva, type VariantProps } from "class-variance-authority"
-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-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2",
+ "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]:pr-1.5 has-data-[icon=inline-start]:pl-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 shadow-sm hover:bg-primary/80",
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
secondary:
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
destructive:
- "border-transparent bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/80",
- outline: "text-foreground",
+ "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:
+ "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: {
variant: "default",
},
- },
-);
+ }
+)
-export interface BadgeProps
- extends React.HTMLAttributes
, VariantProps {}
-
-function Badge({ className, variant, ...props }: BadgeProps) {
- return ;
+function Badge({
+ className,
+ variant = "default",
+ render,
+ ...props
+}: useRender.ComponentProps<"span"> & VariantProps) {
+ return useRender({
+ defaultTagName: "span",
+ props: mergeProps<"span">(
+ {
+ className: cn(badgeVariants({ variant }), className),
+ },
+ props
+ ),
+ render,
+ state: {
+ slot: "badge",
+ variant,
+ },
+ })
}
-export { Badge, badgeVariants };
+export { Badge, badgeVariants }
diff --git a/webui2/src/components/ui/button.tsx b/webui2/src/components/ui/button.tsx
index b4f023621819f49669dece8f85757b8aa6689892..f061d1fdc8a90d3ee961ff0e8f46c85872734fbf 100644
--- a/webui2/src/components/ui/button.tsx
+++ b/webui2/src/components/ui/button.tsx
@@ -1,49 +1,60 @@
-import { cva, type VariantProps } from "class-variance-authority";
-import { Slot as SlotPrimitive } from "radix-ui";
-import * as React from "react";
+"use client"
-import { cn } from "@/lib/utils";
+import { Button as ButtonPrimitive } from "@base-ui/react/button"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
- default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
- destructive: "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90",
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
outline:
- "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
- secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
- ghost: "hover:bg-accent hover:text-accent-foreground",
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
+ ghost:
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
+ destructive:
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
- default: "h-9 px-4 py-2",
- sm: "h-8 rounded-md px-3 text-xs",
- lg: "h-10 rounded-md px-8",
- icon: "h-9 w-9",
+ default:
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ icon: "size-8",
+ "icon-xs":
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
+ "icon-sm":
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
+ "icon-lg": "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
- },
-);
+ }
+)
-export interface ButtonProps
- extends React.ButtonHTMLAttributes, VariantProps {
- asChild?: boolean;
+function Button({
+ className,
+ variant = "default",
+ size = "default",
+ ...props
+}: ButtonPrimitive.Props & VariantProps) {
+ return (
+
+ )
}
-const Button = React.forwardRef(
- ({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? SlotPrimitive.Root : "button";
- return (
-
- );
- },
-);
-Button.displayName = "Button";
-
-export { Button, buttonVariants };
+export { Button, buttonVariants }
diff --git a/webui2/src/components/ui/input.tsx b/webui2/src/components/ui/input.tsx
index dca4fd626a229f42bcc09a019310026495904b1c..7d21babba91655ac1cd6a5ea630eb2ec18d2b52b 100644
--- a/webui2/src/components/ui/input.tsx
+++ b/webui2/src/components/ui/input.tsx
@@ -1,22 +1,20 @@
-import * as React from "react";
+import * as React from "react"
+import { Input as InputPrimitive } from "@base-ui/react/input"
-import { cn } from "@/lib/utils";
+import { cn } from "@/lib/utils"
-const Input = React.forwardRef>(
- ({ className, type, ...props }, ref) => {
- return (
-
- );
- },
-);
-Input.displayName = "Input";
+function Input({ className, type, ...props }: React.ComponentProps<"input">) {
+ return (
+
+ )
+}
-export { Input };
+export { Input }
diff --git a/webui2/src/components/ui/popover.tsx b/webui2/src/components/ui/popover.tsx
index 8cb0ccbe7d6075b52ae49d322b40d3087a8fad72..3d4356254ebaa40f20502e9fbe5af337bf2fba8a 100644
--- a/webui2/src/components/ui/popover.tsx
+++ b/webui2/src/components/ui/popover.tsx
@@ -1,29 +1,88 @@
-import { Popover as PopoverPrimitive } from "radix-ui";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const Popover = PopoverPrimitive.Root;
-const PopoverTrigger = PopoverPrimitive.Trigger;
-const PopoverAnchor = PopoverPrimitive.Anchor;
-
-const PopoverContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
-
-
+}
+
+function PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {
+ return
+}
+
+function PopoverContent({
+ className,
+ align = "center",
+ alignOffset = 0,
+ side = "bottom",
+ sideOffset = 4,
+ ...props
+}: PopoverPrimitive.Popup.Props &
+ Pick<
+ PopoverPrimitive.Positioner.Props,
+ "align" | "alignOffset" | "side" | "sideOffset"
+ >) {
+ return (
+
+
+
+
+
+ )
+}
+
+function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
+ return (
+
+ )
+}
+
+function PopoverDescription({
+ className,
+ ...props
+}: PopoverPrimitive.Description.Props) {
+ return (
+
-
-));
-PopoverContent.displayName = PopoverPrimitive.Content.displayName;
+ )
+}
-export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };
+export {
+ Popover,
+ PopoverContent,
+ PopoverDescription,
+ PopoverHeader,
+ PopoverTitle,
+ PopoverTrigger,
+}
diff --git a/webui2/src/components/ui/separator.tsx b/webui2/src/components/ui/separator.tsx
index f01f205a8d29ec11c8735ca7da4e653b155d2fc4..6e1369e43cce8be3da7ef04940b79dd276245290 100644
--- a/webui2/src/components/ui/separator.tsx
+++ b/webui2/src/components/ui/separator.tsx
@@ -1,24 +1,25 @@
-import { Separator as SeparatorPrimitive } from "radix-ui";
-import * as React from "react";
+"use client"
-import { cn } from "@/lib/utils";
+import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
-const Separator = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
-
-));
-Separator.displayName = SeparatorPrimitive.Root.displayName;
+import { cn } from "@/lib/utils"
-export { Separator };
+function Separator({
+ className,
+ orientation = "horizontal",
+ ...props
+}: SeparatorPrimitive.Props) {
+ return (
+
+ )
+}
+
+export { Separator }
diff --git a/webui2/src/components/ui/skeleton.tsx b/webui2/src/components/ui/skeleton.tsx
index 6d9a616758e39fcbc07480484a308ffb9d9fba5d..0118624f6e6a64b90c24502a4e2b8c5513098072 100644
--- a/webui2/src/components/ui/skeleton.tsx
+++ b/webui2/src/components/ui/skeleton.tsx
@@ -1,7 +1,13 @@
-import { cn } from "@/lib/utils";
+import { cn } from "@/lib/utils"
-function Skeleton({ className, ...props }: React.HTMLAttributes) {
- return ;
+function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
}
-export { Skeleton };
+export { Skeleton }
diff --git a/webui2/src/components/ui/textarea.tsx b/webui2/src/components/ui/textarea.tsx
index 63f787bd632ff5b2afef1666a845c9fd2a3897a6..04d27f7d17584cd77ba7d6f2377f5be6779f1270 100644
--- a/webui2/src/components/ui/textarea.tsx
+++ b/webui2/src/components/ui/textarea.tsx
@@ -1,21 +1,18 @@
-import * as React from "react";
+import * as React from "react"
-import { cn } from "@/lib/utils";
+import { cn } from "@/lib/utils"
-const Textarea = React.forwardRef>(
- ({ className, ...props }, ref) => {
- return (
-
- );
- },
-);
-Textarea.displayName = "Textarea";
+function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
+ return (
+
+ )
+}
-export { Textarea };
+export { Textarea }
diff --git a/webui2/src/index.css b/webui2/src/index.css
index 0c5e0b2409682689f62f00083afa4115dea14397..98314f0ddf65dee5bd4a22b9858a87adfbe2d43c 100644
--- a/webui2/src/index.css
+++ b/webui2/src/index.css
@@ -1,5 +1,7 @@
@import "tailwindcss";
@import "tw-animate-css";
+@import "shadcn/tailwind.css";
+@import "@fontsource-variable/geist";
@plugin "@tailwindcss/typography";
@custom-variant dark (&:where(.dark, .dark *));
@@ -7,49 +9,75 @@
:root {
/* Blue-accented light palette. Primary is GitHub-style indigo-blue so
action buttons are clearly coloured, not a flat dark grey. */
- --background: hsl(0 0% 100%);
- --foreground: hsl(222 20% 18%);
- --card: hsl(0 0% 100%);
- --card-foreground: hsl(222 20% 18%);
- --popover: hsl(0 0% 100%);
- --popover-foreground: hsl(222 20% 18%);
- --primary: hsl(212 88% 44%);
- --primary-foreground: hsl(0 0% 100%);
- --secondary: hsl(214 32% 95%);
- --secondary-foreground: hsl(222 20% 18%);
- --muted: hsl(214 32% 96%);
- --muted-foreground: hsl(220 9% 46%);
- --accent: hsl(214 88% 95%);
- --accent-foreground: hsl(212 88% 35%);
- --destructive: hsl(0 84.2% 60.2%);
+ --background: oklch(1 0 0);
+ --foreground: oklch(0.145 0 0);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.145 0 0);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.145 0 0);
+ --primary: oklch(0.205 0 0);
+ --primary-foreground: oklch(0.985 0 0);
+ --secondary: oklch(0.97 0 0);
+ --secondary-foreground: oklch(0.205 0 0);
+ --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);
--destructive-foreground: hsl(0 0% 98%);
- --border: hsl(214 32% 88%);
- --input: hsl(214 32% 88%);
- --ring: hsl(212 88% 44%);
- --radius: 0.5rem;
+ --border: oklch(0.922 0 0);
+ --input: oklch(0.922 0 0);
+ --ring: oklch(0.708 0 0);
+ --radius: 0.625rem;
+ --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.205 0 0);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --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 {
/* Softer dark — background lifted slightly, text dimmed to reduce glare. */
- --background: hsl(220 13% 15%);
- --foreground: hsl(220 10% 72%);
- --card: hsl(220 13% 18%);
- --card-foreground: hsl(220 10% 72%);
- --popover: hsl(220 13% 18%);
- --popover-foreground: hsl(220 10% 72%);
- --primary: hsl(213 88% 62%);
- --primary-foreground: hsl(220 20% 10%);
- --secondary: hsl(220 12% 24%);
- --secondary-foreground: hsl(220 10% 72%);
- --muted: hsl(220 12% 24%);
- --muted-foreground: hsl(220 8% 52%);
- --accent: hsl(220 20% 28%);
- --accent-foreground: hsl(213 88% 72%);
- --destructive: hsl(0 65% 50%);
+ --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.922 0 0);
+ --primary-foreground: oklch(0.205 0 0);
+ --secondary: oklch(0.269 0 0);
+ --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);
--destructive-foreground: hsl(0 0% 98%);
- --border: hsl(220 12% 26%);
- --input: hsl(220 12% 26%);
- --ring: hsl(213 88% 62%);
+ --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.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --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);
}
@theme inline {
@@ -77,11 +105,29 @@
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
- --font-sans: ui-sans-serif, system-ui, sans-serif;
+ --font-sans: 'Geist Variable', sans-serif;
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;
+ --font-heading: var(--font-sans);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --radius-xl: calc(var(--radius) * 1.4);
+ --radius-2xl: calc(var(--radius) * 1.8);
+ --radius-3xl: calc(var(--radius) * 2.2);
+ --radius-4xl: calc(var(--radius) * 2.6);
}
@keyframes accordion-down {
@@ -136,3 +182,14 @@ body {
text-decoration: var(--shiki-dark-text-decoration);
}
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+ html {
+ @apply font-sans;
+ }
+}
\ No newline at end of file
diff --git a/webui2/src/lib/utils.ts b/webui2/src/lib/utils.ts
index 365058cebd7d2bdb327ca1c081b16e4937e11050..bd0c391ddd1088e9067844c48835bf4abcd61783 100644
--- a/webui2/src/lib/utils.ts
+++ b/webui2/src/lib/utils.ts
@@ -1,6 +1,6 @@
-import { type ClassValue, clsx } from "clsx";
-import { twMerge } from "tailwind-merge";
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs));
+ return twMerge(clsx(inputs))
}
diff --git a/webui2/tsconfig.json b/webui2/tsconfig.json
index d32ff682003e0ff5d8a6e6bb3663d4c35a45b116..28d6b8863af5a7e484d4d440f01464719e918d53 100644
--- a/webui2/tsconfig.json
+++ b/webui2/tsconfig.json
@@ -1,4 +1,9 @@
{
+ "compilerOptions": {
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
"files": [],
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
}