React Overlay Components

The React Overlay components provide a flexible and accessible way to create overlay components like modal dialogs and pop-up overlays for forms, messages, and actions without managing the underlying state and accessibility concerns. Built on top of the React Aria library, these components manage states, focus, keyboard interactions, and accessibility features to ensure a seamless user experience.

OverlayWrapper is a stateful component for any kind of overlay, that manages the open/close state of the overlay and provides a context for its children. Backdrop is primarily meant for showing backdrop behind the overlay component, can also manage states optionally.

Installation

Install the component using the Tailgrids CLI.

npx @tailgrids/cli add overlay

Anatomy

Compose OverlayWrapper and Backdrop with any type of overlay components.

import { OverlayWrapper } from "@/components/tailgrids/core/overlay";
import { Backdrop } from "@/components/tailgrids/core/overlay";
import {
  Dialog,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogBody,
  DialogFooter,
  DialogClose
} from "@/components/tailgrids/core/dialog";

export default function DialogAnatomy() {
  return (
    <OverlayWrapper>
      <Button />

      <Backdrop>// An overlay component like Dialog, Popover, etc.</Backdrop>
    </OverlayWrapper>
  );
}

Examples

Overlay Wrapper

Create an uncontrolled overlay component by wrapping it with OverlayWrapper. The wrapper will manage the open/close state and provide the necessary context for the overlay component to function properly.

Backdrop

Use Backdrop to create a backdrop behind the overlay component.

Controlled Overlay with Backdrop

When creating a controlled overlay with a backdrop, pass the isOpen and onOpenChange props to Backdrop component instead of the overlay component itself.

API Reference

OverlayWrapper

The root component that manages the open/close state and provides context for overlay components.

PropTypeDefaultDescription
childrenReact.ReactNode-Content of the overlay, typically a trigger element
isOpenboolean-Controlled open state
defaultOpenboolean-Uncontrolled default open state
onOpenChange(isOpen: boolean) => void-Called when the open state changes
classNamestring-Additional CSS classes for the wrapper
styleReact.CSSProperties-Inline styles for the wrapper
idstring-The element's unique identifier
aria-labelstring-Defines a string value that labels the current element
aria-labelledbystring-Identifies the element (or elements) that labels the current element
aria-describedbystring-Identifies the element (or elements) that describes the object
aria-detailsstring-Identifies the element (or elements) that provide a detailed description
role'dialog' | 'alertdialog' | 'alert' | 'alertdialog'-The accessibility role for the dialog
slotstring-A slot name for the component

Backdrop

Wraps ModalOverlay from RAC to provide a backdrop overlay behind overlay components.

PropTypeDefaultDescription
childrenReact.ReactNode | (opts: { close: () => void }) => React.ReactNode-Content of the backdrop, typically an overlay component
isDismissablebooleantrueWhether to close the backdrop when the user interacts outside it
isEnteringboolean-Whether the backdrop is currently performing an entry animation
isExitingboolean-Whether the backdrop is currently performing an exit animation
isKeyboardDismissDisabledbooleanfalseWhether pressing the Escape key to close the backdrop should be disabled
shouldCloseOnInteractOutside(element: HTMLElement) => boolean-Function to filter out interaction with elements that should not dismiss the backdrop
classNamestring-Additional CSS classes for the backdrop
styleReact.CSSProperties-Inline styles for the backdrop
idstring-The element's unique identifier
aria-labelstring-Defines a string value that labels the current element
aria-labelledbystring-Identifies the element (or elements) that labels the current element
aria-describedbystring-Identifies the element (or elements) that describes the object
aria-detailsstring-Identifies the element (or elements) that provide a detailed description

Composition

The Overlay components are composed of the root OverlayWrapper and Backdrop components. They are paired with overlay components like Dialog or Popover for complete overlay behavior.

OverlayWrapper                         — Root container that wraps the trigger and overlay content.
├── Button (trigger)                   — Any pressable element.
└── Backdrop                           — Provides the backdrop overlay.
    └── Dialog / Popover               — The overlay panel (Dialog, Popover, etc.) with content.
  • Use OverlayWrapper as the root. It wraps the trigger element and the overlay content and manages the open/close state.
  • Use any pressable component (e.g. Button) as the trigger. Make sure it is the child of OverlayWrapper.
  • Use Backdrop to render a backdrop overlay. It accepts isDismissable, isKeyboardDismissDisabled, and shouldCloseOnInteractOutside props. Omit it entirely to render the overlay without a backdrop.
  • Use Dialog, Popover, or any overlay component as the child of Backdrop to display the actual overlay content.

Accessibility

  • Focus management: The overlay keeps focus while open and returns focus to the trigger when it closes.
  • Keyboard support: Users can press the Escape key to close the overlay. You can turn off this behavior by setting isKeyboardDismissDisabled on Backdrop.
  • Trigger behavior: Users can open and close the overlay using a trigger or a close button with a mouse or keyboard.
  • Outside click: Users can close the overlay by clicking outside when isDismissable is enabled on Backdrop.
  • Overlay role: The overlay component (e.g., Dialog) renders with role="dialog" by default. Use role="alertdialog" for alert dialogs via the role prop on the overlay component.
  • ARIA labeling: Use aria-label or aria-labelledby on the overlay component to describe the overlay content clearly.