Skip to content

Split pins-panel.tsx into per-concern pin modules - #964

Merged
selfcontained merged 1 commit into
mainfrom
agt_ecd461d4dbdb/job-componentizer-b3316d2a
Aug 16, 2026
Merged

Split pins-panel.tsx into per-concern pin modules#964
selfcontained merged 1 commit into
mainfrom
agt_ecd461d4dbdb/job-componentizer-b3316d2a

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

What

apps/web/src/components/app/pins-panel.tsx was 973 lines — the largest component in apps/web by a wide margin (next was agents-view.tsx at 787). It held every layer of the pins feature at once: URL/PR/filename display helpers, the leaf value renderers, the shortcut button, the per-pin dispatcher, the collapsible-group family, the confirm dialog, and the panel shell.

This splits it along the seams the file already had. Every declaration moves whole and unchanged — no hook changes owner, no JSX is reshaped — so the rendered output and behavior are identical.

New file structure

File Lines Contents
pin-value-utils.ts 155 formatPrDisplay, trimFilenameForDisplay, shouldRenderMarkdownAsPlainText, normalizeExternalHref, resolveDisplayValue, ResolvedValue — pure, no JSX
pin-value-row.tsx 146 CopyButton, MarkdownPinBody, PinCaption, PinValueRow — the leaf value primitives
pin-shortcut-item.tsx 169 ShortcutPinItem + DISABLED_PIN_REASON
pin-item.tsx 86 PinItem — dispatches shortcut vs. value pins
pin-group.tsx 204 layoutPins/PinRow, AUTO_COLLAPSE_THRESHOLD, PinGroupView, PersistedPinGroup, EphemeralPinGroup, PinGroup
pins-panel.tsx 233 (was 973) PinList, ConfirmShortcutDialog, PinsPanel

Imports form a DAG (utils → value-row → shortcut-item → item → group → panel), so there are no module cycles. PinItem is no longer re-exported from pins-panel.tsx — nothing outside this cluster imported it. The public surface consumers use (PinList for agent-history-detail-tabs.tsx, PinsPanel for media-sidebar.tsx) is unchanged.

Why this was a candidate

Hit four of the five signals: 973 lines, six logically independent UI regions, mixed concerns (pure URL parsing next to Radix dialogs next to persisted Jotai state), and deep conditional nesting in PinValueRow's href/badge/filename ternary chain.

Validation

  • pnpm run finalize:web — type check + production build pass
  • pnpm run test:e2e — 180 passed, 12 skipped (pre-existing terminal-live skips). Includes the three pins specs: shortcut-button wiring, collapsed-group localStorage round-trip, filename splitting
  • pins-panel.test.tsx (22 tests) + agent-history-detail-tabs.test.tsx (9 tests) green before and after
  • Playwright visual check on a dev stack with all 8 pin types seeded — url, pr, port, code, filename, string, markdown, shortcut — plus a group carrying primary / destructive+confirm / disabled variants. Confirmed the confirm dialog opens and cancels, and the group collapses and re-expands with its count intact (screenshots shared in Dispatch)

Next run

Queued: release-admin.tsx (ReleaseAdmin, 647 lines) — now the largest component in apps/web.

🤖 Generated with Claude Code

pins-panel.tsx had grown to 973 lines — the largest component in
apps/web — holding everything from URL/PR display helpers to the
collapsible group machinery to the panel shell itself.

Move each concern into its own file, whole and unchanged, so no hook
changes owner and the rendered output is identical:

- pin-value-utils.ts    pure display helpers (formatPrDisplay,
                        trimFilenameForDisplay, normalizeExternalHref,
                        resolveDisplayValue, markdown plain-text check)
- pin-value-row.tsx     CopyButton, MarkdownPinBody, PinCaption,
                        PinValueRow — the leaf value primitives
- pin-shortcut-item.tsx ShortcutPinItem and DISABLED_PIN_REASON
- pin-item.tsx          PinItem, the per-pin dispatcher
- pin-group.tsx         layoutPins plus the group/collapse family
- pins-panel.tsx        PinList, ConfirmShortcutDialog, PinsPanel

pins-panel.tsx drops to 233 lines; no new file exceeds 204. Imports
form a DAG, so no module cycles. PinItem is no longer re-exported from
pins-panel.tsx — nothing outside the cluster imported it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@selfcontained
selfcontained merged commit c476eea into main Aug 16, 2026
1 check passed
@selfcontained
selfcontained deleted the agt_ecd461d4dbdb/job-componentizer-b3316d2a branch August 16, 2026 08:14
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.

1 participant