feat(panel): light/dark theme
This commit is contained in:
7 files changed
+162
-12
No files matched your search
@@ -1,19 +1,20 @@
|
||||
import { useEffect } from "react";
|
||||
import { NavLink, Outlet } from "react-router-dom";
|
||||
import { Cat, Globe } from "lucide-react";
|
||||
import { Cat, Globe, Sun, Moon } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import * as SelectPrimitive from "@radix-ui/react-select";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTier } from "@/lib/tier";
|
||||
import { visibleSections } from "@/lib/nav";
|
||||
import { Select, SelectContent, SelectItem } from "@/components/ui/select";
|
||||
import { useTheme } from "@/lib/theme";
|
||||
|
||||
function LangToggle() {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
return (
|
||||
<Select value={i18n.language} onValueChange={(v) => i18n.changeLanguage(v)}>
|
||||
<SelectPrimitive.Trigger className="h-7 w-7 p-0 flex items-center justify-center border border-border rounded-md bg-zinc-900/50 hover:bg-accent text-muted-foreground hover:text-foreground focus:outline-none transition-colors shrink-0">
|
||||
<SelectPrimitive.Trigger className="h-7 w-7 p-0 flex items-center justify-center border border-border rounded-md bg-muted/40 hover:bg-accent text-muted-foreground hover:text-foreground focus:outline-none transition-colors shrink-0">
|
||||
<Globe className="h-4 w-4" />
|
||||
</SelectPrimitive.Trigger>
|
||||
<SelectContent align="start" className="min-w-[6rem]">
|
||||
@@ -24,6 +25,26 @@ function LangToggle() {
|
||||
);
|
||||
}
|
||||
|
||||
function ThemeToggle() {
|
||||
const { theme, toggleTheme } = useTheme();
|
||||
const { t } = useTranslation("common");
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="h-7 w-7 p-0 flex items-center justify-center border border-border rounded-md bg-muted/40 hover:bg-accent text-muted-foreground hover:text-foreground focus:outline-none transition-all duration-200 active:scale-95 shrink-0"
|
||||
aria-label={t("toggle_theme")}
|
||||
title={t("toggle_theme")}
|
||||
>
|
||||
{theme === "light" ? (
|
||||
<Sun className="h-4 w-4" />
|
||||
) : (
|
||||
<Moon className="h-4 w-4" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function AppShell() {
|
||||
const { isAdmin } = useTier();
|
||||
const { t, i18n } = useTranslation("navigation");
|
||||
@@ -77,8 +98,11 @@ export function AppShell() {
|
||||
</nav>
|
||||
|
||||
<div className="mt-auto px-3 pt-4 border-t border-border/60">
|
||||
<div className="flex items-start gap-2.5">
|
||||
<LangToggle />
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="flex items-center gap-1.5 shrink-0">
|
||||
<LangToggle />
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
<span className="text-[10px] text-muted-foreground/60 leading-tight pt-1">
|
||||
{t("common:brand_tagline")}
|
||||
</span>
|
||||
@@ -87,9 +111,15 @@ export function AppShell() {
|
||||
</aside>
|
||||
|
||||
<div className="flex min-w-0 flex-1 flex-col">
|
||||
<header className="flex h-14 items-center gap-2 border-b border-border px-4 md:hidden">
|
||||
<Cat className="h-5 w-5 text-primary" />
|
||||
<span className="font-semibold">{t("common:brand_name")}</span>
|
||||
<header className="flex h-14 items-center justify-between border-b border-border px-4 md:hidden">
|
||||
<div className="flex items-center gap-2">
|
||||
<Cat className="h-5 w-5 text-primary" />
|
||||
<span className="font-semibold">{t("common:brand_name")}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<LangToggle />
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</header>
|
||||
<main className="flex-1 p-6">
|
||||
<Outlet />
|
||||
|
||||
Reference in new issue
Block a user