Skip to content

[Feat]: Abstract Overlay API Review #2086

@Westbrook

Description

@Westbrook

Code of conduct

  • I agree to follow this project's code of conduct.

Impacted component(s)

overlay

Description of the requested feature

openOverlay currently accepts:

{
    target: HTMLElement,
    interaction:
      | 'click'
      | 'longpress'
      | 'hover'
      | 'custom'
      | 'replace'
      | 'inline'
      | 'modal',
    content: HTMLElement,
    options: {
      delayed?: boolean;
      placement?: Placement;
      offset?: number;
      receivesFocus?: 'auto';
      notImmediatelyClosable?: boolean;
      abortPromise?: Promise<boolean>;
      virtualTrigger?: VirtualTrigger;
    }
}

A content element managed for overlay looks like:

interface ManagedOverlayContent {
    open: boolean;
    overlayWillOpenCallback?: (args: { trigger: HTMLElement }) => void;
    overlayOpenCallback?: (args: { trigger: HTMLElement }) => void;
    overlayOpenCancelledCallback?: (args: { trigger: HTMLElement }) => void;
    overlayCloseCallback?: (args: { trigger: HTMLElement }) => void;
}

Important question

If we created a new API could we smooth transition by wrapping it with the old API for the initial term?

Things we might want instead:

content is required but trigger is not

  • points to a usage of the "Active Stack" concept where the "trigger" was the previous "active element" and that content would manage things like theme, focus return, etc.

tabOrder: 'none' | 'inline' | 'replace' | 'trap'

  • 'none' = tooltip and similar that are given aria-* based content relations
  • 'inline' = before trigger <=> trigger <=> overlay <=> after overlay
  • 'replace' = before trigger <=> trigger when closed, overlay when open <=> after overlay
  • 'trap' = modal
    This should absolve the need for receivedFocus as all overlays need focus for the screen reader to step into them when aria-* attributes are not managing the content relations.

interaction:

  • likely the only interaction not managed by tabOrder is longpress which really only manages the first click event.

backdrop management:

  • not all "modals" have a backdrop and we need to manage it somehow
  • it may be that backdrops need to be handled 100% of the time by the overlaid content and not by the overlay system

stack management:

  • overlays need access to the stack to prevent DOM based state resolution
  • adding/removing something from the stack should be synchronous
  • any new non-tabOrder='none' content should dismiss all preceeding tabOrder='none' content on the stack

overlay management:

  • (on or off the stack) should manage their own asyncrony
  • lifecycle should be both explicit and easy to apply

Does abortPromise belong on the overlay lifecycle? Does making the stack syncronous prevent needing to maintain this code path.

Configurable and re-configurable overlays:

  • elements like sp-picker should be able to surface more options around the overlay they throw, see coment and issue
  • overlays thrown in this way should be "updatable", for instance when going between mobile and desktop so that the wrapper (Tray vs Popover) and placement (specific vs 'none') can be swapped

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions