Skip to content

About

Reliable DOM element interactivity checks; including is-occluded check.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

77 Commits

Folders and files

Repository files navigation

Is Interactive?

Versatile DOM element interactivity checks.

npm install webfuse-com/is-interactive

Example

import { checkInteractivity, filterInteractive } from "@webfuse-com/is-interactive";

// Check if an element is interactive:
const click = targetElement => {
  const { isInteractive } = checkInteractivity(targetElement, {
    invisible: false  // disables invisible check
  });

  if(!isInteractive) return;

  automation.click(button);
};

// Create a DOM snapshot (weakly corresponding to the GUI):
const surfaceDOMSnapshot = selector => {
  return filterInteractive(document, {
    offViewport: true
  }).outerHTML;
};

API

// Toggle checks to perform (default: all enabled, except 'offViewport')
interface InteractivityChecks {
  clipped: boolean;       // true
  collapsed: boolean;     // true
  disabled: boolean;      // true
  disconnected: boolean;  // true
  hidden: boolean;        // true
  inert: boolean;         // true
  invisible: boolean;     // true
  modalBlocked: boolean;  // true
  occluded: boolean;      // true
  unclickable: boolean;   // true
  unrendered: boolean;    // true
  ariaHidden: boolean;    // false
  offScrolled: boolean;   // false
  offViewport: boolean;   // false
}

// Additional options (default: all disabled)
interface InteractivityOptions {
  // Skip checks inherited from parents ('hidden', 'inert', 'ariaHidden', 'unrendered'),
  // e.g., when parents are known to be checked already
  skipParentChecks: boolean;  // false
}

/**
 * Check whether an element is interactive.
 */
function checkInteractivity(
  element: Element,
  checks?: InteractivityChecks,
  options?: InteractivityOptions
): {
  isInteractive: boolean;
  reason?:
    | "notElement"
    | "clipped"
    | "collapsed"
    | "disabled"
    | "disconnected"
    | "hidden"
    | "inert"
    | "invisible"
    | "modalBlocked"
    | "occluded"
    | "unclickable"
    | "unrendered"
    | "ariaHidden"
    | "offScrolled"
    | "offViewport"
}

/**
 * Filter a DOM (sub)tree for interactive elements.
 * Create a 'surface'-only DOM.
 */
function filterInteractive(
  dom: Document | Element,
  checks?: InteractivityChecks,
  elementOverrideChecks:
      { [ key: string ]: Partial<InteractivityChecks> }
    | Map<string, Partial<InteractivityChecks>>
): Element  // virtual DOM

By default, filterInteractive sets elementOverrideChecks to:

{
  "input": {
    clipped: false,
    collapsed: false,
    invisible: false,
    occluded: false,
    unrendered: false,
  },
  "select": {
    clipped: false,
    collapsed: false,
    invisible: false,
    occluded: false,
    unrendered: false,
  }
}

This accounts for custom-style input patterns (e.g., occluded by click-receiver element).

The occluded check temporarily scrolls elements into view (restored synchronously; the resulting scroll events are suppressed). With offViewport or offScrolled enabled, the window or scroll containers, respectively, are not scrolled: elements that pass these checks are partially in view already.

Shadow DOM

Checks follow the rendered (flat) tree: slotted elements are assessed within their slot, and filterInteractive keeps open shadow roots in the virtual DOM. Closed shadow roots cannot be inspected: their contents are not filtered, and content slotted into them is assessed as if placed in the host. Closed <details> are handled explicitly.

Interactive Demo (pun intended)

Open demo/demo.html in a browser.

Meaning of Interactive

Actionable ⊂ Interactive ⊂ All Elements

From within a web application, an element is considered interactive when it is surfaced by the UI. That means a user can perceive it and potentially act on it. Elements that are not surfaced are therefore not interactive, for instance, an input declared as hidden.

Whether an interactive element is truly actionable, however, depends on the presence of an actuation listener. Actuation listeners, including browser-native effect, such as those associated with links or checkboxes.

About

Reliable DOM element interactivity checks; including is-occluded check.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Contributors

Languages