Skip to content

Commit 0db1410

Browse files
fix(onboarding): prevent Apply Result dialog from being dismissed (#1971)
## Summary - After pressing "Confirm and Apply" in the onboarding wizard, the Apply Result dialog (showing success/warning/error/timeout) could be dismissed via ESC key, clicking outside the overlay, or clicking the header close (X) button - This allowed users to bypass the result acknowledgment, miss important error/warning diagnostic information, and skip the intended navigation to the Next Steps page - The dialog is now non-dismissible — the **only** way to proceed is by clicking the OK button ## What changed **`OnboardingSummaryStep.vue`** — Apply Result `UModal` (line 1387): - Added `:dismissible="false"` — uses Nuxt UI's built-in mechanism to call `e.preventDefault()` on reka-ui's `pointerDownOutside`, `interactOutside`, and `escapeKeyDown` events - Added `:close="false"` — removes the header close (X) button, which would otherwise bypass the `dismissible` guard via reka-ui's `DialogClose` component - Removed the `@update:open` handler — dead code since no external close events can fire with both props set **`OnboardingSummaryStep.test.ts`**: - Extended UModal stub to accept `dismissible` and `close` props and render them as data attributes - Added test verifying `handleApplyResultConfirm()` (triggered by OK button) is the sole path to close the dialog and advance to Next Steps ## Modal state audit ``` "Confirm and Apply" clicked │ ├─[has internal boot]──→ Boot Drive Warning Dialog (stays dismissible) │ ↓ Continue │ ├──→ handleComplete() runs │ │ │ ★ Apply Result Dialog ← THIS IS FIXED │ Was: dismissible via ESC / click-outside / X button │ Now: only closable via OK button │ ↓ OK → goToNextStep() → NEXT_STEPS │ └──→ InternalBootConfirmDialog (stays dismissible) ``` ## Scope decisions Only the Apply Result Dialog was made non-dismissible. The Boot Drive Warning and InternalBootConfirmDialog retain their current dismissible behavior — these are pre-action confirmations where canceling/escaping is a valid user choice. The Apply Result Dialog is post-action; the settings have already been applied, and the user must acknowledge the outcome. ## Test plan - [x] Existing tests pass (635 passed, 6 skipped) - [ ] Manual: Navigate to Summary → Confirm and Apply → Apply Result appears - [ ] Manual: Press ESC → dialog stays open - [ ] Manual: Click outside overlay → dialog stays open - [ ] Manual: Verify no X button in header - [ ] Manual: Click OK → navigates to Next Steps - [ ] Manual: Verify all result severities (success, warning, error, timeout) are non-dismissible <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Apply result dialog no longer allows users to accidentally dismiss it by clicking outside or using a close button. Users must now explicitly confirm the result to close the dialog and proceed. * **Tests** * Added test coverage for apply result dialog behavior, validating visibility states and confirmation flow mechanics. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 29f814b commit 0db1410

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,9 @@ const mountComponent = (props: Record<string, unknown> = {}) => {
255255
template: '<button :disabled="disabled" @click="$emit(\'click\')"><slot /></button>',
256256
},
257257
UModal: {
258-
props: ['open', 'ui', 'title', 'description'],
258+
props: ['open', 'ui', 'title', 'description', 'dismissible', 'close'],
259259
template: `
260-
<div v-if="open" data-testid="dialog" :class="ui?.content">
260+
<div v-if="open" data-testid="dialog" :class="ui?.content" :data-dismissible="dismissible" :data-close="close" :data-title="title">
261261
<div>{{ title }}</div>
262262
<div>{{ description }}</div>
263263
<slot name="body" />
@@ -584,6 +584,20 @@ describe('OnboardingSummaryStep', () => {
584584
});
585585
});
586586

587+
it('only allows closing the apply result dialog via the OK button', async () => {
588+
const { wrapper, onComplete } = mountComponent();
589+
590+
await clickApply(wrapper);
591+
592+
const vm = getSummaryVm(wrapper);
593+
expect(vm.showApplyResultDialog).toBe(true);
594+
expect(onComplete).not.toHaveBeenCalled();
595+
596+
vm.handleApplyResultConfirm();
597+
expect(vm.showApplyResultDialog).toBe(false);
598+
expect(onComplete).toHaveBeenCalledOnce();
599+
});
600+
587601
it.each([
588602
{
589603
caseName: 'switches to en_US directly without language pack install',

web/src/components/Onboarding/steps/OnboardingSummaryStep.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,8 @@ const handleBack = () => {
13861386

13871387
<UModal
13881388
:open="showApplyResultDialog"
1389+
:dismissible="false"
1390+
:close="false"
13891391
:portal="false"
13901392
:title="applyResultTitle"
13911393
:description="applyResultMessage"
@@ -1396,7 +1398,6 @@ const handleBack = () => {
13961398
? 'z-50 w-[calc(100vw-2rem)] max-w-3xl'
13971399
: 'z-50 max-w-md',
13981400
}"
1399-
@update:open="showApplyResultDialog = $event"
14001401
>
14011402
<template v-if="showDiagnosticLogsInResultDialog" #body>
14021403
<div class="space-y-3">

0 commit comments

Comments
 (0)