dequelabs / cauldron

https://cauldron.dequelabs.com/
Mozilla Public License 2.0
91 stars 21 forks source link

Create AnchoredOverlay Component #1715

Open scurker opened 1 month ago

scurker commented 1 month ago

An overlay is a a layered element that temporarily covers other content on the page. This component should be anchored to a target element that is positionally displayed along the target element according to a specified anchor position.

Props

interface AnchoredOverlayProps<T extend HTMLElement = HTMLElement> 
  extends PolymorphicComponent<T> {

  /** A target element or element ref to render the as the overlay anchor target. */
  target: ElementOrRef<T>

  /** How to anchor the overlay element relative to the target. */
  position?: { ... }

  /** Determines if the overlay is currently shown */
  open?: boolean

  /** A callback function that is called when the open state of the ActionMenu changes. */
  onOpenChange?: (open: boolean) => void

  /** Settings for focus traps on the AnchoredOverlay component. */
  focusTrapOptions?: { ... }

  /** An optional portal target to render the overlay in. Defaults to `document.body`. */
  portal?: ElementOrRef<HTMLElement>

}

Implementation

The AnchoredOverlay is a primitive component that primarily contains behaviors to position an overlay element relative to its target and does not contain any default styles or classnames and is intended to be used in composition with other components. The style attributes to position the popover should be implement using floating-ui and placement arguments:

import { useFloating } from '@floating-ui/react-dom'

function AnchoredOverlay({
  as = 'div',
  open,
  target,
  position,
  children
}: AnchoredOverlayProps): JSX.Element {
  const overlayRef = useRef<HTMLElement>()
  useFloating({
    placement: position,
    open,
    elements: {
      reference: resolveElement(target),
      floating: overlayRef
    }
  }
  const Component = as

  return (
    <Component ref={overlayRef}>
      {children}
    </Component>
  )
}

[!NOTE] Cauldron is currently using popperjs to manage tooltips. floatingui is the rebranding of popperjs with a new api, part of the work involved here will be making any necessary changes to accommodate tooltip and popover to use the updated library.

Escape behaviors should happen automatically as part of this component. When escape is detected, the onOpenChange callback should be invoked.

The associated target is intended to be an interactive element that can trigger the overlay and should have the following properties set on the component (if not already set):