Skip to content

refactor(frontend): organize components into feature folders and split oversized files#73

Merged
sourcehawk merged 2 commits into
mainfrom
worktree-refactor-components-reorg
Jun 4, 2026
Merged

refactor(frontend): organize components into feature folders and split oversized files#73
sourcehawk merged 2 commits into
mainfrom
worktree-refactor-components-reorg

Conversation

@sourcehawk
Copy link
Copy Markdown
Owner

Description

The frontend/components/ directory had ~57 files sitting flat at the top level and several files too large to navigate (SessionView.tsx at 1734 lines, PlaybookEditor.tsx at 1932, Sidebar.tsx at 1284, and more). This PR reorganizes the directory into feature-based folders that mirror the app's route groups, and breaks the ten largest files into co-located sibling files — so a human reader can find things by feature and read any one file in a screen or two. Pure structural refactor: no behavior changes.

Changes

  • Moved the flat component files into feature folders (shared, layout, investigations, watches, playbooks, repos, codefix, connections, mcp, docs) alongside the existing sessions/wiki/inputs, dissolving the single-file proposal/ folder into playbooks/. Files moved with git mv so history follows them.
  • Standardized every component-to-component import on the @/components/<folder>/<Name> alias (previously a mix of relative and alias forms), so each import shows its full location.
  • Split the ten largest files into dot-namespaced siblings in the same folder (reducers, pure helpers, shared types, and trailing leaf sub-components lifted out), leaving each main component body intact. Largest reductions: PlaybookEditor 1932→1538, SessionView 1734→1160, Sidebar 1284→583, NodeEditor 754→163, PlaybookGraph 622→169, LinkedReposPanel 601→117, DocsView 517→185.

Testing

npm run typecheck is clean, the full frontend vitest suite passes (225 tests across 34 files), make frontend produces the Next.js static export and re-syncs the embedded bundle, and the Go binaries compile against the regenerated internal/web/dist. All extractions are verbatim moves — no logic was changed — and the two commits separate the mechanical move/rewrite (reviewable as renames + import edits) from the file splits.

Move the ~57 flat files in frontend/components into feature-based
subfolders (shared, layout, investigations, watches, playbooks, repos,
codefix, connections, mcp, docs) plus the existing sessions/wiki/inputs,
and standardize every component-to-component import on the
@/components/<folder>/<Name> alias. Pure reorganization; no behavior
change. Files moved with git mv to preserve history.
…iblings

Break the ten largest component files into dot-namespaced sibling files
in the same folder (reducers, helpers, types, and trailing leaf
sub-components lifted out), leaving each main component body intact.
Pure structural change; no behavior change.

  PlaybookEditor  1932 -> 1538      SessionView  1734 -> 1160
  Sidebar         1284 ->  583      PlaybookList   998 ->  682
  NodeEditor       754 ->  163      WikiProposalCard 730 -> 516
  PlaybookGraph    622 ->  169      RepoArchitectureView 604 -> 357
  LinkedReposPanel 601 ->  117      DocsView       517 ->  185
Copilot AI review requested due to automatic review settings June 4, 2026 00:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the frontend component structure by organizing components into feature-based folders and standardizing imports to @/components/<folder>/<Name>, while also splitting previously oversized components into smaller co-located modules to improve navigability and maintainability.

Changes:

  • Reorganized frontend/components into feature folders (e.g. shared/, layout/, playbooks/, watches/, repos/, docs/, etc.) and updated imports to use the standardized alias form.
  • Extracted shared UI primitives/utilities (e.g. Spinner, Markdown, Icons, ToolCard, pickers/builders) into components/shared/ and updated callsites.
  • Split/introduced feature modules for larger surfaces (e.g. playbook graph/editor parts, docs view, watch panels, investigation view parts) to reduce file size and co-locate related logic.

Reviewed changes

Copilot reviewed 111 out of 132 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/components/wiki/WikiUpstreamHeader.tsx Update icon imports to shared Icons location.
frontend/components/wiki/WikiProposalNotifier.tsx Add notifier bridging stream events to DOM event for sidebar refresh.
frontend/components/wiki/WikiProposalNotifier.test.tsx Update test import to aliased path.
frontend/components/wiki/WikiProposalCard.tsx Extract preview/files helpers and standardize imports.
frontend/components/wiki/WikiProposalCard.test.tsx Update test import to aliased path.
frontend/components/wiki/WikiProposalCard.preview.tsx New extracted preview/frontmatter parsing helpers.
frontend/components/wiki/WikiProposalCard.files.tsx New extracted raw file rendering helpers.
frontend/components/wiki/WikiNodeEditor.tsx Update icon imports to shared Icons location.
frontend/components/wiki/WikiHome.tsx Use shared Spinner/Paginator imports.
frontend/components/wiki/WikiGraphNodes.tsx Update icon imports to shared Icons location.
frontend/components/wiki/WikiEditor.tsx Update imports (shared UI + moved playbook/wiki components).
frontend/components/wiki/WikiBodyTab.tsx Use shared Markdown/Icons imports.
frontend/components/wiki/PushWikiPRModal.tsx Use shared Spinner/CopyButton imports.
frontend/components/wiki/NewWikiEntryModal.tsx Use shared Spinner/SlackChannelPicker imports.
frontend/components/wiki/EntryRow.tsx Update icon import to shared Icons location.
frontend/components/watches/WatchStatusPill.tsx New watch status pill component with labels/tooltips.
frontend/components/watches/WatchSignalsPanel.tsx Standardize SignalCard import to aliased path.
frontend/components/watches/WatchQueueStrip.tsx New queue strip component (fetch + SSE refresh).
frontend/components/watches/WatchItemsPanel.tsx New items panel component with filtered toggle + items list.
frontend/components/watches/WatchIngestRunsPanel.tsx Use shared Spinner import.
frontend/components/watches/WatchForm.tsx Use shared FilterBuilder/SlackChannelPicker imports.
frontend/components/watches/WatchForm.test.tsx Update test import to aliased path.
frontend/components/watches/WatchesList.tsx Use shared Icons/Spinner and aliased WatchStatusPill import.
frontend/components/watches/WatchesList.test.tsx Update test import to aliased path.
frontend/components/watches/WatchDetailHeader.tsx Use shared Icons/Spinner and aliased WatchStatusPill import.
frontend/components/watches/StartFromSignalDialog.tsx New dialog component for starting investigations from a signal.
frontend/components/watches/SignalCard.tsx Use shared Icons and aliased StartFromSignalDialog import.
frontend/components/watches/SignalCard.test.tsx Update test import to aliased path.
frontend/components/watches/AllWatchesSignalsPanel.tsx New merged signals panel across watches (parallel fetch + SSE refresh).
frontend/components/shared/ToolCard.tsx New shared tool card rendering (inputs/results + nested activity).
frontend/components/shared/Spinner.tsx New shared Spinner component.
frontend/components/shared/SlackChannelPicker.tsx Update to use shared Spinner/FilterableList imports.
frontend/components/shared/Paginator.tsx Update icon import to shared Icons location.
frontend/components/shared/Markdown.tsx New shared Markdown renderer for transcript surfaces.
frontend/components/shared/Icons.tsx Relocated icon surface and updated comment/examples.
frontend/components/shared/FilterBuilder.tsx New shared filter builder for watches.
frontend/components/shared/FilterBuilder.test.tsx Update test import to aliased path.
frontend/components/shared/FilterableList.tsx New shared filterable list component extracted for reuse.
frontend/components/shared/EntityChipsInput.tsx New shared chips input for playbook entity tags.
frontend/components/shared/EntityChipsInput.test.tsx Update test import to aliased path.
frontend/components/shared/CopyButton.tsx Update icon import to shared Icons location.
frontend/components/sessions/UpstreamHome.tsx Use shared Spinner/Paginator imports.
frontend/components/sessions/SessionUpstreamHeader.tsx Update icon imports to shared Icons location.
frontend/components/sessions/SessionDoc.tsx Use shared Markdown/Spinner imports.
frontend/components/sessions/SessionCard.tsx Use shared ExternalLinkIcon import.
frontend/components/sessions/PushSessionPRModal.tsx Use shared Icons/Spinner and updated PushState import path.
frontend/components/repos/RepoSummaryStateProvider.tsx New provider for repo summary status + toast updates via stream.
frontend/components/repos/RepoActivityPanel.tsx Use shared Icons/Spinner imports.
frontend/components/repos/LinkedReposPanel.tsx New linked repos sidebar panel with persisted expand + manage modal.
frontend/components/repos/LinkedReposPanel.list.tsx New repo list rendering + status seeding via summary provider.
frontend/components/playbooks/YamlPanel.tsx Use shared Icons/CopyButton imports.
frontend/components/playbooks/ToolPicker.tsx New searchable tool dropdown for playbook editor.
frontend/components/playbooks/SaveDialog.tsx Use shared Spinner import.
frontend/components/playbooks/ProposalCard.tsx Use shared Spinner and updated ProposalBodyTabs import.
frontend/components/playbooks/ProposalBodyTabs.tsx Update imports for relocated PlaybookGraph/Proposal types.
frontend/components/playbooks/PlaybookList.parts.tsx Extract playbook list footer/pagination parts and use shared Icons.
frontend/components/playbooks/PlaybookList.badges.tsx Extract playbook list badge components.
frontend/components/playbooks/PlaybookGraph.tsx New playbook graph wrapper using xyflow + extracted helpers.
frontend/components/playbooks/PlaybookGraph.layout.ts New extracted graph layout/diff+dagre builder.
frontend/components/playbooks/PlaybookGraph.edges.tsx New extracted custom edge renderer for conditions.
frontend/components/playbooks/PlaybookEditor.reducer.ts New extracted reducer/helpers/types for playbook editor state.
frontend/components/playbooks/PlaybookEditor.parts.tsx New extracted UI parts for playbook editor tabs/actions.
frontend/components/playbooks/NodeEditor.tsx New extracted node editor component.
frontend/components/playbooks/NodeEditor.pickers.tsx New extracted handoff/delegate pickers.
frontend/components/playbooks/NodeEditor.lists.tsx New extracted list editors (branches/args/suggested calls).
frontend/components/playbooks/NodeEditor.inputs.tsx New extracted tool input helpers + args editor.
frontend/components/playbooks/NodeEditor.fields.tsx New extracted field wrappers + shared input classnames.
frontend/components/playbooks/NewTypeModal.tsx Use shared Spinner import.
frontend/components/playbooks/EditorChatDrawer.tsx Use shared Markdown/Spinner/ToolCard and updated imports.
frontend/components/playbooks/DeleteTypeModal.tsx Use shared Spinner import.
frontend/components/playbooks/CommitsDropdown.tsx New commits dropdown with lazy “more” loading.
frontend/components/mcp/MCPStatusBar.tsx New/updated MCP status bar with probe polling + telemetry.
frontend/components/mcp/MCPCatalogView.tsx Use shared Spinner import.
frontend/components/layout/TopNav.tsx New top navigation component with route-derived active tab.
frontend/components/layout/Sidebar.utils.tsx New sidebar helper utilities (sync icon + relative time + view mapping).
frontend/components/layout/Sidebar.test.tsx Update test import to aliased path.
frontend/components/layout/Sidebar.invRow.tsx New extracted investigation row rendering with rename UX.
frontend/components/layout/AppShell.tsx Update imports to new layout folder structure.
frontend/components/investigations/SessionWorkspace.tsx Update imports to aliased feature paths.
frontend/components/investigations/SessionView.test.tsx Update test import to aliased path.
frontend/components/investigations/SessionView.status.tsx New extracted status/badge/action button helpers.
frontend/components/investigations/SessionView.icons.tsx New extracted small SVG icon components used in session UI.
frontend/components/investigations/SessionView.header.tsx New extracted session header (back link, export, latest summary jump).
frontend/components/investigations/SessionView.banners.tsx New extracted auto-mode banners (takeover/finished).
frontend/components/investigations/InvestigationForm.tsx Update shared Spinner/Icons imports.
frontend/components/investigations/InvestigationForm.test.tsx Update test import to aliased path.
frontend/components/investigations/ActivityPanel.tsx Update imports to shared ToolCard/MCPStatusBar + shared Icons.
frontend/components/investigations/ActivityPanel.test.tsx Update test import to aliased path.
frontend/components/inputs/SlackChannelInput.tsx Update SlackChannelPicker import to shared folder.
frontend/components/inputs/ClusterIdInput.tsx Update FilterableList/Spinner imports to shared folder.
frontend/components/docs/DocsView.utils.ts New docs utilities (outline extraction + slugging).
frontend/components/docs/DocsView.tsx New docs surface with section switching + outline tracking.
frontend/components/docs/DocsView.nav.tsx New docs nav section/outline UI.
frontend/components/docs/DocsView.markdown.tsx New docs markdown renderer with Mermaid support + heading anchors.
frontend/components/connections/ConnectionsPanel.tsx Update Icons/Spinner imports to shared folder.
frontend/components/connections/ConnectionsPanel.test.tsx Update test import to aliased path.
frontend/components/connections/ClusterPicker.tsx Update Spinner/FilterableList imports to shared folder.
frontend/components/codefix/PushPRModal.tsx Update Spinner/CopyButton imports to shared folder.
frontend/components/codefix/CodefixPRStateProvider.tsx New provider for codefix PR state updates via stream.
frontend/components/codefix/CodefixProposalCard.tsx Update provider import to aliased path.
frontend/components/codefix/CodefixProposalCard.test.tsx Update test imports to aliased paths.
frontend/app/(main)/watches/new/page.tsx Update WatchForm import to new watches folder.
frontend/app/(main)/watches/client.tsx Update watches component imports to new watches folder.
frontend/app/(main)/watches/[id]/edit/client.tsx Update WatchForm import to new watches folder.
frontend/app/(main)/watches/[id]/client.tsx Update watch detail component imports to new watches folder.
frontend/app/(main)/repos/page.tsx Update RepoArchitectureView import to repos folder.
frontend/app/(main)/repos/client.tsx Update shared UI imports + RepoSummaryStateProvider import path.
frontend/app/(main)/playbooks/page.tsx Update PlaybookList/PlaybookEditor imports to playbooks folder.
frontend/app/(main)/mcp/page.tsx Update MCPCatalogView import to mcp folder.
frontend/app/(main)/layout.tsx Update component imports to new folders + providers/notifier paths.
frontend/app/(main)/investigations/page.tsx Update Spinner import to shared folder.
frontend/app/(main)/investigations/new/page.tsx Update InvestigationForm import to investigations folder.
frontend/app/(main)/investigations/client.tsx Update imports to new folders for workspace + shared UI.
frontend/app/(main)/docs/page.tsx Update DocsView import to docs folder.
frontend/app/(main)/docs/[section]/client.tsx Update DocsView import to docs folder.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +62 to +67
<button
type="button"
onClick={() => setExpanded((v) => !v)}
aria-expanded={expanded}
className="flex w-full items-center justify-between gap-2 px-3 py-2.5 text-left transition hover:bg-zinc-900/40"
>
Comment on lines +74 to +91
<span
role="button"
tabIndex={0}
onClick={(e) => {
e.stopPropagation();
setManageOpen(true);
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
e.stopPropagation();
setManageOpen(true);
}
}}
className="rounded border border-zinc-800 px-1.5 py-0.5 text-xs text-zinc-400 transition hover:border-zinc-600 hover:text-zinc-200"
>
manage
</span>
Comment on lines +31 to +47
<div
role="tab"
aria-selected={active}
aria-disabled={disabled || undefined}
className={
"inline-flex shrink-0 items-center gap-2 rounded-t border-b-2 px-3 py-1.5 text-sm font-medium transition " +
(disabled
? "cursor-not-allowed border-transparent text-zinc-700"
: active
? "border-sky-500 bg-zinc-900/40 text-zinc-100"
: "cursor-pointer border-transparent text-zinc-500 hover:text-zinc-200")
}
onClick={() => {
if (disabled) return;
onClick();
}}
>
Comment on lines +97 to +107
<div
role="tab"
aria-selected={active}
title={payload.playbook_id}
onClick={onClick}
className={
"inline-flex shrink-0 max-w-[14ch] items-center gap-1 rounded-t border-b-2 px-3 py-1.5 text-sm font-medium transition cursor-pointer " +
(active
? "border-sky-500 bg-zinc-900/40 text-zinc-100"
: "border-transparent text-zinc-500 hover:text-zinc-200")
}
@sourcehawk sourcehawk merged commit 17d5984 into main Jun 4, 2026
6 checks passed
@sourcehawk sourcehawk deleted the worktree-refactor-components-reorg branch June 4, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants