Document overlay

A full-screen document reader. It opens by scaling up from the card you clicked (a FLIP from the card's rect to a centered column) and, on close, scales back down into that same card. Content- and router-agnostic: pass the document as children and optional prev/next controls via the footer slot.

It renders full-screen (portaled to document.body). The back arrow, the scrim, and the Escape key all close it.

Installation

npx shadcn@latest add https://canvas.blode.co/r/document-overlay.json

Usage

Capture the source card's rect on click, then drive open. Give the card a stable data-card-id (or data-item-id) matching sourceId so the overlay can find it again to scale back into, even if it moved while open.

import { DocumentOverlay } from "@/components/canvas/document-overlay";
 
const [open, setOpen] = useState(false);
const [rect, setRect] = useState<DOMRect | null>(null);
 
<button
  data-card-id="doc-1"
  onClick={(e) => {
    setRect(e.currentTarget.getBoundingClientRect());
    setOpen(true);
  }}
  type="button"
>
  Open
</button>
 
<DocumentOverlay
  onClose={() => setOpen(false)}
  open={open}
  sourceId="doc-1"
  sourceRect={rect}
  title="Brand & identity"
>
  <p>…document content…</p>
</DocumentOverlay>

Pair it with folder-card / document-card (whose items expose data-item-id / data-card-id) and a pagination footer, see the live demo.

Props

PropTypeDefaultDescription
open*booleanWhether the overlay is open.
children*ReactNodeThe document content.
onClose*() => voidCalled after the close animation completes.
sourceRectDOMRect | nullRect of the source card, for the scale-up FLIP.
sourceIdstringSource card id (`data-card-id`/`data-item-id`), re-found on close.
titlestringHeading rendered above the content.
footerReactNodeRendered below the content once open (e.g. pagination).
skipEntrancebooleanfalseSkip the entrance animation (e.g. for a direct link).
onBeforeClose() => voidFired right before the close animation starts.
onExitComplete() => voidFired after the close animation completes.