theme switch minimalist

This commit is contained in:
wass08
2026-03-10 12:25:30 +01:00
parent 52bc82d6e1
commit 175040232a
2 changed files with 10 additions and 60 deletions
@@ -6,12 +6,9 @@ import {
ArrowUpCircle, ArrowUpCircle,
ChevronDown, ChevronDown,
Clock3, Clock3,
Moon,
RotateCcw, RotateCcw,
Save, Save,
Sun,
} from "lucide-react"; } from "lucide-react";
import { motion } from "framer-motion";
import { useScene } from "@pascal-app/core"; import { useScene } from "@pascal-app/core";
import { import {
@@ -47,7 +44,6 @@ import {
} from "@/features/community/lib/models/actions"; } from "@/features/community/lib/models/actions";
import { useProjectStore } from "@/features/community/lib/projects/store"; import { useProjectStore } from "@/features/community/lib/projects/store";
import { updateProjectName } from "@/features/community/lib/projects/actions"; import { updateProjectName } from "@/features/community/lib/projects/actions";
import { useViewer } from "@pascal-app/viewer";
import { applySceneGraphToEditor } from "@/features/community/lib/models/hooks"; import { applySceneGraphToEditor } from "@/features/community/lib/models/hooks";
function formatRelativeTime(value: string): string { function formatRelativeTime(value: string): string {
@@ -83,9 +79,6 @@ export function AppSidebar() {
const setIsVersionPreviewMode = useProjectStore((s) => s.setIsVersionPreviewMode); const setIsVersionPreviewMode = useProjectStore((s) => s.setIsVersionPreviewMode);
const setIsSceneLoading = useProjectStore((s) => s.setIsSceneLoading); const setIsSceneLoading = useProjectStore((s) => s.setIsSceneLoading);
const setAutosaveStatus = useProjectStore((s) => s.setAutosaveStatus); const setAutosaveStatus = useProjectStore((s) => s.setAutosaveStatus);
const theme = useViewer((state) => state.theme);
const setTheme = useViewer((state) => state.setTheme);
const [mounted, setMounted] = useState(false);
const [isEditingTitle, setIsEditingTitle] = useState(false); const [isEditingTitle, setIsEditingTitle] = useState(false);
const [titleValue, setTitleValue] = useState(""); const [titleValue, setTitleValue] = useState("");
@@ -107,7 +100,6 @@ export function AppSidebar() {
const activeProjectId = activeProject?.id ?? null; const activeProjectId = activeProject?.id ?? null;
useEffect(() => { useEffect(() => {
setMounted(true);
// Widen default sidebar (288px → 432px) for better project title visibility // Widen default sidebar (288px → 432px) for better project title visibility
const store = useSidebarStore.getState(); const store = useSidebarStore.getState();
if (store.width <= 288) { if (store.width <= 288) {
@@ -700,56 +692,6 @@ export function AppSidebar() {
</PopoverContent> </PopoverContent>
</Popover> </Popover>
)} )}
{mounted && (
<button
className="shrink-0 flex items-center bg-black/20 rounded-full p-1 border border-border/50 cursor-pointer"
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
type="button"
aria-label="Toggle theme"
>
<div className="relative flex">
{/* Sliding Background */}
<motion.div
className="absolute inset-0 bg-[#3A3A3C] shadow-sm rounded-full"
initial={false}
animate={{
x: theme === "light" ? "100%" : "0%",
}}
transition={{
type: "spring",
stiffness: 500,
damping: 35,
}}
style={{ width: "50%" }}
/>
{/* Dark Mode Icon */}
<div
className={cn(
"relative z-10 flex h-6 w-8 items-center justify-center rounded-full transition-colors duration-200 pointer-events-none",
theme === "dark"
? "text-foreground"
: "text-muted-foreground"
)}
>
<Moon className="h-3.5 w-3.5" />
</div>
{/* Light Mode Icon */}
<div
className={cn(
"relative z-10 flex h-6 w-8 items-center justify-center rounded-full transition-colors duration-200 pointer-events-none",
theme === "light"
? "text-foreground"
: "text-muted-foreground"
)}
>
<Sun className="h-3.5 w-3.5" />
</div>
</div>
</button>
)}
</div> </div>
</div> </div>
</SidebarHeader> </SidebarHeader>
@@ -5,6 +5,7 @@ import Link from "next/link";
import Image from "next/image"; import Image from "next/image";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { motion } from "framer-motion";
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
@@ -226,11 +227,18 @@ export function IconRail({
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<button <button
className="flex h-9 w-9 items-center justify-center rounded-lg transition-all text-muted-foreground hover:bg-accent hover:text-accent-foreground mb-2" className="flex h-9 w-9 items-center justify-center rounded-lg border border-border/50 bg-accent/40 transition-all text-foreground hover:bg-accent mb-2"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")} onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
type="button" type="button"
> >
{theme === "dark" ? <Sun className="h-4 w-4" /> : <Moon className="h-4 w-4" />} <motion.div
key={theme}
initial={{ rotate: -90, opacity: 0 }}
animate={{ rotate: 0, opacity: 1 }}
transition={{ duration: 0.25, ease: "easeOut" }}
>
{theme === "dark" ? <Sun className="h-4 w-4" /> : <Moon className="h-4 w-4" />}
</motion.div>
</button> </button>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="right">Toggle theme</TooltipContent> <TooltipContent side="right">Toggle theme</TooltipContent>