VisorVisor
ComponentsOverlay

Fullscreen Overlay

A full-viewport overlay for expanding content to fill the screen. Built on Radix Dialog with keyboard dismiss, focus trap, and body scroll lock.

Basic Example

Fullbleed Mode

The fullbleed prop removes all inner padding, letting content fill the entire viewport edge-to-edge. Ideal for full-screen images, maps, or video players.

Controlled State

Use open and onOpenChange to control the overlay programmatically.

import { useState } from 'react';
import {
  FullscreenOverlay,
  FullscreenOverlayTrigger,
  FullscreenOverlayContent,
} from '@/components/ui/fullscreen-overlay/fullscreen-overlay';
import { Button } from '@/components/ui/button/button';

export default function ControlledExample() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>Open Overlay</Button>
      <FullscreenOverlay open={open} onOpenChange={setOpen}>
        <FullscreenOverlayContent>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
            <Button onClick={() => setOpen(false)}>Close</Button>
          </div>
        </FullscreenOverlayContent>
      </FullscreenOverlay>
    </>
  );
}

Features

  • Full viewport: Content fills the entire screen
  • Keyboard dismiss: Escape key closes the overlay
  • Focus trap: Built on Radix Dialog for automatic focus management
  • Body scroll lock: Prevents background scrolling while open
  • Fullbleed mode: Remove padding for edge-to-edge content
  • Theme-agnostic: Uses CSS custom properties for all visual tokens

Installation

npx visor add fullscreen-overlay

This copies two files into your project:

  • components/ui/fullscreen-overlay/fullscreen-overlay.tsx — the component
  • components/ui/fullscreen-overlay/fullscreen-overlay.module.css — the styles

Usage

import {
  FullscreenOverlay,
  FullscreenOverlayTrigger,
  FullscreenOverlayContent,
} from '@/components/ui/fullscreen-overlay/fullscreen-overlay';

export default function Example() {
  return (
    <FullscreenOverlay>
      <FullscreenOverlayTrigger asChild>
        <Button>Expand</Button>
      </FullscreenOverlayTrigger>
      <FullscreenOverlayContent>
        <p>Your content fills the full viewport here.</p>
      </FullscreenOverlayContent>
    </FullscreenOverlay>
  );
}

API Reference

FullscreenOverlayProps

PropTypeDefaultDescription
openbooleanControlled open state of the overlay.
onOpenChange(open: boolean) => voidCallback when the open state changes.
fullbleedbooleanfalseRemoves all inner padding on FullscreenOverlayContent, allowing content to fill the entire viewport edge-to-edge.
childrenReact.ReactNodeContent to render inside FullscreenOverlayContent.
classNamestringAdditional CSS class names to merge onto FullscreenOverlayContent.
asChildbooleanfalseOn FullscreenOverlayTrigger — merges props onto the immediate child element instead of rendering a <button>.

Sub-components

ComponentElementPurpose
FullscreenOverlayRootContext provider wrapping Radix Dialog.Root
FullscreenOverlayTrigger<button>Opens the overlay; use asChild to wrap a custom trigger
FullscreenOverlayContentDialogFull-viewport container. Renders close button, title, and description automatically

Accessibility

  • Built on Radix UI Dialogrole="dialog", aria-modal="true", and visually hidden title/description are provided automatically.
  • Focus is trapped inside the overlay when open and restored to the trigger element on close.
  • Pressing Escape closes the overlay.
  • The close (×) button has a visually hidden "Close" label for screen readers.
  • Use aria-labelledby or aria-describedby on FullscreenOverlayContent if you render a visible heading inside.