diff --git a/src/features/tmux-installer/renderer/adapters/TmuxInstallerBannerAdapter.ts b/src/features/tmux-installer/renderer/adapters/TmuxInstallerBannerAdapter.ts index 7c5978bb..16cb83d2 100644 --- a/src/features/tmux-installer/renderer/adapters/TmuxInstallerBannerAdapter.ts +++ b/src/features/tmux-installer/renderer/adapters/TmuxInstallerBannerAdapter.ts @@ -26,6 +26,7 @@ export interface TmuxInstallerBannerViewModel { progressPercent: number | null; logs: string[]; manualHints: TmuxInstallHint[]; + manualHintsCollapsible: boolean; primaryGuideUrl: string | null; installSupported: boolean; installDisabled: boolean; @@ -79,6 +80,8 @@ export class TmuxInstallerBannerAdapter { : null; const versionLabel = status?.effective.version ?? status?.host.version ?? status?.wsl?.tmuxVersion ?? null; + const manualHints = status?.autoInstall.manualHints ?? []; + const manualHintsCollapsible = status?.platform === 'win32' && manualHints.length > 0; const installLabel = snapshot.phase === 'idle' && status?.platform === 'win32' && @@ -104,7 +107,8 @@ export class TmuxInstallerBannerAdapter { phase: snapshot.phase, progressPercent: formatTmuxInstallerProgress(snapshot.phase), logs: snapshot.logs, - manualHints: status?.autoInstall.manualHints ?? [], + manualHints, + manualHintsCollapsible, primaryGuideUrl, installSupported: status?.autoInstall.supported ?? false, installDisabled: diff --git a/src/features/tmux-installer/renderer/adapters/__tests__/TmuxInstallerBannerAdapter.test.ts b/src/features/tmux-installer/renderer/adapters/__tests__/TmuxInstallerBannerAdapter.test.ts index 20b89577..742807b4 100644 --- a/src/features/tmux-installer/renderer/adapters/__tests__/TmuxInstallerBannerAdapter.test.ts +++ b/src/features/tmux-installer/renderer/adapters/__tests__/TmuxInstallerBannerAdapter.test.ts @@ -71,6 +71,7 @@ describe('TmuxInstallerBannerAdapter', () => { expect(result.primaryGuideUrl).toBeNull(); expect(result.progressPercent).toBeNull(); expect(result.manualHints).toHaveLength(1); + expect(result.manualHintsCollapsible).toBe(false); expect(result.body).toContain('persistent teammate reliability'); }); @@ -143,6 +144,7 @@ describe('TmuxInstallerBannerAdapter', () => { expect(result.platformLabel).toBe('Windows'); expect(result.primaryGuideUrl).toBe('https://learn.microsoft.com/en-us/windows/wsl/install'); expect(result.progressPercent).toBe(100); + expect(result.manualHintsCollapsible).toBe(true); }); it('keeps the banner visible when tmux is installed but runtime is not ready yet', () => { diff --git a/src/features/tmux-installer/renderer/ui/TmuxInstallerBannerView.tsx b/src/features/tmux-installer/renderer/ui/TmuxInstallerBannerView.tsx index d9fc7621..9b5f2c62 100644 --- a/src/features/tmux-installer/renderer/ui/TmuxInstallerBannerView.tsx +++ b/src/features/tmux-installer/renderer/ui/TmuxInstallerBannerView.tsx @@ -1,6 +1,14 @@ import React from 'react'; -import { AlertTriangle, ExternalLink, RefreshCw, Wrench, XCircle } from 'lucide-react'; +import { + AlertTriangle, + ChevronDown, + ChevronUp, + ExternalLink, + RefreshCw, + Wrench, + XCircle, +} from 'lucide-react'; import { useTmuxInstallerBanner } from '../hooks/useTmuxInstallerBanner'; @@ -28,6 +36,7 @@ export function TmuxInstallerBannerView(): React.JSX.Element | null { const { viewModel, install, cancel, submitInput, refresh, toggleDetails, openExternal } = useTmuxInstallerBanner(); const [inputValue, setInputValue] = React.useState(''); + const [manualHintsExpanded, setManualHintsExpanded] = React.useState(false); React.useEffect(() => { if (!viewModel.acceptsInput) { @@ -35,10 +44,19 @@ export function TmuxInstallerBannerView(): React.JSX.Element | null { } }, [viewModel.acceptsInput]); + React.useEffect(() => { + if (!viewModel.manualHintsCollapsible) { + setManualHintsExpanded(false); + } + }, [viewModel.manualHintsCollapsible]); + if (!viewModel.visible) { return null; } + const manualHintsVisible = + viewModel.manualHints.length > 0 && (!viewModel.manualHintsCollapsible || manualHintsExpanded); + return (