mirror of
https://github.com/Lapikud/tipilan.git
synced 2026-03-23 21:34:21 +00:00
Dark mode and sponsors list
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
11
src/components/Theme-provider.tsx
Normal file
11
src/components/Theme-provider.tsx
Normal 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>
|
||||
}
|
||||
59
src/components/ui/button.tsx
Normal file
59
src/components/ui/button.tsx
Normal 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 }
|
||||
257
src/components/ui/dropdown-menu.tsx
Normal file
257
src/components/ui/dropdown-menu.tsx
Normal 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,
|
||||
}
|
||||
Reference in New Issue
Block a user