diff --git a/bun.lockb b/bun.lockb index aa21479..d611580 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 9c6ad3f..55c4ec2 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,15 @@ "lint": "next lint" }, "dependencies": { + "@heroicons/react": "^2.1.5", + "@radix-ui/react-navigation-menu": "^1.2.0", + "@radix-ui/react-slot": "^1.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "framer-motion": "^11.3.30", "lucide-react": "^0.436.0", "next": "14.2.3", + "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", "tailwind-merge": "^2.5.2", diff --git a/public/me.png b/public/me.png new file mode 100644 index 0000000..4e8093e Binary files /dev/null and b/public/me.png differ diff --git a/src/app/(pages)/layout.tsx b/src/app/(pages)/layout.tsx index 7dcf032..8326fa1 100644 --- a/src/app/(pages)/layout.tsx +++ b/src/app/(pages)/layout.tsx @@ -1,6 +1,8 @@ import type { Metadata, Viewport } from "next"; import { Inter } from "next/font/google"; +import { ThemeProvider } from "@/components/theme-provider"; import "../globals.css"; +import { ReactElement } from "react"; const inter = Inter({ subsets: ["latin"] }); @@ -23,9 +25,18 @@ const RootLayout = ({ children, }: Readonly<{ children: React.ReactNode; -}>) => ( +}>): ReactElement => ( - {children} + + + {children} + + ); export default RootLayout; diff --git a/src/app/(pages)/page.tsx b/src/app/(pages)/page.tsx index 931ff0c..788df51 100644 --- a/src/app/(pages)/page.tsx +++ b/src/app/(pages)/page.tsx @@ -1,4 +1,10 @@ +import Navbar from "@/components/landing/navbar"; import { ReactElement } from "react"; -const LandingPage = (): ReactElement =>
Hello World
; +const LandingPage = (): ReactElement => ( +
+ + Page Content +
+); export default LandingPage; diff --git a/src/app/globals.css b/src/app/globals.css index 5913610..a36413a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,7 +4,36 @@ @layer base { :root { - --background: 240 10% 3.9%; + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72.22% 50.59%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5% 64.9%; + --radius: 0.5rem; + + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } + + .dark { + --background: 0 0% 0%; --foreground: 0 0% 98%; --card: 240 10% 3.9%; --card-foreground: 0 0% 98%; @@ -19,10 +48,11 @@ --accent: 240 3.7% 15.9%; --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; + --destructive-foreground: 0 85.7% 97.3%; --border: 240 3.7% 15.9%; --input: 240 3.7% 15.9%; --ring: 240 4.9% 83.9%; + --chart-1: 220 70% 50%; --chart-2: 160 60% 45%; --chart-3: 30 80% 55%; diff --git a/src/components/landing/navbar.tsx b/src/components/landing/navbar.tsx new file mode 100644 index 0000000..6da21e4 --- /dev/null +++ b/src/components/landing/navbar.tsx @@ -0,0 +1,103 @@ +import Image from "next/image"; +import Link from "next/link"; +import { ReactElement } from "react"; +import { + NavigationMenu, + NavigationMenuContent, + NavigationMenuIndicator, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + NavigationMenuViewport, +} from "@/components/ui/navigation-menu"; +import { navigationMenuTriggerStyle } from "@/components/ui/navigation-menu"; +import { HeartIcon } from "@heroicons/react/24/solid"; +import { cn } from "@/lib/utils"; +import ThemeSwitcher from "./theme-switcher"; +import { Button } from "../ui/button"; +import { BookOpenIcon } from "@heroicons/react/24/outline"; +import { SignalIcon } from "@heroicons/react/24/outline"; + +const Navbar = (): ReactElement => ( + +); + +const Branding = (): ReactElement => ( + + My Selfie (: +

RainnnyCLUB

+ +); + +const Links = (): ReactElement => ( + + + {/* Useful Links */} + + Useful Links + + + + + + + + {/* Donate */} + + + + Donate + + + + + + {/* Theme Switcher */} + + + + + +); + +const UsefulLinksContent = (): ReactElement => ( +
+ {/* Wiki */} + + + + + {/* Status Page */} + + + +
+); + +export default Navbar; diff --git a/src/components/landing/theme-switcher.tsx b/src/components/landing/theme-switcher.tsx new file mode 100644 index 0000000..b9debbb --- /dev/null +++ b/src/components/landing/theme-switcher.tsx @@ -0,0 +1,38 @@ +"use client"; + +import { ReactElement } from "react"; +import { MoonStar, Sun } from "lucide-react"; +import { useTheme } from "next-themes"; +import { Button } from "@/components/ui/button"; +import { motion } from "framer-motion"; +import { UseThemeProps } from "next-themes/dist/types"; + +const ThemeSwitcher = (): ReactElement => { + const { theme, setTheme }: UseThemeProps = useTheme(); + const isLight = theme === "light"; + return ( + + ); +}; +export default ThemeSwitcher; diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx new file mode 100644 index 0000000..c527cde --- /dev/null +++ b/src/components/theme-provider.tsx @@ -0,0 +1,9 @@ +"use client"; + +import * as React from "react"; +import { ThemeProvider as NextThemesProvider } from "next-themes"; +import { type ThemeProviderProps } from "next-themes/dist/types"; + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children}; +} diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..0ba4277 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,56 @@ +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 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/components/ui/navigation-menu.tsx b/src/components/ui/navigation-menu.tsx new file mode 100644 index 0000000..58b3b96 --- /dev/null +++ b/src/components/ui/navigation-menu.tsx @@ -0,0 +1,128 @@ +import * as React from "react"; +import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"; +import { cva } from "class-variance-authority"; +import { ChevronDown } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +const NavigationMenu = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + +)); +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName; + +const NavigationMenuList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName; + +const NavigationMenuItem = NavigationMenuPrimitive.Item; + +const navigationMenuTriggerStyle = cva( + "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50", +); + +const NavigationMenuTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children}{" "} + +)); +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName; + +const NavigationMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName; + +const NavigationMenuLink = NavigationMenuPrimitive.Link; + +const NavigationMenuViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ +
+)); +NavigationMenuViewport.displayName = + NavigationMenuPrimitive.Viewport.displayName; + +const NavigationMenuIndicator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +
+ +)); +NavigationMenuIndicator.displayName = + NavigationMenuPrimitive.Indicator.displayName; + +export { + navigationMenuTriggerStyle, + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuLink, + NavigationMenuIndicator, + NavigationMenuViewport, +};