Skip to content

Keep a dialog open when a file picker inside it is cancelled - #43297

Draft
samyferhat wants to merge 2 commits into
twbs:mainfrom
samyferhat:fix/dialog-file-input-cancel
Draft

samyferhat wants to merge 2 commits into
twbs:mainfrom
samyferhat:fix/dialog-file-input-cancel

Conversation

@samyferhat

Copy link
Copy Markdown

Description

  • In DialogBase, ignore a cancel event when its target is not the dialog element.
  • Add three unit tests: a dialog, a dialog with keyboard: false, and a drawer. Each test fires a bubbling cancel event from a file input.

Motivation & Context

  • A file input fires a bubbling cancel event when the user dismisses the picker. The handler treated this event as the dialog's own, so the dialog closed. With keyboard: false, it played the static backdrop animation.
  • The dialog's own cancel event does not bubble, so Escape still works.
  • Dialog and Drawer both use this handler, so the fix applies to both.
  • Checked the compiled bundle in headless Chromium. Clicking the input cancels the picker natively there, because headless mode has no file dialog:
    • Before: the input fires cancel with bubbles: true, and the dialog closes.
    • After: the input fires the same event, and the dialog stays open. Escape then closes it.
  • Not checked with a native picker in a headed browser.
  • The three new tests fail without the change. npm run lint, npm run js-test-unit, and npm run js pass locally.
  • dialog.spec.js already exceeded the ESLint max-lines limit (1502 of 1500). That warning stays.

Type of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Refactoring (non-breaking change)
  • Breaking change (fix or feature that would change existing functionality)

Checklist

  • I have read the contributing guidelines
  • My code follows the code style of the project (using npm run lint)
  • My change introduces changes to the documentation
  • I have updated the documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed

Live previews

  • Not applicable. The docs have no example with a file input in a dialog.

Related issues

Fixes #43278

🤖 Generated with Claude Code

A file input fires a bubbling `cancel` event when the user dismisses the
picker. The dialog handler treated that event as its own, so the dialog
closed. Ignore a `cancel` event from a descendant. The dialog's own
`cancel` event does not bubble, so Escape still works.

Fixes twbs#43278

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@julien-deramond julien-deramond added v6 v6, the main branch bug Something does not work as documented js JavaScript or TypeScript sources and plugins tests Unit, visual or CSS tests labels Nov 4, 2026
@zegganewalid

Copy link
Copy Markdown

The fix is small and the code comment explains well why the target check is safe. Two suggestions for the tests:

  1. Before this change, the handler also called preventDefault() on the file input's cancel. Asserting expect(event.defaultPrevented).toBeFalse() on the event dispatched from the input would lock in that the dialog no longer touches events it doesn't own.

  2. The description says Escape still closes the dialog after the picker is cancelled, but no test covers that sequence. A test that fires the bubbling cancel from the input, then a non-bubbling cancel on the dialog itself, and expects hide() to be called once, would guard the main path against a future change to the target check.

Check that the dialog does not call preventDefault() on a cancel event
from a file input. Also check that Escape still closes the dialog once
after the file picker is cancelled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@netlify

netlify Bot commented Nov 7, 2026

Copy link
Copy Markdown

✅ Deploy Preview for twbs-bootstrap ready!

Name Link
🔨 Latest commit d8784e8
🔍 Latest deploy log https://app.netlify.com/projects/twbs-bootstrap/deploys/6aef5b8be4917605ff176cb7
😎 Deploy Preview https://deploy-preview-43297--twbs-bootstrap.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@samyferhat

Copy link
Copy Markdown
Author

Thanks, both are in d8784e8.

  1. The input's cancel is now dispatched as cancelable, and the test checks that defaultPrevented stays false. Without cancelable: true the check would always pass, even on main.
  2. New test: a bubbling cancel from the input, then the dialog's own cancel. hide() is called once.

Both new tests fail when I revert the fix in dialog-base.ts.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something does not work as documented js JavaScript or TypeScript sources and plugins tests Unit, visual or CSS tests v6 v6, the main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dialog closes when a file input inside it has its picker cancelled

3 participants