Skip to content

fix(configurator): add per-category reset button, fix invisible reset icons - #468

Merged
jackgranatowski merged 4 commits into
mainfrom
claude/configurator-reset-ui-fixes-wt1jqs
Jul 1, 2026
Merged

fix(configurator): add per-category reset button, fix invisible reset icons#468
jackgranatowski merged 4 commits into
mainfrom
claude/configurator-reset-ui-fixes-wt1jqs

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Wire up the panel header with a "Reset N" button that clears just the
active category's overrides (the matching logic already existed unused
in DomainPanel.svelte). Also fix per-token reset controls that relied on
bare opacity-0 group-hover:opacity-100, which never becomes visible on
touch devices or via keyboard focus — apply the same opacity-100 below
sm:, group-focus-within/focus fallback already used correctly in
ThemesPanel.svelte across TokenRow, SliderRow, PowerKnobRow, and the
inline reset buttons in MiscPanel/TypographyPanel/MotionPanel.

Summary by CodeRabbit

  • New Features

    • Added a domain-specific reset action that clears only settings tied to the currently selected domain, leaving other customizations intact.
  • Bug Fixes

    • Corrected the “All tokens” tab badge count to accurately reflect overrides for the active domain.
  • UI Improvements

    • Refined reset/close/toggle control visibility across panels for better responsiveness on small screens, plus improved focus/hover accessibility.

… icons

Wire up the panel header with a "Reset N" button that clears just the
active category's overrides (the matching logic already existed unused
in DomainPanel.svelte). Also fix per-token reset controls that relied on
bare `opacity-0 group-hover:opacity-100`, which never becomes visible on
touch devices or via keyboard focus — apply the same opacity-100 below
`sm:`, group-focus-within/focus fallback already used correctly in
ThemesPanel.svelte across TokenRow, SliderRow, PowerKnobRow, and the
inline reset buttons in MiscPanel/TypographyPanel/MotionPanel.
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Configurator: per-category reset button + accessible reset controls

🐞 Bug fix ✨ Enhancement 🕐 20-40 Minutes

Grey Divider

AI Description

• Add a panel-header “Reset N” action to clear overrides scoped to the active category.
• Fix reset controls visibility on touch/keyboard by adding focus and mobile opacity fallbacks.
• Consolidate domain-scoped reset logic in App (single owner of overrides state).
Diagram

graph TD
  A["App.svelte"] --> B[("overrides state")]
  A --> C["Panel header"] --> D["Reset N button"] --> E["handleResetDomain"] --> F["handleBulkChange"] --> B
  A --> G["DomainPanel"]
  A --> H["domains.ts (DOMAIN_PATTERNS)"] --> E
  G --> I["Rows/Panels reset UI"] --> B
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Compute category membership via domainOf(key) instead of substring patterns
  • ➕ Single source of truth for categorization (domainOf)
  • ➕ Avoids accidental matches from broad substrings
  • ➖ Requires calling domainOf for every override key (still cheap, but more indirect)
  • ➖ May behave differently for non-token domains where patterns are intentionally absent
2. Centralize reset-visibility Tailwind classes into a shared helper/component
  • ➕ Prevents repeating the long opacity/focus class string across many components
  • ➕ Makes future styling tweaks one-line changes
  • ➖ Adds abstraction for a small styling concern
  • ➖ May be overkill unless more rows/panels adopt the same pattern soon

Recommendation: Current approach is solid: App is the correct owner for domain-scoped resets since it owns overrides and bulk patching. The substring-pattern method aligns with existing DOMAIN_PATTERNS and keeps behavior consistent with token scoping. Consider centralizing the repeated opacity/focus class string only if this pattern continues to spread.

Files changed (8) +39 / -28

Enhancement (1) +29 / -3
App.svelteAdd per-category Reset N button and domain-scoped reset handler +29/-3

Add per-category Reset N button and domain-scoped reset handler

• Derives active-domain patterns and counts matching overrides. Adds a panel-header button to clear only the active category’s overrides by generating a null patch and applying it via bulk change.

configurator/src/App.svelte

Bug fix (6) +10 / -10
PowerKnobRow.svelteMake knob reset control visible on touch and keyboard focus +1/-1

Make knob reset control visible on touch and keyboard focus

• Updates reset button classes to be visible by default on small screens and to appear on hover/focus within larger breakpoints, improving accessibility.

configurator/src/components/inputs/PowerKnobRow.svelte

SliderRow.svelteFix slider row raw/reset controls visibility for non-hover interactions +2/-2

Fix slider row raw/reset controls visibility for non-hover interactions

• Adjusts the “raw” toggle and reset button to use mobile-visible opacity and focus/hover fallbacks so controls are discoverable on touch devices and via keyboard.

configurator/src/components/inputs/SliderRow.svelte

TokenRow.svelteFix token row reset icon visibility on touch/keyboard +1/-1

Fix token row reset icon visibility on touch/keyboard

• Replaces hover-only opacity behavior with mobile-visible and focus-visible rules, ensuring the per-token reset affordance is accessible.

configurator/src/components/inputs/TokenRow.svelte

MiscPanel.svelteFix inline reset button visibility for underline thickness control +1/-1

Fix inline reset button visibility for underline thickness control

• Updates the inline reset button styling to be visible on small screens and on focus/keyboard interactions, matching the accessible pattern used elsewhere.

configurator/src/components/panels/MiscPanel.svelte

MotionPanel.svelteFix stagger reset button visibility across interaction modes +1/-1

Fix stagger reset button visibility across interaction modes

• Adjusts the motion stagger reset button to not rely solely on hover, adding mobile-visible opacity and focus fallbacks.

configurator/src/components/panels/MotionPanel.svelte

TypographyPanel.svelteFix multiple typography reset buttons visibility on touch/keyboard +4/-4

Fix multiple typography reset buttons visibility on touch/keyboard

• Updates several inline reset buttons throughout typography controls to be visible on mobile and via focus/focus-within, avoiding hover-only affordances.

configurator/src/components/panels/TypographyPanel.svelte

Refactor (1) +0 / -15
DomainPanel.svelteRemove unused per-domain reset/count logic from DomainPanel +0/-15

Remove unused per-domain reset/count logic from DomainPanel

• Deletes derived override-count and reset handler that were previously unused. DomainPanel now only tracks token-tab override count and delegates state mutations upward.

configurator/src/components/DomainPanel.svelte

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 15 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 32b21c59-1f70-424d-8264-8742db8ad5ee

📥 Commits

Reviewing files that changed from the base of the PR and between ccdcbe0 and 081e9d8.

📒 Files selected for processing (1)
  • configurator/src/App.svelte
📝 Walkthrough

Walkthrough

Domain-scoped override reset logic now lives in App.svelte, and DomainPanel.svelte uses domain classification for its badge count. Several reset and close buttons also changed to responsive opacity and focus/hover visibility classes.

Changes

Domain Reset Relocation

Layer / File(s) Summary
Domain reset state and handler
configurator/src/App.svelte
Adds the reset icon import, derives the active domain override count, builds a domain-only bulk-delete patch, and renders the conditional reset button in the domain panel header.
DomainPanel badge count and reset cleanup
configurator/src/components/DomainPanel.svelte
Adds domain classification to the token-tab badge count and removes the old domain reset count and bulk reset helper.

Reset Button Visibility Styling

Layer / File(s) Summary
Input row button visibility
configurator/src/components/inputs/PowerKnobRow.svelte, configurator/src/components/inputs/SliderRow.svelte, configurator/src/components/inputs/TokenRow.svelte
Updates the reset and close button class lists in the input rows to use responsive opacity and focus-within reveal behavior.
Panel reset button visibility
configurator/src/components/panels/MiscPanel.svelte, configurator/src/components/panels/MotionPanel.svelte, configurator/src/components/panels/TypographyPanel.svelte
Updates reset button opacity and hover/focus visibility classes in the misc, motion, and typography panels, including the typography weight and letter-spacing controls.

Estimated code review effort: 2 (Simple) | ~12 minutes

Possibly related PRs

Suggested labels: codex

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main changes: a scoped reset button and visibility fixes for reset icons.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/configurator-reset-ui-fixes-wt1jqs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the codex label Jul 1, 2026
@qodo-code-review

qodo-code-review Bot commented Jul 1, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 6 rules

Grey Divider


Action required

1. Wrong category reset scope ✓ Resolved 🐞 Bug ≡ Correctness
Description
handleResetDomain() (and the header count) selects overrides via substring matches against
DOMAIN_PATTERNS, which can match tokens that domainOf() classifies into a different domain
(e.g., Layout’s "-bg-" also matches --sf-color-bg--active). This can make the Layout header show
a non-zero “Reset N” and delete color overrides when the user resets Layout.
Code

configurator/src/App.svelte[R154-159]

+  function handleResetDomain() {
+    const patch: Record<string, null> = {};
+    for (const k of Object.keys(overrides)) {
+      if (domainPatterns.some((p) => k.includes(p))) patch[k] = null;
+    }
+    handleBulkChange(patch);
Relevance

⭐⭐⭐ High

Team accepted domain-pattern ambiguity/routing fixes; avoids cross-domain matches (see accepted
domain-patterns.json fix in PR #438).

PR-#438

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The reset/count predicate uses substring matching over DOMAIN_PATTERNS, and the layout patterns
include "-bg-" which appears in color token names like --sf-color-bg--active. Meanwhile
domainOf() would classify those keys as colors because it checks the colors patterns
(including "color") before layout, so the new reset can delete overrides outside the active
domain.

configurator/src/App.svelte[61-67]
configurator/src/App.svelte[154-160]
configurator/src/lib/domains.ts[6-13]
configurator/src/data/domain-patterns.json[9-13]
configurator/src/data/api-index.generated.json[2782-2836]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new per-category reset/count logic in `App.svelte` uses `domainPatterns.some(p => k.includes(p))` to decide which override keys belong to the active domain. Because `DOMAIN_PATTERNS` substrings overlap (e.g. `"-bg-"`), this can include keys that the app otherwise categorizes into a different domain via `domainOf()`, causing cross-category deletion.

## Issue Context
`domainOf()` already defines how overrides are grouped (sidebar badges, etc.) and resolves overlaps by order, so the reset/count logic should use the same classification to avoid scope mismatches.

## Fix Focus Areas
- configurator/src/App.svelte[61-67]
- configurator/src/App.svelte[154-160]

### Suggested fix
- Compute `domainOverridesCount` using `domainOf(k) === domain`.
- Build the reset patch using the same predicate (`domainOf(k) === domain`).
- Optionally keep `domainPatterns` only for UI filtering where overlap doesn’t mutate state, or remove it entirely if no longer needed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread configurator/src/App.svelte
…n overlap

domainPatterns.some(p => k.includes(p)) matched against the active
domain's own pattern list in isolation, but DOMAIN_PATTERNS substrings
overlap across domains (e.g. layout's "-bg-" also appears in color
tokens like --sf-color-bg--active). Resetting Layout could therefore
wipe out unrelated Colors overrides. Use domainOf(k) === domain
instead, the same classifier already used for the sidebar override
badges, so the reset button only ever touches keys that actually
belong to the active category.

(caught by automated review on #468)
jackgranatowski pushed a commit to codeslash-dev/SLASHED-Plugins that referenced this pull request Jul 1, 2026
Pulls in codeslash-dev/SLASHED#468 (205f9ab): the per-category reset
button merged in #127 scoped its overrides by raw substring matching
against the active domain's own pattern list, which over-matches since
DOMAIN_PATTERNS substrings overlap across domains (e.g. layout's
"-bg-" also appears in color tokens like --sf-color-bg--active).
Resetting Layout could silently wipe out unrelated Colors overrides.
Now scoped via domainOf(k) === domain, the same classifier already
used for the sidebar override badges. Rebuilt assets/admin-app/app.js
to match.
domainOverridesInTokenTab still filtered by raw DOMAIN_PATTERNS
substring matching after 205f9ab switched the "Reset N" count to
domainOf(k) === domain, so the two could disagree for overlapping
tokens (e.g. --sf-color-bg--active matches layout's "-bg-" pattern but
domainOf() resolves it to colors). Use the same domainOf() predicate
here so both counts always agree.

(caught by automated review on codeslash-dev/SLASHED-Plugins#128)
jackgranatowski pushed a commit to codeslash-dev/SLASHED-Plugins that referenced this pull request Jul 1, 2026
Pulls in codeslash-dev/SLASHED#468 (ccdcbe0): DomainPanel.svelte's
domainOverridesInTokenTab badge still filtered by raw DOMAIN_PATTERNS
substring matching after the "Reset N" count switched to
domainOf(k) === domain, so the two counts could disagree for
overlapping tokens (e.g. --sf-color-bg--active). Now both use the same
domainOf() predicate. Rebuilt assets/admin-app/app.js to match.

(caught by automated review on #128)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
configurator/src/App.svelte (1)

61-68: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: dedupe the domain-key filter.

domainOverridesCount and handleResetDomain both recompute Object.keys(overrides).filter(k => domainOf(k) === domain) independently. Extracting a single derived array of domain-scoped keys would avoid the duplicated predicate and keep both consumers guaranteed in sync as the logic evolves.

♻️ Suggested consolidation
-  let domainOverridesCount = $derived(
-    Object.keys(overrides).filter((k) => domainOf(k) === domain).length
-  );
+  let domainOverrideKeys = $derived(
+    Object.keys(overrides).filter((k) => domainOf(k) === domain)
+  );
+  let domainOverridesCount = $derived(domainOverrideKeys.length);
   function handleResetDomain() {
     const patch: Record<string, null> = {};
-    for (const k of Object.keys(overrides)) {
-      if (domainOf(k) === domain) patch[k] = null;
-    }
+    for (const k of domainOverrideKeys) patch[k] = null;
     handleBulkChange(patch);
   }

Also applies to: 155-162

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@configurator/src/App.svelte` around lines 61 - 68, The domain-scoped override
filtering is duplicated between domainOverridesCount and handleResetDomain, so
extract the shared Object.keys(overrides).filter(...) logic into one derived
list or helper and reuse it in both places. Update App.svelte so the
active-domain key selection is defined once and both the count and reset
behavior consume the same source of truth, keeping domainOf() and domain in
sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@configurator/src/App.svelte`:
- Around line 61-68: The domain-scoped override filtering is duplicated between
domainOverridesCount and handleResetDomain, so extract the shared
Object.keys(overrides).filter(...) logic into one derived list or helper and
reuse it in both places. Update App.svelte so the active-domain key selection is
defined once and both the count and reset behavior consume the same source of
truth, keeping domainOf() and domain in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a6942551-5de0-42d9-a16b-41ba8e246ffd

📥 Commits

Reviewing files that changed from the base of the PR and between 6311b5a and ccdcbe0.

📒 Files selected for processing (2)
  • configurator/src/App.svelte
  • configurator/src/components/DomainPanel.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
  • configurator/src/components/DomainPanel.svelte

domainOverridesCount and handleResetDomain each recomputed
Object.keys(overrides).filter(k => domainOf(k) === domain)
independently. Extract the shared domainOverrideKeys derived so both
consumers stay guaranteed in sync as the logic evolves.

(nitpick from automated review on #468)
jackgranatowski pushed a commit to codeslash-dev/SLASHED-Plugins that referenced this pull request Jul 1, 2026
…ework

Pulls in codeslash-dev/SLASHED#468 (081e9d8): domainOverridesCount and
handleResetDomain each recomputed the same domainOf() filter
independently; extracted the shared domainOverrideKeys derived so both
stay in sync. Rebuilt assets/admin-app/app.js to match.

(nitpick from automated review on #128)

Copy link
Copy Markdown
Contributor Author

Applied CodeRabbit's dedup suggestion in 081e9d8: extracted a shared domainOverrideKeys derived so domainOverridesCount and handleResetDomain() both consume the same filtered list instead of recomputing domainOf(k) === domain independently.


Generated by Claude Code

@jackgranatowski
jackgranatowski merged commit e81c36e into main Jul 1, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants