Dark mode and sponsors list

This commit is contained in:
2025-05-01 04:45:29 +03:00
parent 4e65bc5412
commit 6bf3c12b28
17 changed files with 1137 additions and 56 deletions

View File

@@ -2,9 +2,9 @@ import { vipnagorgialla } from "@/components/Vipnagorgialla";
export default function Expo() {
return (
<div className="flex flex-col min-h-[90vh] bg-[#EEE5E5] p-12 pt-18">
<h1 className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] mt-8 mb-4`}>Messiala</h1>
<p className="text-2xl text-[#2A2C3F]">Koostööpartneritega arutamisel. Rohkem infot teel!</p>
<div className="flex flex-col min-h-[90vh] p-12 pt-18">
<h1 className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}>Messiala</h1>
<p className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5]">Koostööpartneritega arutamisel. Rohkem infot teel!</p>
</div>
);
}

View File

@@ -1,10 +1,14 @@
// Head metadata
// import type { Metadata } from "next";
// Provides the theme context to the app
import { ThemeProvider } from "@/components/Theme-provider"
import "./globals.css";
// Fonts
import { Work_Sans } from "next/font/google";
import "./globals.css";
import SidebarParent from "@/components/SidebarParent";
import Footer from "@/components/Footer";
@@ -25,13 +29,20 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<html lang="en" suppressHydrationWarning>
<body
className={`${workSans} antialiased bg-[#EEE5E5]`}
className={`${workSans} antialiased bg-[#EEE5E5] dark:bg-[#0E0F19]`}
>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<SidebarParent />
{children}
<Footer />
</ThemeProvider>
</body>
</html>
);

View File

@@ -6,80 +6,93 @@ export default function Home() {
return (
<div>
{/* Title */}
<div className="border-b-3 border-[#007CAB] flex items-center justify-between pt-18">
<img src="/tipilan-white.svg" alt="TipiLAN Logo" className="h-64"/>
<div className="border-b-3 border-[#007CAB] dark:border-[#00A3E0] flex items-center justify-between pt-18">
<img src="/tipilan-white.svg" alt="TipiLAN Logo" className="h-64 dark:hidden"/>
<img src="/tipilan-dark.svg" alt="TipiLAN Logo" className="h-36 mx-12 my-14 not-dark:hidden"/>
<div className="pr-12 hidden 2xl:block">
<h3 className={`text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F]`}>Auhinnafond</h3>
<h2 className={`text-8xl ${vipnagorgialla.className} font-bold italic text-[#007CAB]`}>10 000</h2>
<h3 className={`text-6xl ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F]`}>Auhinnafond</h3>
<h2 className={`text-8xl ${vipnagorgialla.className} font-bold italic text-[#007CAB] dark:text-[#00A3E0]`}>10 000</h2>
</div>
</div>
{/* Grid of buttons */}
<div className="grid grid-cols-1 xl:grid-cols-3 border-[#007CAB] min-h-[33vh]">
<div className="p-12 flex flex-col justify-between border-b-3 lg:border-r-3 group border-[#007CAB] hover:bg-[#007CAB] transition">
<div className="grid grid-cols-1 xl:grid-cols-3 border-[#007CAB] dark:border-[#00A3E0] min-h-[33vh]">
<div className="p-12 flex flex-col justify-between border-b-3 lg:border-r-3 group border-[#007CAB] dark:border-[#00A3E0] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition">
<Link href="/timetable" prefetch={true}>
<div className="cursor-pointer flex flex-row justify-between">
<h2 className={`text-4xl md:text-5xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] group-hover:text-black`}>
<h2 className={`text-4xl md:text-5xl ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] group-hover:text-black dark:group-hover:text-[#2A2C3F]`}>
Ajakava
</h2>
<MdEast size={'4em'} className="text-[#007CAB] group-hover:translate-x-2 -translate-y-2 group-hover:text-[#EEE5E5] transition"/>
<MdEast size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 -translate-y-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition"/>
</div>
</Link>
<div>
<MdEventNote size={'4em'} className="text-[#007CAB] group-hover:text-[#EEE5E5] mb-4"/>
<p className="text-xl group-hover:text-black">
<MdEventNote size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] mb-4"/>
<p className="text-xl dark:group-hover:text-[#2A2C3F] group-hover:text-black">
TipiLAN on pungil põnevatest turniiridest, mini-võistlustest, loengutest ja paljust muust.
</p>
</div>
</div>
<div className="p-12 flex flex-col justify-between border-b-3 lg:border-r-3 group border-[#007CAB] hover:bg-[#007CAB] transition">
<div className="p-12 flex flex-col justify-between border-b-3 lg:border-r-3 group border-[#007CAB] dark:border-[#00A3E0] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition">
<Link href="/tourney" prefetch={true}>
<div className="cursor-pointer flex flex-row justify-between">
<h2 className={`text-4xl md:text-5xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] group-hover:text-black`}>
<h2 className={`text-4xl md:text-5xl ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}>
Turniirid
</h2>
<MdEast size={'4em'} className="text-[#007CAB] group-hover:translate-x-2 -translate-y-2 group-hover:text-[#EEE5E5] transition"/>
<MdEast size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 -translate-y-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition"/>
</div>
</Link>
<div>
<MdEmojiEvents size={'4em'} className="text-[#007CAB] group-hover:text-[#EEE5E5] mb-4"/>
<p className="text-xl group-hover:text-black">
<MdEmojiEvents size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] mb-4"/>
<p className="text-xl dark:group-hover:text-[#2A2C3F] group-hover:text-black">
TipiLANil toimuvad suurejoonelised Counter-Strike 2 ja League of Legends turniirid, mille auhinnafond on 10 000.
</p>
</div>
</div>
<div className="p-12 flex flex-col justify-between border-b-3 border-[#007CAB] group hover:bg-[#007CAB] transition-all">
<div className="p-12 flex flex-col justify-between border-b-3 border-[#007CAB] dark:border-[#00A3E0] group hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] transition-all">
<Link href="/expo" prefetch={true}>
<div className="cursor-pointer flex flex-row justify-between">
<h2 className={`text-4xl md:text-5xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] group-hover:text-black`}>
<h2 className={`text-4xl md:text-5xl ${vipnagorgialla.className} font-bold italic uppercase dark:text-[#EEE5E5] text-[#2A2C3F] dark:group-hover:text-[#2A2C3F] group-hover:text-black`}>
Messiala
</h2>
<MdEast size={'4em'} className="text-[#007CAB] group-hover:translate-x-2 -translate-y-2 group-hover:text-[#EEE5E5] transition"/>
<MdEast size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] group-hover:translate-x-2 -translate-y-2 dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] transition"/>
</div>
</Link>
<div>
<MdWeekend size={'4em'} className="text-[#007CAB] group-hover:text-[#EEE5E5] mb-4"/>
<p className="text-xl group-hover:text-black">
<MdWeekend size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5] mb-4"/>
<p className="text-xl dark:group-hover:text-[#2A2C3F] group-hover:text-black">
TipiLANi messialal paiknevad ettevõtted, lisategevused ja toimuvad loengud.
</p>
</div>
</div>
</div>
{/* Date */}
<div className={`p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#007CAB] hover:bg-[#007CAB] group transition`}>
<div className={`p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#007CAB] dark:border-[#00A3E0] hover:bg-[#007CAB] dark:hover:bg-[#00A3E0] group transition`}>
<Link href="/tickets" prefetch={true}>
<div className="cursor-pointer text-left flex flex-row justify-between xl:justify-start">
<h3 className="text-4xl md:text-5xl text-[#2A2C3F] group-hover:text-black pb-8">
<h3 className="text-4xl md:text-5xl dark:text-[#EEE5E5] dark:group-hover:text-[#2A2C3F] text-[#2A2C3F] group-hover:text-black pb-8">
Broneeri oma koht juba täna!
</h3>
<MdEast size={'4em'} className="text-[#007CAB] hidden md:block ml-8 group-hover:translate-x-2 -translate-y-2 group-hover:text-[#EEE5E5] transition"/>
<MdEast size={'4em'} className="text-[#007CAB] dark:text-[#00A3E0] hidden md:block ml-8 group-hover:translate-x-2 -translate-y-2 group-hover:text-[#EEE5E5] dark:group-hover:text-[#EEE5E5] transition"/>
</div>
</Link>
<h2 className="text-6xl text-[#007CAB] group-hover:text-[#EEE5E5]">
<h2 className="text-6xl text-[#007CAB] dark:text-[#00A3E0] dark:group-hover:text-[#EEE5E5] group-hover:text-[#EEE5E5]">
24.-26. okt.
</h2>
</div>
{/* Sponsors */}
<div className={`p-12 flex flex-col ${vipnagorgialla.className} font-bold italic border-b-3 border-[#007CAB] dark:border-[#00A3E0]`}>
<div className="text-left flex flex-col justify-between xl:justify-start">
<h3 className="text-4xl md:text-5xl dark:text-[#EEE5E5] text-[#2A2C3F] group-hover:text-black pb-8">
TipiLANi tõmbab käima...
</h3>
<div className="flex flex-row gap-12">
<img src="/sponsors/taltech-color.png" alt="Taltech (Tallinna Tehnikaülikool)" className="h-48 w-48 object-contain"/>
<img src="/sponsors/redbull.png" alt="Redbull" className="h-48 w-48 object-contain"/>
</div>
</div>
</div>
</div>
);
}

View File

@@ -3,8 +3,8 @@ import Link from 'next/link';
export default function Tickets() {
return (
<div className="flex flex-col min-h-[90vh] bg-[#EEE5E5] m-6 mt-16 md:m-16">
<h1 className={`text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] mt-8 md:mt-16 mb-4`}>PILETID JA REGAMINE</h1>
<div className="flex flex-col min-h-[90vh] m-6 mt-16 md:m-16">
<h1 className={`text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 md:mt-16 mb-4`}>PILETID JA REGAMINE</h1>
<div className="flex justify-center lg:items-center flex-col lg:flex-row gap-8 md:gap-12 flex-grow mb-16 md:mt-8 lg:mt-0">
<div className="bg-[#007CAB] -skew-x-2 md:-skew-x-5 text-white px-8 md:px-12 py-16 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]">
<h2 className={`text-6xl ${vipnagorgialla.className} font-bold italic text-[#EEE5E5] pb-2`}>8</h2>

View File

@@ -2,9 +2,9 @@ import { vipnagorgialla } from "@/components/Vipnagorgialla";
export default function Timetable() {
return (
<div className="flex flex-col min-h-[90vh] bg-[#EEE5E5] p-12 pt-18">
<h1 className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] mt-8 mb-4`}>Ajakava</h1>
<p className="text-2xl text-[#2A2C3F]">Lisame ajakava lähiajal.</p>
<div className="flex flex-col min-h-[90vh] p-12 pt-18">
<h1 className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}>Ajakava</h1>
<p className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5]">Lisame ajakava lähiajal.</p>
</div>
);
}

View File

@@ -2,9 +2,9 @@ import { vipnagorgialla } from "@/components/Vipnagorgialla";
export default function Tourney() {
return (
<div className="flex flex-col min-h-[90vh] bg-[#EEE5E5] p-12 pt-18">
<h1 className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] mt-8 mb-4`}>Turniirid</h1>
<p className="text-2xl text-[#2A2C3F]">Kui tahate oma oskusi proovile panna siis vaadake siia tagasi! Rohkem infot lähiajal.</p>
<div className="flex flex-col min-h-[90vh] p-12 pt-18">
<h1 className={`text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic uppercase text-[#2A2C3F] dark:text-[#EEE5E5] mt-8 mb-4`}>Turniirid</h1>
<p className="text-2xl text-[#2A2C3F] dark:text-[#EEE5E5]">Kui tahate oma oskusi proovile panna siis vaadake siia tagasi! Rohkem infot lähiajal.</p>
</div>
);
}

View File

@@ -2,17 +2,18 @@ import { SiDiscord, SiInstagram, SiFacebook } from "react-icons/si";
const Footer = () => (
<div className="flex items-center justify-center sm:justify-between flex-col sm:flex-row h-60 px-12">
<img src="/tipilan-white.svg" alt="TipiLAN Logo" className="h-16"/>
<img src="/tipilan-white.svg" alt="TipiLAN Logo" className="h-16 dark:hidden"/>
<img src="/tipilan-dark.svg" alt="TipiLAN Logo" className="h-9 ml-3 not-dark:hidden"/>
{/* Social media */}
<div className="flex flex-row">
<a href="https://discord.gg/eB7sVqgJ9b" target="_blank" rel="noopener noreferrer">
<SiDiscord title="Discord" size={'2em'} className="mx-4 text-[#2A2C3F]"/>
<SiDiscord title="Discord" size={'2em'} className="mx-4 text-[#2A2C3F] dark:text-[#EEE5E5]"/>
</a>
<a href="https://instagram.com/tipilan.ee" target="_blank" rel="noopener noreferrer">
<SiInstagram title="Instagram" size={'2em'} className="mx-4 text-[#2A2C3F]"/>
<SiInstagram title="Instagram" size={'2em'} className="mx-4 text-[#2A2C3F] dark:text-[#EEE5E5]"/>
</a>
<a href="https://facebook.com/tipilan.ee" target="_blank" rel="noopener noreferrer">
<SiFacebook title="Facebook" size={'2em'} className="mx-4 text-[#2A2C3F]"/>
<SiFacebook title="Facebook" size={'2em'} className="mx-4 text-[#2A2C3F] dark:text-[#EEE5E5]"/>
</a>
</div>
</div>

View File

@@ -1,20 +1,57 @@
'use client';
// Icons
import { MdClose, MdMenu } from "react-icons/md";
import { MdClose, MdMenu, MdSunny, MdModeNight } from "react-icons/md";
// Theme Provider
import { useTheme } from "next-themes"
// Shadcn UI
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
// Fonts
import { vipnagorgialla } from "@/components/Vipnagorgialla";
const Header = ({ isOpen, toggleSidebar }: { isOpen: boolean; toggleSidebar: () => void }) => (
<header className="h-16 flex items-center bg-[#EEE5E5] border-b-3 border-[#007CAB] justify-between px-12 text-[#2A2C3F]">
<button onClick={toggleSidebar}>
{isOpen ? (
<MdClose className="h-12 w-12 text-[#2A2C3F]" />
) : (
<MdMenu className="h-12 w-12 text-[#2A2C3F]" />
)}
</button>
<p className={`text-3xl ${vipnagorgialla.className} font-bold italic hidden`}>ENG</p>
</header>
);
const Header = ({ isOpen, toggleSidebar }: { isOpen: boolean; toggleSidebar: () => void }) => {
const { setTheme } = useTheme();
return (
<header className="h-16 flex items-center bg-[#EEE5E5] dark:bg-[#0E0F19] border-b-3 border-[#007CAB] dark:border-[#00A3E0] justify-between px-12 text-[#2A2C3F] dark:text-[#EEE5E5]">
<button onClick={toggleSidebar}>
{isOpen ? (
<MdClose className="h-12 w-12 text-[#2A2C3F] dark:text-[#EEE5E5]" />
) : (
<MdMenu className="h-12 w-12 text-[#2A2C3F] dark:text-[#EEE5E5]" />
)}
</button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<MdSunny className="scale-150 text-[#2A2C3F] dark:hidden"/>
<MdModeNight className="scale-150 dark:text-[#EEE5E5] not-dark:hidden"/>
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48 translate-y-4">
<DropdownMenuItem className="text-xl" onClick={() => setTheme('light')}>
Light
</DropdownMenuItem>
<DropdownMenuItem className="text-xl" onClick={() => setTheme('dark')}>
Dark
</DropdownMenuItem>
<DropdownMenuItem className="text-xl" onClick={() => setTheme('system')}>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</header>
);
};
export default Header;

View File

@@ -26,7 +26,7 @@ const Sidebar = ({ isOpen, toggleSidebar }: { isOpen: boolean; toggleSidebar: ()
onClick={toggleSidebar} // Close sidebar when clicking outside
></div>
<div
className={`text-5xl ${vipnagorgialla.className} font-bold italic uppercase fixed flex items-center flex-col gap-8 pt-16 top-0 left-0 h-[99vh] mt-16 -skew-x-5 border-r-3 border-[#007CAB] w-screen sm:w-128 bg-[#EEE5E5] text-[#2A2C3F] transition-transform transform z-20`}
className={`text-5xl ${vipnagorgialla.className} font-bold italic uppercase fixed flex items-center flex-col gap-8 pt-16 top-0 left-0 h-[99vh] mt-16 -skew-x-5 border-r-3 border-[#007CAB] dark:border-[#00A3E0] w-screen sm:w-128 bg-[#EEE5E5] dark:bg-[#0E0F19] text-[#2A2C3F] dark:text-[#EEE5E5] transition-transform transform z-20`}
style={{ transform: isOpen ? 'translateX(-10%) skewX(calc(5deg * -1)' : 'translateX(-150%) skewX(calc(5deg * -1)' }}
>
<Link href="/" prefetch={true} onClick={toggleSidebar}>Avaleht</Link>

View File

@@ -0,0 +1,11 @@
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
export function ThemeProvider({
children,
...props
}: React.ComponentProps<typeof NextThemesProvider>) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

View File

@@ -0,0 +1,59 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
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-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-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",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant,
size,
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }

View File

@@ -0,0 +1,257 @@
"use client"
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function DropdownMenu({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
}
function DropdownMenuPortal({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
return (
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
)
}
function DropdownMenuTrigger({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
return (
<DropdownMenuPrimitive.Trigger
data-slot="dropdown-menu-trigger"
{...props}
/>
)
}
function DropdownMenuContent({
className,
sideOffset = 4,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
return (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
className
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
)
}
function DropdownMenuGroup({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
return (
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
)
}
function DropdownMenuItem({
className,
inset,
variant = "default",
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
variant?: "default" | "destructive"
}) {
return (
<DropdownMenuPrimitive.Item
data-slot="dropdown-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function DropdownMenuCheckboxItem({
className,
children,
checked,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
return (
<DropdownMenuPrimitive.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
checked={checked}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CheckIcon className="size-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
)
}
function DropdownMenuRadioGroup({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
return (
<DropdownMenuPrimitive.RadioGroup
data-slot="dropdown-menu-radio-group"
{...props}
/>
)
}
function DropdownMenuRadioItem({
className,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
return (
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CircleIcon className="size-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
)
}
function DropdownMenuLabel({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
}) {
return (
<DropdownMenuPrimitive.Label
data-slot="dropdown-menu-label"
data-inset={inset}
className={cn(
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
className
)}
{...props}
/>
)
}
function DropdownMenuSeparator({
className,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
return (
<DropdownMenuPrimitive.Separator
data-slot="dropdown-menu-separator"
className={cn("bg-border -mx-1 my-1 h-px", className)}
{...props}
/>
)
}
function DropdownMenuShortcut({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="dropdown-menu-shortcut"
className={cn(
"text-muted-foreground ml-auto text-xs tracking-widest",
className
)}
{...props}
/>
)
}
function DropdownMenuSub({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
}
function DropdownMenuSubTrigger({
className,
inset,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
}) {
return (
<DropdownMenuPrimitive.SubTrigger
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
className
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto size-4" />
</DropdownMenuPrimitive.SubTrigger>
)
}
function DropdownMenuSubContent({
className,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
return (
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
className
)}
{...props}
/>
)
}
export {
DropdownMenu,
DropdownMenuPortal,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
}