From 589af3d615a087dac73a2bd0bbe27a289eefd915 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 15 May 2026 20:09:49 -0700 Subject: [PATCH] Match workspace filter menu styling (#2032) * Match sidebar filter menu styling * Polish workspace menu layering --- .../src/components/sidebar/SidebarFilter.tsx | 81 +++++++------------ .../src/components/sidebar/SidebarHeader.tsx | 27 +++++++ .../src/components/ui/context-menu.tsx | 4 +- .../src/components/ui/dropdown-menu.tsx | 4 +- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/renderer/src/components/sidebar/SidebarFilter.tsx b/src/renderer/src/components/sidebar/SidebarFilter.tsx index e68d6a45f..05ca6722b 100644 --- a/src/renderer/src/components/sidebar/SidebarFilter.tsx +++ b/src/renderer/src/components/sidebar/SidebarFilter.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useMemo, useState } from 'react' -import { Activity, Check, GitBranch, ListFilter, FolderPlus, Server, X } from 'lucide-react' +import { Check, FolderPlus, ListFilter, Server } from 'lucide-react' import { useAppStore } from '@/store' import { Button } from '@/components/ui/button' import { @@ -16,7 +16,7 @@ import { searchRepos } from '@/lib/repo-search' import { cn } from '@/lib/utils' const menuItemClassName = - 'rounded-[7px] px-2 py-1 text-[12px] leading-5 font-medium transition-colors hover:bg-black/8 hover:text-accent-foreground focus-visible:bg-black/8 focus-visible:text-accent-foreground focus-visible:outline-none dark:hover:bg-white/14 dark:focus-visible:bg-white/14' + 'relative flex cursor-default items-center gap-2 rounded-[7px] px-2 py-1 text-[12px] leading-5 font-medium outline-hidden select-none hover:bg-black/8 hover:text-accent-foreground focus-visible:bg-black/8 focus-visible:text-accent-foreground dark:hover:bg-white/14 dark:focus-visible:bg-white/14' const SidebarFilter = React.memo(function SidebarFilter() { const showActiveOnly = useAppStore((s) => s.showActiveOnly) @@ -84,7 +84,6 @@ const SidebarFilter = React.memo(function SidebarFilter() { }, [repos, setFilterRepoIds]) const clearRepos = useCallback(() => setFilterRepoIds([]), [setFilterRepoIds]) - const closeFilters = useCallback(() => handleOpenChange(false), [handleOpenChange]) return ( @@ -119,52 +118,18 @@ const SidebarFilter = React.memo(function SidebarFilter() { -
- Filters -
- {hasAnyFilter ? ( - - ) : null} - - - - - - Close filters - - -
-
- -
- -
+
} label="Active only" checked={showActiveOnly} onClick={() => setShowActiveOnly(!showActiveOnly)} /> } label="Hide default branch" checked={hideDefaultBranchWorkspace} onClick={() => setHideDefaultBranchWorkspace(!hideDefaultBranchWorkspace)} @@ -175,10 +140,10 @@ const SidebarFilter = React.memo(function SidebarFilter() {
- + Repositories {hasRepoFilter && ( - + {selectedCount} selected )} @@ -257,6 +222,19 @@ const SidebarFilter = React.memo(function SidebarFilter() {
)} + {hasAnyFilter && ( + <> +
+ + + )} + {/* Why: per design, "Add project" stays visible regardless of repo count so users can recover from the 0/1-repo state where the repo section is hidden. */} @@ -280,13 +258,12 @@ const SidebarFilter = React.memo(function SidebarFilter() { }) type ToggleRowProps = { - icon: React.ReactNode label: string checked: boolean onClick: () => void } -function ToggleRow({ icon, label, checked, onClick }: ToggleRowProps) { +function ToggleRow({ label, checked, onClick }: ToggleRowProps) { // Why: the popover is not a true menu, so we use a plain button with // aria-pressed rather than role="menuitemcheckbox". The visible checkmark // carries the state for sighted users. @@ -296,19 +273,15 @@ function ToggleRow({ icon, label, checked, onClick }: ToggleRowProps) { onClick={onClick} aria-pressed={checked} className={cn( - 'flex w-full items-center gap-2 text-left', menuItemClassName, + 'w-full pl-7 text-left', checked ? 'text-foreground' : 'text-muted-foreground' )} > - - {icon} - {label} + + + + {label} ) } diff --git a/src/renderer/src/components/sidebar/SidebarHeader.tsx b/src/renderer/src/components/sidebar/SidebarHeader.tsx index ba08709a4..0533a62a3 100644 --- a/src/renderer/src/components/sidebar/SidebarHeader.tsx +++ b/src/renderer/src/components/sidebar/SidebarHeader.tsx @@ -224,6 +224,33 @@ const SidebarHeader = React.memo(function SidebarHeader() { setWorkspaceBoardMode('persistent') }, [clearWorkspaceBoardHoverClose, clearWorkspaceBoardHoverOpen, setWorkspaceBoardMode]) + useEffect(() => { + if (!workspaceBoardOpen) { + return + } + + const handleKeyDown = (event: KeyboardEvent): void => { + if (event.key !== 'Escape') { + return + } + clearWorkspaceBoardHoverOpen() + clearWorkspaceBoardHoverClose() + workspaceBoardHoverSuppressedRef.current = workspaceHeaderHoveredRef.current + event.preventDefault() + setWorkspaceBoardMode('closed') + } + + // Why: the workspace board is a non-modal companion panel, so focus may + // be outside the sheet when Escape should still dismiss it. + document.addEventListener('keydown', handleKeyDown, true) + return () => document.removeEventListener('keydown', handleKeyDown, true) + }, [ + clearWorkspaceBoardHoverClose, + clearWorkspaceBoardHoverOpen, + setWorkspaceBoardMode, + workspaceBoardOpen + ]) + return ( <>