Skip to content

fix: Check for :modal selector support before using it#33

Merged
smockle merged 1 commit intomainfrom
smockle/gate-modal-selector
Jan 14, 2026
Merged

fix: Check for :modal selector support before using it#33
smockle merged 1 commit intomainfrom
smockle/gate-modal-selector

Conversation

@smockle
Copy link
Contributor

@smockle smockle commented Jan 14, 2026

JSDOM doesn’t implement :modal, so if Jest is used to test components in an environment where @github/arianotify-polyfill is loaded, it throws SyntaxError: unknown pseudo-class selector ':modal'.

This PR fixes that issue by only using :modal where it’s supported.

Semi-related: #25

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a feature detection check for the :modal CSS pseudo-class selector to prevent syntax errors in environments like JSDOM (used by Jest) that don't support this selector.

Changes:

  • Added CSS feature detection using CSS.supports("selector(:modal)") before using the :modal selector
  • Fallback to dialog[open] selector when :modal is not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// This can be checked by seeing if the element is within the modal, if the modal is present.
(this.element.ownerDocument
.querySelector(":modal")
.querySelector(CSS.supports("selector(:modal)") ? ":modal" : "dialog[open]")
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The fallback selector dialog[open] is not semantically equivalent to :modal. The :modal selector matches only dialogs opened with showModal() (which make outside content inert), while dialog[open] matches any dialog with the open attribute, including non-modal dialogs opened with show() (which don't make outside content inert). This could cause incorrect behavior where non-modal dialogs are incorrectly treated as making content outside them inert. Consider using dialog[open]:modal as a fallback (which requires the browser to parse it but still functions), or check for the modal state differently (e.g., checking for the presence of a ::backdrop pseudo-element or using JavaScript to track modal state).

See below for a potential fix:

      // Element must be connected to the document.
      if (!this.element.isConnected) {
        return false;
      }

      // Elements within inert containers should not be announced.
      if (this.element.closest("[inert]")) {
        return false;
      }

      // If there is a modal element on the page, everything outside of it is implicitly inert.
      // Only apply this logic when the browser supports the :modal selector.
      const doc = this.element.ownerDocument;
      let modal = null;

      if (typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("selector(:modal)")) {
        modal = doc.querySelector(":modal");
      }

      // If there is a modal, only announce elements within it; otherwise, allow announcement.
      return modal ? modal.contains(this.element) : true;

Copilot uses AI. Check for mistakes.
// This can be checked by seeing if the element is within the modal, if the modal is present.
(this.element.ownerDocument
.querySelector(":modal")
.querySelector(CSS.supports("selector(:modal)") ? ":modal" : "dialog[open]")
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The new feature detection logic and fallback behavior for environments without :modal support lacks test coverage. Consider adding tests that verify correct behavior in environments where CSS.supports('selector(:modal)') returns false, ensuring the fallback selector works appropriately.

Copilot uses AI. Check for mistakes.
@smockle smockle merged commit 996e7d9 into main Jan 14, 2026
10 checks passed
@smockle smockle deleted the smockle/gate-modal-selector branch January 14, 2026 20:17
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.

3 participants