Files
full-stack-fastapi-template/frontend/src/components/Common/Appearance.tsx
T
Alejandra 8c2532a5c3 🛂 Migrate frontend to Shadcn (#2010)
* 🔧 Add Tailwind, update dependencies and config files

* ✨ Introduce new Shadcn components and remove old ones

* 🔧 Update dependencies

* Add new components.json file

* 🔥 Remove Chakra UI files

* 🔧 Add ThemeProvider component and integrate it into main

* 🔥 Remove common components

* Update primary color

* ✨ Add new components

* ✨ Add AuthLayout component

* 🔧 Add utility function cn

* 🔧 Refactor devtools integration and update dependencies

* ✨ Add Footer and Error components

* ♻️ Update Footer

* 🔥 Remove utils

* ♻️ Refactor error handling in useAuth

* ♻️ Refactor useCustomToast

* ♻️ Refactor Login component and form handling

* ♻️ Refactor SignUp component and form handling

* 🔧 Update dependencies

* ♻️ Refactor RecoverPassword component and form handling

* ♻️ Refactor ResetPassword and form handling

* ♻️ Add error component to root route

* ♻️ Refactor error handling in utils

* ♻️ Update buttons

* 🍱 Add icons and logos assets

* ♻️ Refactor Sidebar component

* 🎨 Format

* ♻️ Refactor ThemeProvider

* ♻️ Refactor Common components

* 🔥 Remove old Appearance component

* ✨ Add Sidebar components

* ♻️ Refactor DeleteAccount components

* ♻️ Refactor ChangePassword component

* ♻️ Refactor UserSettings

* ✨ Add TanStack table

* ♻️ Update SignUp

* ✨ Add Select component

* 🎨 Format

* ♻️ Update Footer

* ✨ Add useCopyToClipboard hook

* 🎨 Tweak table styles

* 🎨 Tweak styling

* ♻️ Refactor AddUser and AddItem components

* ♻️ Update DeleteConfirmation

* ✅ Update tests

* ✅ Update tests

* ✅ Fix tests

* ✨ Add DataTable for item and admin management

* ♻️ Refactor DeleteUser and DeleteItem components

* ✅ Fix tests

* ♻️ Refactor EditUser and EditItem components

* ♻️ Refactor UserInformation component

* 🎨 Format

* ♻️ Refactor pending components

* 🎨 Format

* ✅ Update tests

* ✅ Update tests

* ✅ Fix test

* ♻️ Minor tweaks

* ♻️ Update social media links
2025-12-07 13:21:13 +01:00

106 lines
3.2 KiB
TypeScript

import { Monitor, Moon, Sun } from "lucide-react"
import { type Theme, useTheme } from "@/components/theme-provider"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar"
type LucideIcon = React.FC<React.SVGProps<SVGSVGElement>>
const ICON_MAP: Record<Theme, LucideIcon> = {
system: Monitor,
light: Sun,
dark: Moon,
}
export const SidebarAppearance = () => {
const { isMobile } = useSidebar()
const { setTheme, theme } = useTheme()
const Icon = ICON_MAP[theme]
return (
<SidebarMenuItem>
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
<SidebarMenuButton tooltip="Appearance" data-testid="theme-button">
<Icon className="size-4 text-muted-foreground" />
<span>Appearance</span>
<span className="sr-only">Toggle theme</span>
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
side={isMobile ? "top" : "right"}
align="end"
className="w-(--radix-dropdown-menu-trigger-width) min-w-56"
>
<DropdownMenuItem
data-testid="light-mode"
onClick={() => setTheme("light")}
>
<Sun className="mr-2 h-4 w-4" />
Light
</DropdownMenuItem>
<DropdownMenuItem
data-testid="dark-mode"
onClick={() => setTheme("dark")}
>
<Moon className="mr-2 h-4 w-4" />
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
<Monitor className="mr-2 h-4 w-4" />
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
)
}
export const Appearance = () => {
const { setTheme } = useTheme()
return (
<div className="flex items-center justify-center">
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
<Button data-testid="theme-button" variant="outline" size="icon">
<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>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
data-testid="light-mode"
onClick={() => setTheme("light")}
>
<Sun className="mr-2 h-4 w-4" />
Light
</DropdownMenuItem>
<DropdownMenuItem
data-testid="dark-mode"
onClick={() => setTheme("dark")}
>
<Moon className="mr-2 h-4 w-4" />
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
<Monitor className="mr-2 h-4 w-4" />
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
}