Skip to content

refactor: dedupe Settings segmented fieldsets into OptionGroup - #693

Merged
enaboapps merged 1 commit into
mainfrom
refactor/settings-optiongroup-684
Sep 8, 2026
Merged

enaboapps merged 1 commit into
mainfrom
refactor/settings-optiongroup-684

Conversation

@enaboapps

Copy link
Copy Markdown
Contributor

Closes #684. Replaces #692, which GitHub auto-closed when its base branch refactor/settings-module-683 was deleted on merge of #691. Same branch, rebased onto main; the code is unchanged and the review on #692 found no findings.

The eight segmented option fieldsets in SettingsView were hand-rolled copies of the same fieldset > legend > div.segmented > button[aria-pressed] structure. This replaces them with one OptionGroup.

Added to controls.tsx

  • OptionGroup — generic over string | number option values, with an optional columns modifier (three / four / five, omitted entirely for the one group that has no column class) and a children slot for the trailing note that the overlay-visibility fieldset renders inside its fieldset.
  • secondsOptions — builds the {value / 1000}s labels shared by the movement, scroll, key and dwell interval groups. Returns the label as a fragment so the button keeps its two text nodes rather than collapsing to one.
  • overlayVisibilityOptions, overlaySizeOptions.

SettingsView.tsx: 82 → 70 lines.

The pointer-speed fieldset is deliberately untouched

Its buttons carry per-option aria-labels and it renders an exact-speed select plus a movement-values readout, so it is not the same structure. Folding it in would have meant changing DOM.

Byte-identical DOM — verified, not assumed

Rather than relying on the tests passing, the rendered Settings view innerHTML was dumped on the parent commit and on this one and diffed:

State Result
Default settings identical
Every feature toggle enabled, non-default selections across all eight groups identical
All toggles off, zero / out-of-range values identical

The non-default cases matter because the default dump leaves aria-pressed and disabled uniform. Every button was also clicked at both commits to confirm each onChange still writes the same AppSettings key. The dump harness was temporary and is not committed.

Validation

Re-run after the rebase onto main:

Check Result
npm run lint pass
npm test pass — 75 tests, no test file changed
npm run build pass
cargo fmt --check exit 0
cargo clippy --all-targets -- -D warnings exit 0
cargo test exit 0 — 263 + 7 tests

No Rust files are touched; the Rust gates are run per AGENTS.md.

Review note carried over from #692

The review suggested letting T infer from options instead of passing explicit type arguments, so that a future edit attaching the wrong option list would fail to compile. That was tested: with inference enabled, deliberately wiring dwellDelayOptions into the Scroll interval group still compiles clean, because all four interval settings are plain number. The suggestion does not deliver the protection described for the swap that is actually plausible here, so the explicit form was kept.

🤖 Generated with Claude Code

The eight segmented option fieldsets in SettingsView were hand-rolled
copies of the same fieldset > legend > div.segmented > button[aria-pressed]
structure. Replace them with a single OptionGroup component.

Adds to controls.tsx:
- OptionGroup, generic over string | number option values, with an optional
  columns modifier and a children slot for the trailing note that the
  overlay-visibility fieldset renders inside its fieldset
- secondsOptions, which builds the {value / 1000}s labels shared by the
  movement, scroll, key and dwell interval groups
- overlayVisibilityOptions and overlaySizeOptions

The DOM is byte-identical. Verified empirically by dumping the rendered
Settings view innerHTML on the parent commit and on this one and diffing:
identical at default settings, and identical again with every feature
toggle enabled and non-default selections across all eight groups.

The pointer-speed fieldset is left alone; its buttons carry per-option
aria-labels and it renders extra content, so it is not the same structure.

SettingsView.tsx: 82 -> 70 lines. Tests unchanged, 75 passing.

Refs #684

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@enaboapps
enaboapps merged commit 3b00cba into main Sep 8, 2026
9 of 10 checks passed
@enaboapps
enaboapps deleted the refactor/settings-optiongroup-684 branch September 8, 2026 13:50
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.

Deduplicate Settings segmented fieldsets into a shared OptionGroup control (no behavior change)

2 participants