Skip to content

Split notification-settings.tsx into a hook and section components#799

Merged
selfcontained merged 1 commit into
mainfrom
agt_5a391efd73a7/job-componentizer-a262b568
Jul 19, 2026
Merged

Split notification-settings.tsx into a hook and section components#799
selfcontained merged 1 commit into
mainfrom
agt_5a391efd73a7/job-componentizer-a262b568

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

What

Refactors apps/web/src/components/app/notification-settings.tsx (646 lines) into a logic hook plus focused presentational components. Pure structural refactor — no behavior, DOM, class, or testid changes.

Why it was a candidate

The file mixed three unrelated concerns in one 646-line module:

  • ~250 lines of state/logic (15 useState, 5 refs, 3 useEffect, 8 handlers)
  • two already-standalone device-only sections
  • three server-backed notification regions inline in the render tree

Flagged in the componentizer backlog as "settings form with multiple sections."

New file structure

File Lines Responsibility
notification-settings.tsx 75 thin composition shell
use-notification-settings.ts ~300 all state, refs, effects, handlers (save/test/toggle/permission)
browser-notifications-section.tsx ~160 Browser Notifications region (owns its platform detection)
slack-notifications-section.tsx ~140 Slack webhook + event toggles + save/test actions
notification-device-sections.tsx ~110 SoundCuesSection + TipsSection (device-only toggles)
notification-settings-constants.ts 26 NotifyEventType, response type, EVENT_OPTIONS

Sections communicate only through the hook's return value and props — no cross-dependencies. Section wrappers (border-t/gap-8 layout) are preserved exactly; the Slack group renders as a fragment of its three sibling divs so spacing is unchanged.

Validation

  • pnpm run finalize:web — type check + production build pass
  • pnpm run test:e2e — 168 passed, 13 skipped (pre-existing terminal-live/tmux skips); settings.spec.ts suite green
  • Visual check via Playwright: all sections render in the same order with no console errors; toggling a Slack event correctly enables the Save button (hasChanges flows through the extracted hook)

Next up

Queued for the next run: agent-card.tsx (825 lines) — extract distinct card sections (status, actions, metadata) into subcomponents.

🤖 Generated with Claude Code

notification-settings.tsx was 646 lines mixing all notification state
and logic with the full render tree. Extracted:

- use-notification-settings.ts — all state (15 useState), refs, effects,
  and handlers (save/test/toggle/permission) as a single logic hook
- notification-settings-constants.ts — NotifyEventType, response type,
  EVENT_OPTIONS
- notification-device-sections.tsx — SoundCuesSection + TipsSection
  (device-only local toggles)
- browser-notifications-section.tsx — Browser Notifications region
  (owns its platform detection)
- slack-notifications-section.tsx — Slack webhook + event toggles +
  save/test actions

NotificationSettings is now a 75-line composition shell. Pure structural
refactor — DOM, classes, testids, and behavior are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@selfcontained
selfcontained merged commit d879960 into main Jul 19, 2026
1 check passed
@selfcontained
selfcontained deleted the agt_5a391efd73a7/job-componentizer-a262b568 branch July 19, 2026 08:12
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