Skip to content

Add confirmation dialog for reset all action - #446

Merged
jackgranatowski merged 3 commits into
mainfrom
claude/frontend-panel-reset-confirm-qxjoai
Jun 29, 2026
Merged

Add confirmation dialog for reset all action#446
jackgranatowski merged 3 commits into
mainfrom
claude/frontend-panel-reset-confirm-qxjoai

Conversation

@jackgranatowski

Copy link
Copy Markdown
Contributor

Summary

Adds a confirmation dialog when resetting all overrides, and reorders the header buttons to place the Save button before the undo/redo controls for better UX.

Changes

  • StudioHeader.svelte

    • Added showResetConfirm state to manage confirmation dialog visibility
    • Introduced handleResetAllClick(), confirmReset(), and cancelReset() functions to handle the reset flow with confirmation
    • Added a modal confirmation dialog that displays the number of customizations being cleared
    • Moved the Save button before the undo/redo buttons in the header layout
    • Removed the visual separator that was between reset and save buttons
  • App.svelte

    • Replaced JSON.stringify() comparisons with a new shallowEq() helper function for more efficient equality checks on flat string records
    • Updated lastSavedSnapshot to store an object copy instead of a JSON string
    • Applied shallowEq() throughout the save state logic for better performance on every state change

Implementation Details

The confirmation dialog includes:

  • Clear messaging about what will be reset (with proper pluralization)
  • Reminder that the action can still be undone before saving
  • Cancel and Reset buttons with appropriate styling
  • Accessible dialog markup with role="dialog" and aria-modal

The shallowEq() helper provides a cheaper alternative to JSON.stringify() for comparing flat string records, improving performance on every reactive update without changing the save behavior.

https://claude.ai/code/session_01YQF3CbAAzbd6jjj1nWhe3Z

claude added 2 commits June 29, 2026 07:52
…on left

- Reset All (trash icon) now shows a confirmation dialog before clearing
  overrides, reducing accidental data loss
- Save button moved to the left of undo/redo icons for quicker access
…ider responsiveness

JSON.stringify(overrides) was called on every input change — twice in setOverrides
and once per tick via the hasPendingChanges derived — serialising potentially hundreds
of token values at 60fps. Replaced with a cheap shallow key-value comparison.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 53 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: cf0d1a2a-b64e-4d3f-8cf4-e21736b0388c

📥 Commits

Reviewing files that changed from the base of the PR and between 500a3a5 and 6f72c95.

📒 Files selected for processing (2)
  • configurator/src/App.svelte
  • configurator/src/components/shell/StudioHeader.svelte
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/frontend-panel-reset-confirm-qxjoai

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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add reset-all confirmation modal and optimize override dirty-checks
✨ Enhancement 🕐 40+ Minutes

Grey Divider

Description

• Add a confirmation modal before clearing all overrides to prevent accidental resets.
• Reorder header controls to place Save before undo/redo for faster access.
• Replace JSON.stringify-based equality checks with a shallow record compare for responsiveness.
Diagram

graph TD
  U([User]) --> H["StudioHeader.svelte"] --> M["Reset confirm modal"] --> H
  H --> A["App.svelte (overrides state)"] --> P["saveOverrides()"]
  A --> H
  subgraph Legend
    direction LR
    _user(["User"]) ~~~ _ui["UI component"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Track dirty state incrementally (mutation counter)
  • ➕ O(1) dirty checks; avoids scanning keys on each derived recompute
  • ➕ More robust if overrides grow large
  • ➖ More bookkeeping and higher risk of missing an update path
  • ➖ Harder to reason about with undo/redo snapshots
2. Use a stable hash (e.g., sorted key hash) instead of shallowEq
  • ➕ Retains cheap comparisons while reducing reliance on shared key sets
  • ➕ Can be extended if values stop being flat strings
  • ➖ More code and potential hashing overhead
  • ➖ Still requires careful handling of key ordering and collisions

Recommendation: The current approach is a good tradeoff: shallowEq removes repeated JSON serialization hot-path costs while keeping the save semantics straightforward. The main constraint is that overrides remain a flat string record; if that changes, consider migrating to an incremental dirty flag or a stable hash approach.

Files changed (2) +84 / -34

Enhancement (1) +71 / -28
StudioHeader.svelteGate reset-all behind a confirmation modal and reorder header actions +71/-28

Gate reset-all behind a confirmation modal and reorder header actions

• Adds showResetConfirm state and handlers to open/cancel/confirm a reset-all confirmation dialog. Reorders header buttons to place Save before undo/redo and removes the prior visual separator near reset/save controls.

configurator/src/components/shell/StudioHeader.svelte

Refactor (1) +13 / -6
App.svelteReplace JSON.stringify dirty checks with shallow record equality +13/-6

Replace JSON.stringify dirty checks with shallow record equality

• Introduces a shallowEq helper for flat string records and replaces JSON.stringify-based comparisons for dirty state and undo/redo change detection. Updates the saved snapshot to store a copied object and uses shallowEq to confirm the app is still clean after an async save completes.

configurator/src/App.svelte

@qodo-code-review

qodo-code-review Bot commented Jun 29, 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


Remediation recommended

1. Non-modal confirm dialog ✓ Resolved 🐞 Bug ≡ Correctness
Description
The reset confirmation overlay doesn't move focus into the dialog or handle Escape/backdrop
dismissal, so keyboard focus can remain on (and tab through) the underlying page instead of the
dialog. This breaks the expected modal interaction pattern and can make the confirmation hard to use
for keyboard/assistive-technology users.
Code

configurator/src/components/shell/StudioHeader.svelte[R152-181]

+{#if showResetConfirm}
+  <div
+    class="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
+    role="dialog"
+    aria-modal="true"
+    aria-labelledby="reset-confirm-title"
+  >
+    <div class="bg-[#1a1a2e] border border-white/10 rounded-xl p-6 max-w-sm w-full mx-4 shadow-2xl">
+      <h3 id="reset-confirm-title" class="text-white font-bold text-sm mb-2">Reset all overrides?</h3>
+      <p class="text-slate-400 text-xs mb-5">
+        This will clear all {overridesCount} customisation{overridesCount !== 1 ? 's' : ''}.
+        You can still undo this before saving.
+      </p>
+      <div class="flex gap-2 justify-end">
+        <button
+          onclick={cancelReset}
+          class="px-3 py-1.5 text-xs rounded-lg bg-white/8 text-slate-300 hover:bg-white/12 transition-colors cursor-pointer"
+        >
+          Cancel
+        </button>
+        <button
+          onclick={confirmReset}
+          class="px-3 py-1.5 text-xs rounded-lg bg-rose-600 hover:bg-rose-500 text-white font-bold transition-colors cursor-pointer"
+        >
+          Reset all
+        </button>
+      </div>
+    </div>
+  </div>
+{/if}
Relevance

⭐⭐⭐ High

Team previously accepted overlay focus + Escape-dismiss a11y fixes (PR #313) and Escape-to-close
modal behavior (PR #423).

PR-#313
PR-#423

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
StudioHeader’s dialog overlay is added with ARIA modal attributes but no focus initialization, focus
trap, Escape handler, or backdrop click handler. CommandPalette demonstrates the expected modal
behavior in this repo by focusing its input and closing on Escape/backdrop click.

configurator/src/components/shell/StudioHeader.svelte[33-44]
configurator/src/components/shell/StudioHeader.svelte[152-181]
configurator/src/components/CommandPalette.svelte[44-55]
configurator/src/components/CommandPalette.svelte[69-76]

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 reset confirmation UI is rendered as a modal (`role="dialog"`, `aria-modal="true"`) but currently has no focus management or keyboard dismissal behavior.

### Issue Context
Without moving focus into the dialog (and ideally trapping it), keyboard users can keep interacting with background controls. The codebase already has an example modal (CommandPalette) that focuses an input, closes on Escape, and supports backdrop-click dismissal.

### Fix Focus Areas
- configurator/src/components/shell/StudioHeader.svelte[33-44]
- configurator/src/components/shell/StudioHeader.svelte[152-181]

### Suggested implementation notes
- When `showResetConfirm` becomes true, programmatically focus a control inside the dialog (typically the Cancel button for safety).
- Add `on:keydown` handling to close on `Escape`.
- Consider adding backdrop-click-to-close (consistent with `CommandPalette`) and restoring focus to the triggering Reset button on close.
- If you want true modality, implement a simple focus trap (cycle Tab/Shift+Tab within the dialog).

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


Grey Divider

Qodo Logo

Auto-focus Cancel button on open, trap Tab between Cancel/Reset-all,
Escape dismisses, backdrop click dismisses — consistent with CommandPalette
@jackgranatowski
jackgranatowski merged commit 2a3ff37 into main Jun 29, 2026
13 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