Skip to content

refactor(components): decompose SettingsTab into per-section files#53

Merged
saagpatel merged 5 commits into
masterfrom
codex/refactor/wave5-6-settings-tab
Apr 21, 2026
Merged

refactor(components): decompose SettingsTab into per-section files#53
saagpatel merged 5 commits into
masterfrom
codex/refactor/wave5-6-settings-tab

Conversation

@saagpatel
Copy link
Copy Markdown
Owner

What

Decompose src/components/Settings/SettingsTab.tsx (1842 → 847 LOC shell) into seven new per-section sibling files under src/components/Settings/sections/ plus a useSettingsInit hook that centralizes initial-load orchestration. Exported helpers move to SettingsTab.helpers.ts (re-exported from the shell so existing tests keep working).

Why

Longest settings file in the codebase. Each section has distinct concerns (LLM, KB, Jira, semantic-search, advanced-search, variables, context window) that deserve their own focused file. Per-section tests mock only the props that section actually uses.

How

5 commits:

  1. Move helpers into SettingsTab.helpers.ts (shell re-exports to keep SettingsTab.helpers.test.ts green).
  2. Extract 7 new section components: ModelSection, ContextWindowSection, SemanticSearchSection, KbSection, AdvancedSearchSection, VariablesSection, JiraSection. Section-local state (variable form, jira form, show-other-models toggle) lives inside the owning section.
  3. Extract useSettingsInit hook that centralizes the init fetch orchestration, audit loading, and MemoryKernel preflight refresh.
  4. Add focused unit tests for each new section — 16 new tests. The omnibus SettingsTab.test.tsx stays as the integration suite.
  5. Add stable setter deps to the shell's useCallback arrays to silence exhaustive-deps warnings after the refactor.

Decisions / notes

  • Prop drilling over context: with at most 5 props per section and the shell still owning cross-section state, a SettingsContext would add overhead without measurable clarity gain. Prop drilling kept.
  • Hook-call ordering: the shell still calls the 10 data hooks directly (useLlm, useKb, etc.) and passes their methods into useSettingsInit. Centralizing the hook calls inside the init hook would break the existing SettingsTab.test.tsx mock layout; that shift can be done in a follow-up if the shell's hook list grows further.
  • Named helper re-exports: SettingsTab.tsx re-exports formatBytes, formatSpeed, formatVerificationStatus, getSearchApiEmbeddingBadge, validateQualityThresholds, and formatAuditEvent so SettingsTab.helpers.test.ts keeps passing unchanged.

Testing

  • pnpm ui:gate:static — clean (only pre-existing warnings in other files).
  • pnpm test — 184 tests pass (was 168; +16 new per-section tests).
  • Manual walk of every Settings section is recommended before merge.

Risk

  • Long PR; every commit is individually revertable.
  • Visual snapshot unchanged (DOM structure preserved).
  • No public API changes; SettingsTab default export, helper named exports, and CSS class names preserved.

Extract formatBytes, formatSpeed, formatVerificationStatus,
getSearchApiEmbeddingBadge, validateQualityThresholds, and
formatAuditEvent into SettingsTab.helpers.ts. SettingsTab.tsx
re-exports them so SettingsTab.helpers.test.ts keeps passing
without import changes.
Extract Language Model, Context Window, Semantic Search,
Knowledge Base, Advanced Search, Template Variables, and Jira
sections into dedicated sibling files under sections/. The
SettingsTab shell now orchestrates these section components along
with the previously extracted ops and overview sections. Each
section owns the props it needs; variable-form state lives inside
VariablesSection, jira-form state lives inside JiraSection, and
show-other-models toggle lives inside ModelSection.
Move the cross-section initial data load (Promise.all of 12 hook
fetches), the audit loader, and the MemoryKernel preflight refresh
into useSettingsInit. Shell still calls the 10 data hooks and
orchestrates handlers; the new hook owns the init-driven state plus
the effects that populate it on mount.
Add focused unit tests for ModelSection, ContextWindowSection,
SemanticSearchSection, KbSection, AdvancedSearchSection,
VariablesSection, and JiraSection. Each test mocks only the props
that section needs. The omnibus SettingsTab.test.tsx remains as the
integration suite exercising cross-section flows.
The setters returned by useSettingsInit are stable React setState
references, but eslint's exhaustive-deps lint still wants them in
the dependency arrays. Include them to silence the warnings and
document the dependency clearly.
@saagpatel saagpatel merged commit e5fe843 into master Apr 21, 2026
18 of 19 checks passed
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