From 19f9a3128f8db80bbe6882231d139f5ed1ad7830 Mon Sep 17 00:00:00 2001 From: saidmounaim Date: Wed, 11 Mar 2026 17:21:06 +0000 Subject: [PATCH] feat: add quick theme toggle in sidebar header Add a theme toggle icon button near the T3 Code logo for quick access to theme switching. The toggle shows a sun/moon icon based on the current resolved theme and opens a dropdown with System, Light, and Dark options. - Uses existing useTheme hook for state management - Syncs automatically with Settings page theme selector - Works on both web and desktop (Electron) builds Co-Authored-By: Claude Opus 4.5 --- apps/web/src/components/Sidebar.tsx | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index 8b68c3b8044..a32a9dd8f73 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -3,10 +3,12 @@ import { ChevronRightIcon, FolderIcon, GitPullRequestIcon, + MoonIcon, PlusIcon, RocketIcon, SettingsIcon, SquarePenIcon, + SunIcon, TerminalIcon, TriangleAlertIcon, } from "lucide-react"; @@ -64,6 +66,7 @@ import { import { Alert, AlertAction, AlertDescription, AlertTitle } from "./ui/alert"; import { Button } from "./ui/button"; import { Collapsible, CollapsibleContent } from "./ui/collapsible"; +import { Menu, MenuTrigger, MenuPopup, MenuRadioGroup, MenuRadioItem } from "./ui/menu"; import { Tooltip, TooltipPopup, TooltipTrigger } from "./ui/tooltip"; import { SidebarContent, @@ -81,6 +84,7 @@ import { SidebarTrigger, } from "./ui/sidebar"; import { useThreadSelectionStore } from "../threadSelectionStore"; +import { useTheme } from "../hooks/useTheme"; import { formatWorktreePathForDisplay, getOrphanedWorktreePathForThread } from "../worktreeCleanup"; import { isNonEmpty as isNonEmptyString } from "effect/String"; import { resolveThreadStatusPill, shouldClearThreadSelectionOnMouseDown } from "./Sidebar.logic"; @@ -276,6 +280,7 @@ export default function Sidebar() { const navigate = useNavigate(); const isOnSettings = useLocation({ select: (loc) => loc.pathname === "/settings" }); const { settings: appSettings } = useAppSettings(); + const { theme, setTheme, resolvedTheme } = useTheme(); const routeThreadId = useParams({ strict: false, select: (params) => (params.threadId ? ThreadId.makeUnsafe(params.threadId) : null), @@ -1259,12 +1264,38 @@ export default function Sidebar() { ); + const ThemeIcon = resolvedTheme === "dark" ? MoonIcon : SunIcon; + + const themeDropdown = ( + + + } + > + + + + + System + Light + Dark + + + + ); + return ( <> {isElectron ? ( <> {wordmark} + {themeDropdown} {showDesktopUpdateButton && ( ) : ( - {wordmark} +
+ {wordmark} + {themeDropdown} +
)}