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

Open Beginner friendly
#43,278 1 comment 1 reaction 0 assignees View on GitHub

Maintainers usually reply within 1 day

@samyferhat is already working on this.

Since Nov 4, 2026.

  • #43297 by @samyferhat — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
bootstrap, javascript, typescript
Domain
frontend

Research direction

Start with the cancel handler in js/src/dialog-base.ts, linked in the issue, and check how nearby dialog event handlers distinguish events from descendants. Add coverage using the issue's reproduction steps and verify that cancelling the file picker leaves the dialog open, while the dialog's own cancel behavior still works.

Written by the indexing model from the issue text.

Description

bug confirmed has-pr js v6
Prerequisites
Describe the issue

A dialog closes when the user opens the file picker of an <input type="file"> inside it and then dismisses the picker without choosing a file.

When a file picker is dismissed, browsers fire a cancel event at the input, and the HTML spec has it bubble (spec). It reaches the <dialog>, where DialogBase listens for cancel to handle Escape. That handler does not check event.target, so it treats the bubbled event as the dialog's own cancel and calls hide():

https://github.com/twbs/bootstrap/blob/7e914e3fd0d51f6a71ad6fd0a6b79590190d8136/js/src/dialog-base.ts#L308-L320

The native cancel event of a <dialog> does not bubble, so any cancel that arrives from a descendant is never the dialog's own. The backdrop click handler a few lines further down already guards with event.target !== this._element.

Steps to reproduce with the test case below:

  1. Click "Open dialog".
  2. Click the file input, so the file picker opens.
  3. Press Cancel in the file picker.

Expected: the dialog stays open.

Actual: the dialog closes. With data-bs-keyboard="false" it plays the static-backdrop animation instead, which is just as unexpected.

Suggested fix: ignore cancel events from descendants at the top of the handler:

this._cancelHandler = event => {
  if (event.target !== this._element) {
    return
  }

  event.preventDefault()
  // …
}

The workaround until then is to stop the event on the input:

input.addEventListener('cancel', event => event.stopPropagation())
Reduced test cases

CodePen: https://codepen.io/editor/aloysiu5/pen/01a1a134-60a4-7254-98af-7ffc218ae510

The same as a self-contained page against the alpha.1 CDN build:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Dialog closes when a file picker is cancelled</title>
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="p-6">
  <button type="button" class="btn-solid theme-primary" data-bs-toggle="dialog" data-bs-target="#upload">Open dialog</button>

  <dialog class="dialog" id="upload" aria-labelledby="upload-title">
    <div class="dialog-header">
      <h2 class="dialog-title" id="upload-title">Upload</h2>
      <button type="button" class="btn-close" data-bs-dismiss="dialog" aria-label="Close"></button>
    </div>
    <div class="dialog-body">
      <label for="file" class="form-label">Choose a file, then cancel the picker</label>
      <input type="file" class="form-control" id="file">
    </div>
  </dialog>

  <script type="module">
    import "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
    document.getElementById("file").addEventListener("cancel", (event) => {
      console.log("cancel on", event.target.tagName, "bubbles:", event.bubbles)
    })
  </script>
</body>
</html>

The console line shows the event that closes the dialog: cancel on INPUT bubbles: true.

What operating system(s) are you seeing the problem on?

macOS

What browser(s) are you seeing the problem on?

Chrome

What version of Bootstrap are you using?

v6.0.0-alpha.1 (the handler is unchanged on main at 7e914e3)

Dominant language
MDX
Stars
175k
Forks
78.5k
Avg merge
1d 11h
Merged PRs (30d)
111

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from twbs/bootstrap

All issues in twbs/bootstrap

Similar issues

More Web Dev issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.