Files
automaker/apps/ui/src/components/views/board-view/header-mobile-menu.tsx
webdevcody d98cae124f 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.
2026-01-16 22:27:19 -05:00

169 lines
5.7 KiB
TypeScript

import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { Slider } from '@/components/ui/slider';
import {
HeaderActionsPanel,
HeaderActionsPanelTrigger,
} from '@/components/ui/header-actions-panel';
import { Bot, Wand2, Settings2, GitBranch, Zap } from 'lucide-react';
import { cn } from '@/lib/utils';
import { MobileUsageBar } from './mobile-usage-bar';
interface HeaderMobileMenuProps {
// Panel visibility
isOpen: boolean;
onToggle: () => void;
// Worktree panel visibility
isWorktreePanelVisible: boolean;
onWorktreePanelToggle: (visible: boolean) => void;
// Concurrency control
maxConcurrency: number;
runningAgentsCount: number;
onConcurrencyChange: (value: number) => void;
// Auto mode
isAutoModeRunning: boolean;
onAutoModeToggle: (enabled: boolean) => void;
onOpenAutoModeSettings: () => void;
// Plan button
onOpenPlanDialog: () => void;
// Usage bar visibility
showClaudeUsage: boolean;
showCodexUsage: boolean;
}
export function HeaderMobileMenu({
isOpen,
onToggle,
isWorktreePanelVisible,
onWorktreePanelToggle,
maxConcurrency,
runningAgentsCount,
onConcurrencyChange,
isAutoModeRunning,
onAutoModeToggle,
onOpenAutoModeSettings,
onOpenPlanDialog,
showClaudeUsage,
showCodexUsage,
}: HeaderMobileMenuProps) {
return (
<>
<HeaderActionsPanelTrigger isOpen={isOpen} onToggle={onToggle} />
<HeaderActionsPanel isOpen={isOpen} onClose={onToggle} title="Board Controls">
{/* Usage Bar - show if either provider is authenticated */}
{(showClaudeUsage || showCodexUsage) && (
<div className="space-y-2">
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
Usage
</span>
<MobileUsageBar showClaudeUsage={showClaudeUsage} showCodexUsage={showCodexUsage} />
</div>
)}
{/* Controls Section */}
<div className="space-y-1">
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
Controls
</span>
{/* Auto Mode Toggle */}
<div
className="flex items-center justify-between p-3 cursor-pointer hover:bg-accent/50 rounded-lg border border-border/50 transition-colors"
onClick={() => onAutoModeToggle(!isAutoModeRunning)}
data-testid="mobile-auto-mode-toggle-container"
>
<div className="flex items-center gap-2">
<Zap
className={cn(
'w-4 h-4',
isAutoModeRunning ? 'text-yellow-500' : 'text-muted-foreground'
)}
/>
<span className="text-sm font-medium">Auto Mode</span>
</div>
<div className="flex items-center gap-2">
<Switch
id="mobile-auto-mode-toggle"
checked={isAutoModeRunning}
onCheckedChange={onAutoModeToggle}
onClick={(e) => e.stopPropagation()}
data-testid="mobile-auto-mode-toggle"
/>
<button
onClick={(e) => {
e.stopPropagation();
onOpenAutoModeSettings();
}}
className="p-1 rounded hover:bg-accent/50 transition-colors"
title="Auto Mode Settings"
data-testid="mobile-auto-mode-settings-button"
>
<Settings2 className="w-4 h-4 text-muted-foreground" />
</button>
</div>
</div>
{/* Worktrees Toggle */}
<div
className="flex items-center justify-between p-3 cursor-pointer hover:bg-accent/50 rounded-lg border border-border/50 transition-colors"
onClick={() => onWorktreePanelToggle(!isWorktreePanelVisible)}
data-testid="mobile-worktrees-toggle-container"
>
<div className="flex items-center gap-2">
<GitBranch className="w-4 h-4 text-muted-foreground" />
<span className="text-sm font-medium">Worktree Bar</span>
</div>
<Switch
id="mobile-worktrees-toggle"
checked={isWorktreePanelVisible}
onCheckedChange={onWorktreePanelToggle}
onClick={(e) => e.stopPropagation()}
data-testid="mobile-worktrees-toggle"
/>
</div>
{/* Concurrency Control */}
<div
className="p-3 rounded-lg border border-border/50"
data-testid="mobile-concurrency-control"
>
<div className="flex items-center gap-2 mb-3">
<Bot className="w-4 h-4 text-muted-foreground" />
<span className="text-sm font-medium">Max Agents</span>
<span
className="text-sm text-muted-foreground ml-auto"
data-testid="mobile-concurrency-value"
>
{runningAgentsCount}/{maxConcurrency}
</span>
</div>
<Slider
value={[maxConcurrency]}
onValueChange={(value) => onConcurrencyChange(value[0])}
min={1}
max={10}
step={1}
className="w-full"
data-testid="mobile-concurrency-slider"
/>
</div>
{/* Plan Button */}
<Button
variant="outline"
className="w-full justify-start"
onClick={() => {
onOpenPlanDialog();
onToggle();
}}
data-testid="mobile-plan-button"
>
<Wand2 className="w-4 h-4 mr-2" />
Plan
</Button>
</div>
</HeaderActionsPanel>
</>
);
}