feat: progress (2/19) & clerk themes and extra theming

This commit is contained in:
dvelo 2025-02-19 14:31:59 -06:00
parent a0a139de02
commit a9d5ddf43d
32 changed files with 768 additions and 325 deletions

@ -71,6 +71,7 @@
"sonner": "^1.7.0",
"stripe-gradient": "^1.0.1",
"tailwind-merge": "^2.3.0",
"tailwindcss": "^4.0.7",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-patch": "^4.0.0",
"turbo": "^2.4.0",
@ -92,6 +93,7 @@
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"@tailwindcss/postcss": "^4.0.7",
"@tailwindcss/typography": "^0.5.13",
"@types/canvas-confetti": "^1.6.4",
"@types/node": "^20",

@ -31,7 +31,7 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
'@tailwindcss/postcss': {},
},
};

@ -31,18 +31,16 @@
"use client";
import "../globals.css";
import { useSearchParams } from "next/navigation";
import { Inter } from "next/font/google";
import { Placeholder } from "@/components/ui/placeholder";
import { X } from "lucide-react";
import { IsScript } from "@/components/util/is-script";
import { Button } from "@/components/ui/button";
import { ClerkProvider } from "@clerk/nextjs";
import Link from "next/link";
import { NavBar } from "@/components/feat/navbar/navbar";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/util/theme-provider";
const inter = Inter({ subsets: ["latin"] });
import { FontBoundary } from "@/components/util/font-boundary";
import { ClerkProvider } from "@/components/util/clerk-provider";
export default function RootLayout({
children,
@ -53,37 +51,37 @@ export default function RootLayout({
const search = searchParams?.get("theme") || "light";
return (
<ClerkProvider>
<html lang="en">
<body className={inter.className}>
<html lang="en">
<noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder
icon={<X />}
title="JavaScript is required for MHSF"
description="MHSF cannot grab servers or do other external requests without JavaScript."
>
<Link href="https://www.enable-javascript.com/">
<Button>Here's how</Button>
</Link>
</Placeholder>
</main>
</noscript>
<IsScript>
<FontBoundary>
<TooltipProvider>
<noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder
icon={<X />}
title="JavaScript is required for MHSF"
description="MHSF cannot grab servers or do other external requests without JavaScript."
>
<Link href="https://www.enable-javascript.com/">
<Button>Here's how</Button>
</Link>
</Placeholder>
</main>
</noscript>
<IsScript>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<ClerkProvider>
<NavBar />
<div className="pt-16">{children}</div>
</ThemeProvider>
</IsScript>
</ClerkProvider>
</ThemeProvider>
</TooltipProvider>
</body>
</html>
</ClerkProvider>
</FontBoundary>
</IsScript>
</html>
);
}

@ -1,9 +1,142 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
body {
font-family: Arial, Helvetica, sans-serif;
@plugin 'tailwindcss-animate';
@custom-variant dark (&:is(.dark *));
@theme {
--animate-spin: spin 1s linear infinite;
--animate-scale-in: scaleIn 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
--color-border: hsl(var(--border));
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-shadcn-primary: hsl(var(--primary));
--color-shadcn-primary-foreground: hsl(var(--primary-foreground));
--color-secondary: hsl(var(--secondary));
--color-secondary-foreground: hsl(var(--secondary-foreground));
--color-destructive: hsl(var(--destructive));
--color-destructive-foreground: hsl(var(--destructive-foreground));
--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));
--color-accent: hsl(var(--accent));
--color-accent-foreground: hsl(var(--accent-foreground));
--color-popover: hsl(var(--popover));
--color-popover-foreground: hsl(var(--popover-foreground));
--color-card: hsl(var(--card));
--color-card-foreground: hsl(var(--card-foreground));
--color-slate-25: rgb(var(--c-s-25, 252 253 254));
--color-slate-50: rgb(var(--c-s-50, 248 250 252));
--color-slate-100: rgb(var(--c-s-100, 241 245 249));
--color-slate-200: rgb(var(--c-s-200, 226 232 240));
--color-slate-300: rgb(var(--c-s-300, 203 213 225));
--color-slate-400: rgb(var(--c-s-400, 148 163 184));
--color-slate-500: rgb(var(--c-s-500, 100 116 139));
--color-slate-600: rgb(var(--c-s-600, 71 85 105));
--color-slate-700: rgb(var(--c-s-700, 51 65 85));
--color-slate-800: rgb(var(--c-s-800, 30 41 59));
--color-slate-900: rgb(var(--c-s-900, 15 23 42));
--color-slate-950: rgb(var(--c-s-950, 2 6 23));
--color-zinc-50: rgb(var(--c-z-50, 249 250 251));
--color-zinc-100: rgb(var(--c-z-100, 243 244 246));
--color-zinc-200: rgb(var(--c-z-200, 229 231 235));
--color-zinc-300: rgb(var(--c-z-300, 209 213 219));
--color-zinc-400: rgb(var(--c-z-400, 156 163 175));
--color-zinc-500: rgb(var(--c-z-500, 107 114 128));
--color-zinc-600: rgb(var(--c-z-600, 75 85 99));
--color-zinc-700: rgb(var(--c-z-700, 50 60 76));
--color-zinc-800: rgb(var(--c-z-800, 22 31 45));
--color-zinc-900: rgb(var(--c-z-900, 17 24 39));
--color-zinc-925: rgb(var(--c-z-925, 8 12 25));
--color-zinc-950: rgb(var(--c-z-950, 5 9 16));
--color-primary-100: rgb(var(--c-p-100, 241 245 249));
--color-primary-900: rgb(var(--c-p-900, 15 23 42));
--color-black: rgb(var(--c-o-black, 0 0 0));
--color-white: rgb(var(--c-o-white, 255 255 255));
--color-sidebar: hsl(var(--sidebar-background));
--color-sidebar-foreground: hsl(var(--sidebar-foreground));
--color-sidebar-primary: hsl(var(--sidebar-primary));
--color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
--color-sidebar-accent: hsl(var(--sidebar-accent));
--color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
--color-sidebar-border: hsl(var(--sidebar-border));
--color-sidebar-ring: hsl(var(--sidebar-ring));
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes scaleIn {
0% {
transform: scale(0.95);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
}
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
@layer utilities {
body {
font-family: Arial, Helvetica, sans-serif;
}
}
.system-ui-font--font-boundary {
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
"Open Sans",
"Helvetica Neue",
sans-serif;
}
@layer base {
@ -93,8 +226,10 @@ body {
}
}
body {
@apply bg-slate-50 text-slate-900 dark:bg-zinc-950 dark:text-zinc-100 accent-slate-950 dark:accent-zinc-50;
@layer utilities {
body {
@apply bg-slate-50 text-slate-900 dark:bg-zinc-950 dark:text-zinc-100 accent-slate-950 dark:accent-zinc-50;
}
}
@layer base {
@ -106,6 +241,29 @@ body {
}
}
.cl-headerTitle {
@apply bg-linear-to-r from-[#3b82f6] to-[#ef4444] bg-clip-text text-transparent;
}
.cl-socialButtonsBlockButtonText__discord {
@apply text-[#5865f2];
}
.cl-socialButtonsBlockButtonText__github {
@apply text-black dark:text-white;
}
.cl-footer {
background: white !important;
&:is(.dark *) {
background: #1e1e24 !important;
}
}
.cl-card {
box-shadow: none !important;
}
@layer base {
::view-transition-old(root),
::view-transition-new(root) {

@ -31,6 +31,8 @@
"use client";
import "./globals.css";
import { useSearchParams } from "next/navigation";
import { ThemeProvider } from "@/components/util/theme-provider";
import { ClerkProvider } from "@/components/util/clerk-provider";
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
@ -45,7 +47,17 @@ export default function RootLayout({
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className={inter.className}>
<noscript>{children}</noscript>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<ClerkProvider>{children}</ClerkProvider>
</ThemeProvider>
</body>
</html>
);
}

@ -90,9 +90,9 @@ export default function Embed({ params }: { params: { server: string } }) {
>
<ServerCrash
size={16}
className="group-hover:text-white p-[4px] group-hover:p-[3px] w-[24px] h-[24px] transition-all bg-gradient-to-r group-hover:from-blue-600 group-hover:to-purple-500 group-hover:rounded"
className="group-hover:text-white p-[4px] group-hover:p-[3px] w-[24px] h-[24px] transition-all bg-linear-to-r group-hover:from-blue-600 group-hover:to-purple-500 group-hover:rounded"
/>
<span className="transition-colors ml-2 group-hover:bg-clip-text group-hover:text-transparent bg-gradient-to-r group-hover:from-blue-600 group-hover:to-purple-500">
<span className="transition-colors ml-2 group-hover:bg-clip-text group-hover:text-transparent bg-linear-to-r group-hover:from-blue-600 group-hover:to-purple-500">
Powered by MHSF
</span>
</Link>

@ -1,5 +1,73 @@
import { Material } from "@/components/ui/material";
import {
Setting,
SettingContent,
SettingDescription,
SettingMeta,
SettingTitle,
} from "./setting";
import { ModeToggle } from "@/components/util/mode-toggle";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useEffect, useState } from "react";
import { useSettingsStore } from "@/lib/hooks/use-settings-store";
export function BrowserSettings() {
return <Material></Material>;
const settingsStore = useSettingsStore();
const [fontFamily, setFontFamily] = useState("inter");
useEffect(() => {
setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
}, [settingsStore]);
return (
<Material className="mt-6 grid gap-4">
<h2 className="text-xl font-semibold text-inherit">Appearance</h2>
<Setting>
<SettingContent>
<SettingMeta>
<SettingTitle>Color Scheme</SettingTitle>
<SettingDescription>
Change the MHSF color scheme
</SettingDescription>
</SettingMeta>
<ModeToggle />
</SettingContent>
</Setting>
<Setting>
<SettingContent>
<SettingMeta>
<SettingTitle>Font</SettingTitle>
<SettingDescription>
Change the default font used in the interface.
</SettingDescription>
</SettingMeta>
<Select
defaultValue="inter"
value={fontFamily}
onValueChange={(c) => {
settingsStore.set("font-family", c, false);
window.dispatchEvent(new Event("font-family-change"));
setFontFamily(c);
}}
>
<SelectTrigger className="max-w-[180px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="inter">Inter</SelectItem>
<SelectItem value="geist-sans">Geist Sans</SelectItem>
<SelectItem value="system-ui">System UI</SelectItem>
<SelectItem value="roboto">Roboto</SelectItem>
</SelectContent>
</Select>
</SettingContent>
</Setting>
</Material>
);
}

@ -0,0 +1,78 @@
import { cn } from "@/lib/utils";
import type { ReactNode } from "react";
export function Setting({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<div
className={cn(
"flex flex-col w-full justify-between gap-2 max-w-full @container/setting",
className
)}
>
{children}
</div>
);
}
export function SettingContent({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<div className="flex flex-col @md/setting:flex-row items-center gap-2">
{children}
</div>
);
}
export function SettingMeta({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<div
className={cn(
"flex flex-col gap-0.5 flex-[2] w-full flex-shrink-0 min-w-48",
className
)}
>
{children}
</div>
);
}
export function SettingTitle({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return <h1 className={cn("font-medium text-base", className)}>{children}</h1>;
}
export function SettingDescription({
className,
children,
}: {
className?: string;
children: ReactNode | ReactNode[] | undefined;
}) {
return (
<p className={cn("text-slate-800 dark:text-zinc-200 text-sm", className)}>
{children}
</p>
);
}

@ -16,7 +16,7 @@ export function Settings() {
<h1 className="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-4xl mb-3">
Settings
</h1>
<Tabs defaultValue="account" className="mt-3">
<Tabs defaultValue="browser-settings" className="mt-3">
<TabsList>
<TabsTrigger
value="browser-settings"
@ -47,10 +47,10 @@ export function Settings() {
</TabsContent>
<TabsContent value="user-settings">
<SignedOut>
<Material className="mt-6 grid gap-4">
<Material className="mt-6 grid gap-4 py-6">
<h3
className={cn(
"scroll-m-20 text-2xl font-semibold tracking-tight bg-gradient-to-r from-[#3b82f6] to-[#ef4444] bg-clip-text text-transparent",
"scroll-m-20 text-2xl font-semibold tracking-tight bg-linear-to-r from-[#3b82f6] to-[#ef4444] bg-clip-text text-transparent",
"w-full flex items-center text-center justify-center"
)}
>

@ -13,35 +13,35 @@ const buttonVariants = cva(
variant: {
default: `border border-transparent bg-primary-900 text-white
dark:bg-primary-100 dark:text-black hover:brightness-125 dark:hover:brightness-90 active:brightness-90
active:dark:brightness-75`,
dark:active:brightness-75`,
secondary: `border border-slate-200 border-b-slate-300 dark:border-zinc-800 dark:border-t-zinc-700/50 bg-white dark:bg-zinc-900
hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 hover:dark:border-zinc-700 active:dark:bg-zinc-900 active:bg-slate-200`,
hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:hover:border-zinc-700 dark:active:bg-zinc-900 active:bg-slate-200`,
tertiary:
"border border-transparent bg-transparent hover:bg-slate-100 hover:dark:bg-zinc-700/30 dark:text-zinc-200",
"border border-transparent bg-transparent hover:bg-slate-100 dark:hover:bg-zinc-700/30 dark:text-zinc-200",
danger:
"border border-red-500 bg-red-500 hover:text-red-500 hover:bg-transparent text-white",
"danger-subtle": "text-red-500 hover:bg-red-500 hover:!text-inherit",
"danger-subtle": "text-red-500 hover:bg-red-500 hover:text-inherit!",
"success-subtle":
"text-green-500 hover:bg-green-500 hover:!text-inherit",
"text-green-500 hover:bg-green-500 hover:text-inherit!",
"warning-subtle":
"text-yellow-500 hover:bg-yellow-500 hover:!text-inherit",
"text-yellow-500 hover:bg-yellow-500 hover:text-inherit!",
ghost: `border border-slate-200 dark:border-zinc-800 bg-transparent
hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 dark:text-zinc-400 hover:text-inherit
hover:dark:text-inherit`,
hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:text-zinc-400 hover:text-inherit
dark:hover:text-inherit`,
elevated: `bg-slate-100 dark:bg-zinc-800 border border-slate-200
dark:border-zinc-700 hover:bg-zinc-200 hover:dark:bg-zinc-700 hover:border-slate-300
hover:dark:border-zinc-600`,
dark:border-zinc-700 hover:bg-zinc-200 dark:hover:bg-zinc-700 hover:border-slate-300
dark:hover:border-zinc-600`,
elevatedLow: `bg-slate-100 dark:bg-zinc-900 border border-slate-200
dark:border-zinc-800 hover:bg-slate-200 hover:dark:bg-zinc-800 hover:border-slate-300
hover:dark:border-zinc-700`,
dark:border-zinc-800 hover:bg-slate-200 dark:hover:bg-zinc-800 hover:border-slate-300
dark:hover:border-zinc-700`,
none: "",
},
@ -63,7 +63,7 @@ const buttonVariants = cva(
right: "justify-end text-right origin-right",
},
shadow: {
sm: "shadow-sm",
sm: "shadow-xs",
none: "shadow-none",
},
rounding: {

@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-5 w-5 shrink-0 rounded-sm border border-slate-200 border-b-slate-300 border-primary transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-shadcn-primary data-[state=checked]:text-shadcn-primary-foreground",
"peer h-5 w-5 shrink-0 rounded-sm border border-slate-200 border-b-slate-300 border-primary transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-shadcn-primary data-[state=checked]:text-shadcn-primary-foreground",
className
)}
{...props}

@ -28,7 +28,7 @@ const ContextMenuSubTrigger = React.forwardRef<
<ContextMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
inset && "pl-8",
className
)}
@ -63,7 +63,7 @@ const ContextMenuContent = React.forwardRef<
<ContextMenuPrimitive.Content
ref={ref}
className={cn(
"backdrop-blur-xl w-max max-w-[280px] z-[100] origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl",
"backdrop-blur-xl w-max max-w-[280px] z-100 origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl",
className
)}
data-align="end"
@ -94,7 +94,7 @@ const ContextMenuItem = React.forwardRef<
<ContextMenuPrimitive.Item
ref={ref}
className={cn(
"w-full px-2 rounded-lg z-[100] min-h-[36px] font-normal flex items-center cursor-pointer hover:dark:bg-zinc-800/70",
"w-full px-2 rounded-lg z-100 min-h-[36px] font-normal flex items-center cursor-pointer dark:hover:bg-zinc-800/70",
props.disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "",
"duration-100 border border-transparent bg-transparent hover:bg-slate-100 dark:text-zinc-200",
className
@ -111,7 +111,7 @@ const ContextMenuCheckboxItem = React.forwardRef<
<ContextMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
checked={checked}
@ -135,7 +135,7 @@ const ContextMenuRadioItem = React.forwardRef<
<ContextMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
{...props}

@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay ref={ref} asChild {...props}>
<motion.div
className={cn(
"fixed bg-[#ffffff]/50 dark:bg-black/50 inset-0 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
"fixed bg-[#ffffff]/50 dark:bg-black/50 inset-0 backdrop-blur-xs data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
)}
initial={{ opacity: 0 }}
@ -65,7 +65,7 @@ const DialogContent = React.forwardRef<
ref={ref}
{...props}
className={cn(
"top-[50%] left-[50%] max-h-[85vh] translate-x-[-50%] translate-y-[-50%] focus:outline-none",
"top-[50%] left-[50%] max-h-[85vh] translate-x-[-50%] translate-y-[-50%] focus:outline-hidden",
"w-full border border-slate-200 border-b-slate-300",
"dark:border-zinc-900 dark:border-t-zinc-800 dark:border-b-zinc-900",
"rounded-2xl max-w-lg box-border mx-auto overscroll-contain shadow-lg overflow-auto",

@ -28,7 +28,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
"flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
inset && "pl-8",
className
)}
@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef<
<DropdownMenuPrimitive.Content
ref={ref}
className={cn(
"backdrop-blur-xl w-max z-[100] max-w-[280px] origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl select-none outline-none",
"backdrop-blur-xl w-max z-100 max-w-[280px] origin-top-left max-h-[32rem] overflow-auto list-none shadow-xl rounded-xl select-none outline-hidden",
className
)}
{...props}
@ -96,7 +96,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"w-full px-2 rounded-lg z-[100] outline-none min-h-[36px] font-normal flex items-center cursor-pointer hover:dark:bg-zinc-800/70",
"w-full px-2 rounded-lg z-100 outline-hidden min-h-[36px] font-normal flex items-center cursor-pointer dark:hover:bg-zinc-800/70",
props.disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "",
"duration-100 border border-transparent bg-transparent hover:bg-slate-100 dark:text-zinc-200",
className
@ -113,7 +113,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
checked={checked}
@ -137,7 +137,7 @@ const DropdownMenuRadioItem = React.forwardRef<
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
{...props}
@ -183,7 +183,7 @@ const DropdownMenuSeparator = React.forwardRef<
{...props}
>
<div>{props.children}</div>
<hr className="flex-shrink flex-1 border-slate-200 dark:border-zinc-800 border-opacity-70" />
<hr className="shrink flex-1 border-slate-200 dark:border-zinc-800 border-opacity-70" />
</DropdownMenuPrimitive.Separator>
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;

@ -14,7 +14,7 @@ const sizeClass = {
};
const shadowClass = {
sm: "shadow-sm",
sm: "shadow-xs",
none: "shadow-none",
};
@ -63,7 +63,7 @@ const Input: React.FC<InputWithLabelProps> = ({
</Label>
)}
<div
className={`${shadowClass[shadow]} border ${borderClass} focus-within:border-primary-900 focus-within:dark:border-primary-100 focus-within:ring-2 ring-slate-300 dark:ring-zinc-700 transition-colors rounded-lg flex flex-row items-center text-sm ${className}`}
className={`${shadowClass[shadow-sm]} border ${borderClass} focus-within:border-primary-900 dark:focus-within:border-primary-100 focus-within:ring-2 ring-slate-300 dark:ring-zinc-700 transition-colors rounded-lg flex flex-row items-center text-sm ${className}`}
>
{prefix && (
<div
@ -79,7 +79,7 @@ const Input: React.FC<InputWithLabelProps> = ({
disabled={disabled}
value={value}
onChange={onChange}
className={`${sizeClass[size]} bg-white dark:bg-zinc-950 focus:outline-none rounded-lg text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:!border-red-500 peer invalid:text-red-500 z-10 ${className}`}
className={`${sizeClass[size]} bg-white dark:bg-zinc-950 focus:outline-hidden rounded-lg text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:border-red-500! peer invalid:text-red-500 z-10 ${className}`}
/>
{suffix && (
<div

@ -7,8 +7,8 @@ const cardVariants = cva("text-sm", {
variants: {
elevation: {
flat: "",
low: "shadow-xs",
medium: "shadow-sm",
low: "shadow-2xs",
medium: "shadow-xs",
high: "shadow-md",
xhigh: "shadow-lg",
max: "shadow-xl",

@ -28,7 +28,7 @@ const RadioGroupItem = React.forwardRef<
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-shadcn-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
"aspect-square h-4 w-4 rounded-full border border-shadcn-primary text-primary shadow-sm focus:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}

@ -20,11 +20,11 @@ const SelectTrigger = React.forwardRef<
ref={ref}
className={cn(
// Select Specific
"appearance-none transition-colors rounded-lg text-sm w-full min-w-full cursor-pointer px-3",
"appearance-none transition-colors rounded-lg text-sm w-full cursor-pointer px-3",
"flex items-center h-9 justify-between",
// Secondary Button Props
"border border-slate-200 border-b-slate-300 dark:border-zinc-800 dark:border-t-zinc-700/50 bg-white dark:bg-zinc-900",
"hover:bg-slate-100 hover:dark:bg-zinc-800 hover:dark:border-zinc-700 active:dark:bg-zinc-900 active:bg-slate-200",
"hover:bg-slate-100 dark:hover:bg-zinc-800 dark:hover:border-zinc-700 dark:active:bg-zinc-900 active:bg-slate-200",
className
)}
{...props}
@ -133,8 +133,8 @@ const SelectItem = React.forwardRef<
ref={ref}
{...props}
className={cn(
"relative flex w-full select-none items-center data-[state=checked]:!bg-slate-100 data-[state=checked]:dark:!bg-zinc-800 rounded-lg py-1.5 pl-2 pr-8 text-sm outline-none focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"w-full px-2 rounded-lg cursor-pointer min-h-[36px] font-normal flex items-center hover:dark:bg-zinc-800/70 hover:bg-slate-100",
"relative flex w-full select-none items-center data-[state=checked]:bg-slate-100! dark:data-[state=checked]:bg-zinc-800! rounded-lg py-1.5 pl-2 pr-8 text-sm outline-hidden focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"w-full px-2 rounded-lg cursor-pointer min-h-[36px] font-normal flex items-center dark:hover:bg-zinc-800/70 hover:bg-slate-100",
disabled ? "opacity-70 pointer-events-none cursor-not-allowed" : "",
"duration-100",
className

@ -64,7 +64,7 @@ const SheetContent = React.forwardRef<
className={cn(sheetVariants({ side }), className)}
{...props}
>
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>

@ -141,7 +141,7 @@ const SidebarProvider = React.forwardRef<
} as React.CSSProperties
}
className={cn(
"group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar",
"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
className
)}
ref={ref}
@ -181,7 +181,7 @@ const Sidebar = React.forwardRef<
return (
<div
className={cn(
"flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground",
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
className
)}
ref={ref}
@ -198,7 +198,7 @@ const Sidebar = React.forwardRef<
<SheetContent
data-sidebar="sidebar"
data-mobile="true"
className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
className="w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
style={
{
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
@ -224,31 +224,31 @@ const Sidebar = React.forwardRef<
{/* This is what handles the sidebar gap on desktop */}
<div
className={cn(
"relative h-svh w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear",
"relative h-svh w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
"group-data-[collapsible=offcanvas]:w-0",
"group-data-[side=right]:rotate-180",
variant === "floating" || variant === "inset"
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon]"
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
)}
/>
<div
className={cn(
"fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex",
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
side === "left"
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
// Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l",
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
className
)}
{...props}
>
<div
data-sidebar="sidebar"
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
>
{children}
</div>
@ -301,9 +301,9 @@ const SidebarRail = React.forwardRef<
title="Toggle Sidebar"
className={cn(
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
"[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
className
@ -323,7 +323,7 @@ const SidebarInset = React.forwardRef<
ref={ref}
className={cn(
"relative flex min-h-svh flex-1 flex-col bg-background",
"peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
"peer-data-[variant=inset]:min-h-[calc(100svh-(--spacing(4)))] md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm",
className
)}
{...props}
@ -439,7 +439,7 @@ const SidebarGroupLabel = React.forwardRef<
ref={ref}
data-sidebar="group-label"
className={cn(
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-hidden ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
className
)}
@ -460,9 +460,9 @@ const SidebarGroupAction = React.forwardRef<
ref={ref}
data-sidebar="group-action"
className={cn(
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-hidden ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden",
"after:absolute after:-inset-2 md:after:hidden",
"group-data-[collapsible=icon]:hidden",
className
)}
@ -512,7 +512,7 @@ const SidebarMenuItem = React.forwardRef<
SidebarMenuItem.displayName = "SidebarMenuItem"
const sidebarMenuButtonVariants = cva(
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
{
variants: {
variant: {
@ -523,7 +523,7 @@ const sidebarMenuButtonVariants = cva(
size: {
default: "h-8 text-sm",
sm: "h-7 text-xs",
lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
},
},
defaultVariants: {
@ -606,9 +606,9 @@ const SidebarMenuAction = React.forwardRef<
ref={ref}
data-sidebar="menu-action"
className={cn(
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-hidden ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden",
"after:absolute after:-inset-2 md:after:hidden",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
@ -669,7 +669,7 @@ const SidebarMenuSkeleton = React.forwardRef<
/>
)}
<Skeleton
className="h-4 max-w-[--skeleton-width] flex-1"
className="h-4 max-w-(--skeleton-width) flex-1"
data-sidebar="menu-skeleton-text"
style={
{
@ -722,7 +722,7 @@ const SidebarMenuSubButton = React.forwardRef<
data-size={size}
data-active={isActive}
className={cn(
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs",
size === "md" && "text-sm",

@ -11,8 +11,8 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex w-11 h-6 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm",
"transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"peer inline-flex w-11 h-6 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs",
"transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-shadcn-primary",
"data-[state=unchecked]:bg-input",
className
@ -22,7 +22,7 @@ const Switch = React.forwardRef<
>
<SwitchPrimitives.Thumb
className={cn(
"box-border w-5 h-full bg-white dark:bg-black rounded-full shadow-sm",
"box-border w-5 h-full bg-white dark:bg-black rounded-full shadow-xs",
"transition data-[state=checked]:translate-x-5"
)}
/>

@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"font-medium rounded-full px-4 py-1 hover:bg-slate-200/40 hover:dark:bg-zinc-700/40 group transition-colors duration-100 relative z-0 flex-shrink-0",
"font-medium rounded-full px-4 py-1 hover:bg-slate-200/40 dark:hover:bg-zinc-700/40 group transition-colors duration-100 relative z-0 shrink-0",
className
)}
{...props}
@ -50,7 +50,7 @@ const TabsContent = React.forwardRef<
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"mt-2 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
)}
{...props}

@ -65,7 +65,7 @@ const TextArea: React.FC<TextAreaProps> = ({
value={value}
onChange={(e) => restProps.onChange?.(e)}
ref={elementRef}
className={`${sizeClass[size]} ${borderClass} focus:border-slate-800 focus:dark:border-zinc-200 bg-white dark:bg-zinc-950 focus:outline-none focus:ring-2 ring-slate-800/50 rounded-xl dark:ring-zinc-200/50 transition-all text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:!border-red-500 peer invalid:text-red-500 z-10 ${className}`}
className={`${sizeClass[size]} ${borderClass} focus:border-slate-800 dark:focus:border-zinc-200 bg-white dark:bg-zinc-950 focus:outline-hidden focus:ring-2 ring-slate-800/50 rounded-xl dark:ring-zinc-200/50 transition-all text-sm w-full disabled:bg-slate-100 disabled:cursor-not-allowed invalid:border-red-500! peer invalid:text-red-500 z-10 ${className}`}
/>
</div>
{restProps.children}

@ -0,0 +1,25 @@
"use client";
import { ClerkProvider as ImportedClerkProvider } from "@clerk/nextjs";
import { dark } from "@clerk/themes";
import { useTheme } from "next-themes";
import { MultisessionAppSupport } from "@clerk/nextjs/internal";
export const ClerkProvider = ({ children }: { children: React.ReactNode }) => {
const { resolvedTheme } = useTheme();
if (resolvedTheme === "dark") {
console.log(resolvedTheme);
return (
<ImportedClerkProvider appearance={{ baseTheme: dark }}>
<MultisessionAppSupport>{children}</MultisessionAppSupport>
</ImportedClerkProvider>
);
}
console.log("a");
return (
<ImportedClerkProvider>
<MultisessionAppSupport>{children}</MultisessionAppSupport>
</ImportedClerkProvider>
);
};

@ -0,0 +1,47 @@
"use client";
import { useSettingsStore } from "@/lib/hooks/use-settings-store";
import { Inter, Roboto } from "next/font/google";
import { useEffect, useState, type ReactNode } from "react";
import { GeistSans } from "geist/font/sans";
const inter = Inter({ subsets: ["latin"] });
const roboto = Roboto({
subsets: ["latin"],
weight: ["100", "300", "400", "500", "700", "900"],
});
export function FontBoundary({
children,
}: {
children?: ReactNode | ReactNode[];
}) {
const settingsStore = useSettingsStore();
const [fontFamily, setFontFamily] = useState("inter");
useEffect(() => {
setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
window.addEventListener("font-family-change", () => {
setFontFamily((settingsStore.get("font-family") ?? "inter") as string);
});
}, [settingsStore]);
return (
<body
className={`font-${fontFamily} ${(() => {
switch (fontFamily) {
case "geist-sans":
return GeistSans.className;
case "roboto":
return roboto.className;
case "inter":
return inter.className;
default:
return "system-ui-font--font-boundary";
}
})()}`}
>
{children}
</body>
);
}

@ -4,6 +4,7 @@ import { Book, ExternalLink, NotebookText } from "lucide-react";
export function Link(
props: LinkProps & {
children?: React.ReactNode;
className?: string;
}
) {
const href = props.href as string;

@ -11,19 +11,17 @@ import {
} from "../ui/dropdown-menu";
export function ModeToggle() {
const { setTheme } = useTheme();
const { setTheme, resolvedTheme } = useTheme();
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="tertiary"
className="flex items-center"
size="square-lg"
>
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
<Button className="flex items-center gap-2">
<span className="flex items-center">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
</span>
{resolvedTheme === "dark" ? "Dark Mode" : "Light Mode"}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">

@ -1,11 +1,17 @@
"use client";
import type * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import * as React from "react";
import { ThemeProvider as NextThemeProvider } from "next-themes";
import type { ThemeProviderProps } from "next-themes";
export function ThemeProvider({
children,
...props
}: React.ComponentProps<typeof NextThemesProvider>) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => {
setMounted(true);
}, []);
if (!mounted) return null;
return <NextThemeProvider {...props}>{children}</NextThemeProvider>;
}

@ -0,0 +1,38 @@
import { useUser } from "@clerk/nextjs";
export function useSettingsStore() {
const { isSignedIn, user } = useUser();
/* Get: (key: string) =>
check if the user is signed in, if so, check user storage & grab entry
if not or if the entry couldn't be found, check browser storage
Set: (key: string, value: string, userEntry: boolean) =>
if user signed in & userEntry === true, send to user storage
if user signed out & userEntry === true, do nothing
if userEntry === false, send to browser
*/
return {
get: (key: string) => {
if (isSignedIn) {
const value = user.publicMetadata[key] as string | boolean;
if (value === undefined) return localStorage.getItem(key);
return value;
}
return localStorage.getItem(key);
},
set: async (key: string, value: string, userEntry: boolean) => {
if (isSignedIn && userEntry === true) {
await fetch("/api/v0/account-sl/change", {
body: JSON.stringify({ [key]: value }),
});
}
if (!isSignedIn && userEntry)
throw new Error("How is this even possible?!?!");
if (userEntry === false) {
localStorage.setItem(key, value);
}
},
};
}

@ -30,52 +30,41 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { clerkClient, getAuth } from "@clerk/nextjs/server";
import z from "zod";
const obj = z.object({
// Use padding on the sides of only the servers, not the whole server list
srv: z.boolean(),
// Items per row (4-6 rows)
ipr: z.number().min(4).max(6),
// Padding of server list (0-120px)
pad: z.number().min(0).max(120),
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
req: NextApiRequest,
res: NextApiResponse,
) {
const { userId } = getAuth(req);
const { userId } = getAuth(req);
if (!userId) {
return res.status(401).json({ error: "Unauthorized" });
}
const { data } = req.body;
if (!userId) {
return res.status(401).json({ error: "Unauthorized" });
}
const { data } = req.body;
if (data === undefined) {
res.status(400).send({ message: "Couldn't find data" });
return;
}
const { type } = req.body;
if (data === undefined) {
res.status(400).send({ message: "Couldn't find data" });
return;
}
if (type === undefined) {
res.status(400).send({ message: "Couldn't find data" });
return;
}
if (data === null) {
await (
await clerkClient()
).users.updateUserMetadata(userId, {
publicMetadata: { [type]: null },
});
res.status(200).send({ message: "Success" });
}
if (type !== "srv" && type !== "ipr" && type !== "pad")
return res.status(400).send({ message: "Couldn't find data" });
const v = obj.parse(data);
for (const [key, value] of Object.entries(v)) {
(await clerkClient()).users.updateUserMetadata(userId, {
publicMetadata: {
[key]: typeof value === "number" ? value.toString() : value,
},
});
}
if (type === "srv" && typeof data !== "boolean")
return res.status(400).send({ message: "Couldn't find data" });
if (type === "ipr" && typeof data !== "number")
return res.status(400).send({ message: "Couldn't find data" });
if (type === "pad" && typeof data !== "number")
return res.status(400).send({ message: "Couldn't find data" });
(await clerkClient()).users.updateUserMetadata(userId, {
publicMetadata: {
[type]: typeof data === "number" ? data.toString() : data,
},
});
res.status(200).send({ message: "Success" });
res.status(200).send({ message: "Success" });
}

@ -1,153 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
import type { Config } from "tailwindcss";
export default {
darkMode: ["class"],
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
keyframes: {
spin: {
"0%": {
transform: "rotate(0deg)",
},
"100%": {
transform: "rotate(360deg)",
},
},
scaleIn: {
"0%": {
transform: "scale(0.95)",
opacity: "0",
},
"100%": {
transform: "scale(1)",
opacity: "1",
},
},
},
animation: {
spin: "spin 1s linear infinite",
"scale-in": "scaleIn 0.2s cubic-bezier(0.34, 1.56, 0.64, 1)",
},
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
"shadcn-primary": {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
slate: {
"25": "rgb(var(--c-s-25,252 253 254) / <alpha-value>)",
"50": "rgb(var(--c-s-50,248 250 252) / <alpha-value>)",
"100": "rgb(var(--c-s-100,241 245 249) / <alpha-value>)",
"200": "rgb(var(--c-s-200,226 232 240) / <alpha-value>)",
"300": "rgb(var(--c-s-300,203 213 225) / <alpha-value>)",
"400": "rgb(var(--c-s-400,148 163 184) / <alpha-value>)",
"500": "rgb(var(--c-s-500,100 116 139) / <alpha-value>)",
"600": "rgb(var(--c-s-600,71 85 105) / <alpha-value>)",
"700": "rgb(var(--c-s-700,51 65 85) / <alpha-value>)",
"800": "rgb(var(--c-s-800,30 41 59) / <alpha-value>)",
"900": "rgb(var(--c-s-900,15 23 42) / <alpha-value>)",
"950": "rgb(var(--c-s-950,2 6 23) / <alpha-value>)",
},
zinc: {
"50": "rgb(var(--c-z-50,249 250 251) / <alpha-value>)",
"100": "rgb(var(--c-z-100,243 244 246) / <alpha-value>)",
"200": "rgb(var(--c-z-200,229 231 235) / <alpha-value>)",
"300": "rgb(var(--c-z-300,209 213 219) / <alpha-value>)",
"400": "rgb(var(--c-z-400,156 163 175) / <alpha-value>)",
"500": "rgb(var(--c-z-500,107 114 128) / <alpha-value>)",
"600": "rgb(var(--c-z-600,75 85 99) / <alpha-value>)",
"700": "rgb(var(--c-z-700,50 60 76) / <alpha-value>)",
"800": "rgb(var(--c-z-800,22 31 45) / <alpha-value>)",
"900": "rgb(var(--c-z-900,17 24 39) / <alpha-value>)",
"925": "rgb(var(--c-z-925,8 12 25) / <alpha-value>)",
"950": "rgb(var(--c-z-950,5 9 16) / <alpha-value>)",
},
primary: {
"100": "rgb(var(--c-p-100,241 245 249) / <alpha-value>)",
"900": "rgb(var(--c-p-900,15 23 42) / <alpha-value>)",
},
black: "rgb(var(--c-o-black,0 0 0) / <alpha-value>)",
white: "rgb(var(--c-o-white,255 255 255) / <alpha-value>)",
sidebar: {
DEFAULT: "hsl(var(--sidebar-background))",
foreground: "hsl(var(--sidebar-foreground))",
primary: "hsl(var(--sidebar-primary))",
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
accent: "hsl(var(--sidebar-accent))",
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
border: "hsl(var(--sidebar-border))",
ring: "hsl(var(--sidebar-ring))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [require("tailwindcss-animate")],
} satisfies Config;

180
yarn.lock

@ -2588,6 +2588,99 @@
resolved "https://registry.yarnpkg.com/@tailwindcss-mangle/shared/-/shared-3.0.0.tgz#8a60fa4168da0069c62fba75f212864ac796c54b"
integrity sha512-h1ateiRm/o0JvRsD5755dyS4H1RPE5sgeyEAOorLGVkGvNawkACtM+0MsiD/ZFNgrfQ7aYDD+DF/dV/8LN5Lmw==
"@tailwindcss/node@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.0.7.tgz#11211457bbe83ff3656c74bf0276e27e9ce87410"
integrity sha512-dkFXufkbRB2mu3FPsW5xLAUWJyexpJA+/VtQj18k3SUiJVLdpgzBd1v1gRRcIpEJj7K5KpxBKfOXlZxT3ZZRuA==
dependencies:
enhanced-resolve "^5.18.1"
jiti "^2.4.2"
tailwindcss "4.0.7"
"@tailwindcss/oxide-android-arm64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.7.tgz#a0864f4831a4eca1a92207fd5ae726343fbb0554"
integrity sha512-5iQXXcAeOHBZy8ASfHFm1k0O/9wR2E3tKh6+P+ilZZbQiMgu+qrnfpBWYPc3FPuQdWiWb73069WT5D+CAfx/tg==
"@tailwindcss/oxide-darwin-arm64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.7.tgz#a25e3831cfb0a9ab5b77ada620b8c714e0f41eab"
integrity sha512-7yGZtEc5IgVYylqK/2B0yVqoofk4UAbkn1ygNpIJZyrOhbymsfr8uUFCueTu2fUxmAYIfMZ8waWo2dLg/NgLgg==
"@tailwindcss/oxide-darwin-x64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.7.tgz#1dae8648aa03c9783cd01cfd1249c781aaa49dd1"
integrity sha512-tPQDV20fBjb26yWbPqT1ZSoDChomMCiXTKn4jupMSoMCFyU7+OJvIY1ryjqBuY622dEBJ8LnCDDWsnj1lX9nNQ==
"@tailwindcss/oxide-freebsd-x64@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.7.tgz#904aaa135e5a2500faf729290b12133f15273500"
integrity sha512-sZqJpTyTZiknU9LLHuByg5GKTW+u3FqM7q7myequAXxKOpAFiOfXpY710FuMY+gjzSapyRbDXJlsTQtCyiTo5w==
"@tailwindcss/oxide-linux-arm-gnueabihf@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.7.tgz#27b6483303218f545a971ec68f468417cab1f6be"
integrity sha512-PBgvULgeSswjd8cbZ91gdIcIDMdc3TUHV5XemEpxlqt9M8KoydJzkuB/Dt910jYdofOIaTWRL6adG9nJICvU4A==
"@tailwindcss/oxide-linux-arm64-gnu@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.7.tgz#98126af54ff0262756e9a4f730a8b6f6585e13c2"
integrity sha512-By/a2yeh+e9b+C67F88ndSwVJl2A3tcUDb29FbedDi+DZ4Mr07Oqw9Y1DrDrtHIDhIZ3bmmiL1dkH2YxrtV+zw==
"@tailwindcss/oxide-linux-arm64-musl@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.7.tgz#55f0183a8521473cab1ca0414b57079efc145952"
integrity sha512-WHYs3cpPEJb/ccyT20NOzopYQkl7JKncNBUbb77YFlwlXMVJLLV3nrXQKhr7DmZxz2ZXqjyUwsj2rdzd9stYdw==
"@tailwindcss/oxide-linux-x64-gnu@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.7.tgz#053b019201892b339c0d975092bfc8024be54226"
integrity sha512-7bP1UyuX9kFxbOwkeIJhBZNevKYPXB6xZI37v09fqi6rqRJR8elybwjMUHm54GVP+UTtJ14ueB1K54Dy1tIO6w==
"@tailwindcss/oxide-linux-x64-musl@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.7.tgz#c4d753acf3d6ef617e91b53880b7c1b966677ca6"
integrity sha512-gBQIV8nL/LuhARNGeroqzXymMzzW5wQzqlteVqOVoqwEfpHOP3GMird5pGFbnpY+NP0fOlsZGrxxOPQ4W/84bQ==
"@tailwindcss/oxide-win32-arm64-msvc@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.7.tgz#cceea5857939092d5149e6afc8da1b8d3a7464b2"
integrity sha512-aH530NFfx0kpQpvYMfWoeG03zGnRCMVlQG8do/5XeahYydz+6SIBxA1tl/cyITSJyWZHyVt6GVNkXeAD30v0Xg==
"@tailwindcss/oxide-win32-x64-msvc@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.7.tgz#500cf333326a45078ca5b0fd68b56b1f0b434bfa"
integrity sha512-8Cva6bbJN7ZJx320k7vxGGdU0ewmpfS5A4PudyzUuofdi8MgeINuiiWiPQ0VZCda/GX88K6qp+6UpDZNVr8HMQ==
"@tailwindcss/oxide@4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.0.7.tgz#b53573fc01b8b61af195ad36957d05c78278761d"
integrity sha512-yr6w5YMgjy+B+zkJiJtIYGXW+HNYOPfRPtSs+aqLnKwdEzNrGv4ZuJh9hYJ3mcA+HMq/K1rtFV+KsEr65S558g==
optionalDependencies:
"@tailwindcss/oxide-android-arm64" "4.0.7"
"@tailwindcss/oxide-darwin-arm64" "4.0.7"
"@tailwindcss/oxide-darwin-x64" "4.0.7"
"@tailwindcss/oxide-freebsd-x64" "4.0.7"
"@tailwindcss/oxide-linux-arm-gnueabihf" "4.0.7"
"@tailwindcss/oxide-linux-arm64-gnu" "4.0.7"
"@tailwindcss/oxide-linux-arm64-musl" "4.0.7"
"@tailwindcss/oxide-linux-x64-gnu" "4.0.7"
"@tailwindcss/oxide-linux-x64-musl" "4.0.7"
"@tailwindcss/oxide-win32-arm64-msvc" "4.0.7"
"@tailwindcss/oxide-win32-x64-msvc" "4.0.7"
"@tailwindcss/postcss@^4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@tailwindcss/postcss/-/postcss-4.0.7.tgz#b8bc02b5e23248ac7cbac1970ed807850e03261c"
integrity sha512-zXcKs1uGssVDlnsQ+iwrkul5GPKvsXPynGCuk/eXLx3DVhHlQKMpA6tXN2oO28x2ki1xRBTfadKiHy2taVvp7g==
dependencies:
"@alloc/quick-lru" "^5.2.0"
"@tailwindcss/node" "4.0.7"
"@tailwindcss/oxide" "4.0.7"
lightningcss "^1.29.1"
postcss "^8.4.41"
tailwindcss "4.0.7"
"@tailwindcss/typography@^0.5.13":
version "0.5.16"
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.16.tgz#a926c8f44d5c439b2915e231cad80058850047c6"
@ -4130,6 +4223,11 @@ destroy@1.2.0:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
detect-libc@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
@ -4326,7 +4424,7 @@ encodeurl@~2.0.0:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
enhanced-resolve@^5.15.0:
enhanced-resolve@^5.15.0, enhanced-resolve@^5.18.1:
version "5.18.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf"
integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==
@ -6119,6 +6217,11 @@ jiti@^1.18.2, jiti@^1.21.6:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9"
integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==
jiti@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
js-cookie@3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc"
@ -6275,6 +6378,74 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"
lightningcss-darwin-arm64@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.1.tgz#dce17349c7b9f968f396ec240503de14e7b4870b"
integrity sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==
lightningcss-darwin-x64@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.1.tgz#e79c984180c57d00ee114210ceced83473d72dfc"
integrity sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==
lightningcss-freebsd-x64@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.1.tgz#4b3aec9620684a60c45266d50fd843869320f42f"
integrity sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==
lightningcss-linux-arm-gnueabihf@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.1.tgz#b80e9c4dd75652bec451ffd4d5779492a01791ff"
integrity sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==
lightningcss-linux-arm64-gnu@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.1.tgz#7825eb119ddf580a4a4f011c6f384a3f9c992060"
integrity sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==
lightningcss-linux-arm64-musl@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.1.tgz#389efccf80088dce2bb00e28bd7d1cfe36a71669"
integrity sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==
lightningcss-linux-x64-gnu@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.1.tgz#98fc5df5e39ac8ddc51e51f785849eb21131f789"
integrity sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==
lightningcss-linux-x64-musl@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.1.tgz#fb4f80895ba7dfa8048ee32e9716a1684fefd6b2"
integrity sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==
lightningcss-win32-arm64-msvc@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.1.tgz#fd4409fd1505d89d0ff66511c36df5a1379eb7cd"
integrity sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==
lightningcss-win32-x64-msvc@1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.1.tgz#54dcd52884f6cbf205a53d49239559603f194927"
integrity sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==
lightningcss@^1.29.1:
version "1.29.1"
resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.29.1.tgz#1d4d62332fc5ba4b6c28e04a8c5638c76019702b"
integrity sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==
dependencies:
detect-libc "^1.0.3"
optionalDependencies:
lightningcss-darwin-arm64 "1.29.1"
lightningcss-darwin-x64 "1.29.1"
lightningcss-freebsd-x64 "1.29.1"
lightningcss-linux-arm-gnueabihf "1.29.1"
lightningcss-linux-arm64-gnu "1.29.1"
lightningcss-linux-arm64-musl "1.29.1"
lightningcss-linux-x64-gnu "1.29.1"
lightningcss-linux-x64-musl "1.29.1"
lightningcss-win32-arm64-msvc "1.29.1"
lightningcss-win32-x64-msvc "1.29.1"
lilconfig@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
@ -8056,7 +8227,7 @@ postcss@8.4.31:
picocolors "^1.0.0"
source-map-js "^1.0.2"
postcss@^8, postcss@^8.4.23, postcss@^8.4.38, postcss@^8.4.39, postcss@^8.4.40, postcss@^8.4.47:
postcss@^8, postcss@^8.4.23, postcss@^8.4.38, postcss@^8.4.39, postcss@^8.4.40, postcss@^8.4.41, postcss@^8.4.47:
version "8.5.2"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.2.tgz#e7b99cb9d2ec3e8dd424002e7c16517cb2b846bd"
integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==
@ -9240,6 +9411,11 @@ tailwindcss@3.3.2:
resolve "^1.22.2"
sucrase "^3.32.0"
tailwindcss@4.0.7, tailwindcss@^4.0.7:
version "4.0.7"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.0.7.tgz#b3e26a5dda77651808a873f1b535cc8c39fcb0ae"
integrity sha512-yH5bPPyapavo7L+547h3c4jcBXcrKwybQRjwdEIVAd9iXRvy/3T1CC6XSQEgZtRySjKfqvo3Cc0ZF1DTheuIdA==
tailwindcss@^3.4.1:
version "3.4.17"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63"