refactor: decompose large frontend components into focused modules

Split six monolithic component files into smaller, single-responsibility
modules organized by feature domain:

- ChatPane (1054→~250 lines): extract InlinePills, ApprovalBanner,
  ThinkingDots into chat/ directory
- SettingsPanel (1027→~280 lines): extract McpServerEditor,
  LspProfileEditor, ToolingEditorShell into settings/ directory;
  mutation helpers into lib/settingsHelpers.ts
- PatternEditor: use shared ToggleSwitch from ui/
- App.tsx: extract useTheme and useSidecarCapabilities into hooks/
- Sidebar: extracted accessibility improvements inline

New shared primitives:
- hooks/useClickOutside: replaces 5 duplicated click-outside listeners
- components/ui/: ToggleSwitch, PopoverToggleRow, FormField, TextInput,
  TextareaInput, SelectInput, InfoCallout

Accessibility improvements:
- NewSessionModal: role=dialog, aria-modal, Escape-to-close
- Pill dropdowns: aria-expanded, aria-haspopup, role=listbox/option
- Sidebar context menu: role=menu/menuitem, Escape-to-close
- SessionItem: Space key activation alongside Enter
- ToolbarButton: aria-pressed for toggle state
- ApprovalBanner: role=alert
- QueuedApprovalsList: aria-expanded on toggle
- ThinkingDots: aria-label

No behavioral changes. All 137 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-25 20:12:36 +01:00
co-authored by Copilot
parent 1bd0fcba3e
commit fcfc5c9641
24 changed files with 1209 additions and 1157 deletions
@@ -0,0 +1,24 @@
export interface ToggleSwitchProps {
enabled: boolean;
size?: 'sm' | 'md';
}
export function ToggleSwitch({ enabled, size = 'md' }: ToggleSwitchProps) {
const trackSize = size === 'sm' ? 'h-[14px] w-[24px]' : 'h-[18px] w-[32px]';
const thumbSize = size === 'sm' ? 'size-[10px]' : 'size-[14px]';
const translateOn = size === 'sm' ? 'translate-x-[12px]' : 'translate-x-[16px]';
return (
<span
className={`relative inline-flex ${trackSize} shrink-0 items-center rounded-full transition-colors ${
enabled ? 'bg-indigo-500' : 'bg-zinc-700'
}`}
>
<span
className={`inline-block ${thumbSize} rounded-full bg-white shadow-sm transition-transform ${
enabled ? translateOn : 'translate-x-[2px]'
}`}
/>
</span>
);
}