feat: enhance sidebar functionality for mobile and compact views

- Introduced a floating toggle button for mobile to show/hide the sidebar when collapsed.
- Updated sidebar behavior to completely hide on mobile when the new mobileSidebarHidden state is true.
- Added logic to conditionally render sidebar components based on screen size using the new useIsCompact hook.
- Enhanced SidebarHeader to include close and expand buttons for mobile views.
- Refactored CollapseToggleButton to hide in compact mode.
- Implemented HeaderActionsPanel for mobile actions in various views, improving accessibility and usability on smaller screens.

These changes improve the user experience on mobile devices by providing better navigation options and visibility controls.
This commit is contained in:
webdevcody
2026-01-16 22:27:19 -05:00
parent 26aaef002d
commit d98cae124f
23 changed files with 982 additions and 362 deletions

View File

@@ -1,11 +1,11 @@
import { useCallback } from 'react';
import { useCallback, useState } from 'react';
import { Switch } from '@/components/ui/switch';
import { Label } from '@/components/ui/label';
import { Wand2, GitBranch, ClipboardCheck } from 'lucide-react';
import { UsagePopover } from '@/components/usage-popover';
import { useAppStore } from '@/store/app-store';
import { useSetupStore } from '@/store/setup-store';
import { useIsMobile } from '@/hooks/use-media-query';
import { useIsTablet } from '@/hooks/use-media-query';
import { AutoModeSettingsPopover } from './dialogs/auto-mode-settings-popover';
import { WorktreeSettingsPopover } from './dialogs/worktree-settings-popover';
import { PlanSettingsPopover } from './dialogs/plan-settings-popover';
@@ -108,7 +108,10 @@ export function BoardHeader({
// Show if Codex is authenticated (CLI or API key)
const showCodexUsage = !!codexAuthStatus?.authenticated;
const isMobile = useIsMobile();
// State for mobile actions panel
const [showActionsPanel, setShowActionsPanel] = useState(false);
const isTablet = useIsTablet();
return (
<div className="flex items-center justify-between gap-5 p-4 border-b border-border bg-glass backdrop-blur-md">
@@ -125,11 +128,13 @@ export function BoardHeader({
</div>
<div className="flex gap-4 items-center">
{/* Usage Popover - show if either provider is authenticated, only on desktop */}
{isMounted && !isMobile && (showClaudeUsage || showCodexUsage) && <UsagePopover />}
{isMounted && !isTablet && (showClaudeUsage || showCodexUsage) && <UsagePopover />}
{/* Mobile view: show hamburger menu with all controls */}
{isMounted && isMobile && (
{/* Tablet/Mobile view: show hamburger menu with all controls */}
{isMounted && isTablet && (
<HeaderMobileMenu
isOpen={showActionsPanel}
onToggle={() => setShowActionsPanel(!showActionsPanel)}
isWorktreePanelVisible={isWorktreePanelVisible}
onWorktreePanelToggle={handleWorktreePanelToggle}
maxConcurrency={maxConcurrency}
@@ -146,7 +151,7 @@ export function BoardHeader({
{/* Desktop view: show full controls */}
{/* Worktrees Toggle - only show after mount to prevent hydration issues */}
{isMounted && !isMobile && (
{isMounted && !isTablet && (
<div className={controlContainerClass} data-testid="worktrees-toggle-container">
<GitBranch className="w-4 h-4 text-muted-foreground" />
<Label
@@ -169,7 +174,7 @@ export function BoardHeader({
)}
{/* Auto Mode Toggle - only show after mount to prevent hydration issues */}
{isMounted && !isMobile && (
{isMounted && !isTablet && (
<div className={controlContainerClass} data-testid="auto-mode-toggle-container">
<Label
htmlFor="auto-mode-toggle"
@@ -193,8 +198,8 @@ export function BoardHeader({
</div>
)}
{/* Plan Button with Settings - only show on desktop, mobile has it in the menu */}
{isMounted && !isMobile && (
{/* Plan Button with Settings - only show on desktop, tablet/mobile has it in the panel */}
{isMounted && !isTablet && (
<div className={controlContainerClass} data-testid="plan-button-container">
{hasPendingPlan && (
<button