A lexicon-driven AppView for ATProto. happyview.dev
backfill firehose jetstream atproto appview oauth lexicon
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add dark mode

Trezy f50098b9 2410541f

+55 -6
+9 -6
web/src/app/layout.tsx
··· 1 1 import type { Metadata } from "next" 2 2 import { Geist, Geist_Mono } from "next/font/google" 3 + import { ThemeProvider } from "next-themes" 3 4 import "./globals.css" 4 5 import { ConfigProvider } from "@/lib/config-context" 5 6 import { AuthProvider } from "@/lib/auth-context" ··· 26 27 children: React.ReactNode 27 28 }>) { 28 29 return ( 29 - <html lang="en"> 30 + <html lang="en" suppressHydrationWarning> 30 31 <body 31 32 className={`${geistSans.variable} ${geistMono.variable} antialiased`} 32 33 > 33 - <ConfigProvider> 34 - <AuthProvider> 35 - <TooltipProvider>{children}</TooltipProvider> 36 - </AuthProvider> 37 - </ConfigProvider> 34 + <ThemeProvider attribute="class" defaultTheme="system" enableSystem> 35 + <ConfigProvider> 36 + <AuthProvider> 37 + <TooltipProvider>{children}</TooltipProvider> 38 + </AuthProvider> 39 + </ConfigProvider> 40 + </ThemeProvider> 38 41 </body> 39 42 </html> 40 43 )
+4
web/src/components/site-header.tsx
··· 2 2 3 3 import { Separator } from "@/components/ui/separator" 4 4 import { SidebarTrigger } from "@/components/ui/sidebar" 5 + import { ThemeToggle } from "@/components/theme-toggle" 5 6 6 7 export function SiteHeader({ title }: { title: string }) { 7 8 return ( ··· 13 14 className="mx-2 data-[orientation=vertical]:h-4" 14 15 /> 15 16 <h1 className="text-base font-medium">{title}</h1> 17 + <div className="ml-auto"> 18 + <ThemeToggle /> 19 + </div> 16 20 </div> 17 21 </header> 18 22 )
+42
web/src/components/theme-toggle.tsx
··· 1 + "use client" 2 + 3 + import { useTheme } from "next-themes" 4 + import { IconSun, IconMoon, IconDeviceDesktop } from "@tabler/icons-react" 5 + 6 + import { Button } from "@/components/ui/button" 7 + import { 8 + DropdownMenu, 9 + DropdownMenuContent, 10 + DropdownMenuItem, 11 + DropdownMenuTrigger, 12 + } from "@/components/ui/dropdown-menu" 13 + 14 + export function ThemeToggle() { 15 + const { setTheme } = useTheme() 16 + 17 + return ( 18 + <DropdownMenu> 19 + <DropdownMenuTrigger asChild> 20 + <Button variant="ghost" size="icon" className="size-7"> 21 + <IconSun className="size-4 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" /> 22 + <IconMoon className="absolute size-4 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" /> 23 + <span className="sr-only">Toggle theme</span> 24 + </Button> 25 + </DropdownMenuTrigger> 26 + <DropdownMenuContent align="end"> 27 + <DropdownMenuItem onClick={() => setTheme("light")}> 28 + <IconSun className="size-4" /> 29 + Light 30 + </DropdownMenuItem> 31 + <DropdownMenuItem onClick={() => setTheme("dark")}> 32 + <IconMoon className="size-4" /> 33 + Dark 34 + </DropdownMenuItem> 35 + <DropdownMenuItem onClick={() => setTheme("system")}> 36 + <IconDeviceDesktop className="size-4" /> 37 + System 38 + </DropdownMenuItem> 39 + </DropdownMenuContent> 40 + </DropdownMenu> 41 + ) 42 + }