10x-media plugins
Form Builder

Presentations

Page, inline, modal, and drawer surfaces, and the overlay primitives behind them.

A presentation is a named bundle controlling how a form surfaces: in the page flow, or as an overlay, and whether it dismisses on success. Four ship by default:

NameSurfaceBehavior
pageIn flow (default)Renders inline in the page.
inlineEmbeddedSame as page, semantically scoped to an embedded slot.
modalOverlayCentered dialog; dismisses on success.
drawerOverlaySide panel; dismisses on success.

Choosing a presentation

Presentation is a rendering concern, decided by the code that renders the form, not stored on the form document. Pass the presentation prop, as a registered name or an inline object (page is the default when omitted):

<Form form={form} presentation="modal" onClose={() => setOpen(false)} title="Contact us" />

onClose is forwarded to the presentation's Wrapper so the host controls closing; title becomes the overlay's accessible name.

Custom presentations

Register at render time through the presentations prop, following the opt-in convention (false removes a built-in, an object adds or replaces one). An overlay presentation is a full FormPresentation with the React Wrapper it needs:

import { DialogSurface, type FormPresentation } from '@10x-media/form-builder/react'

const fullscreen: FormPresentation = {
  name: 'fullscreen',
  label: 'Fullscreen',
  surface: 'overlay',
  density: 'comfortable',
  dismissOnSuccess: true,
  Wrapper: ({ open, onClose, title, children }) => (
    <DialogSurface open={open} onClose={onClose} label={title} surface="fullscreen">
      {children}
    </DialogSurface>
  ),
}

<Form form={form} presentations={{ fullscreen }} presentation="fullscreen" onClose={close} />

Overlay primitives

The built-in modal and drawer are thin compositions of exported primitives; take exactly the pieces you need:

import {
  DialogSurface, // backdrop + role=dialog/aria-modal + focus trap + scroll lock + dismiss
  Backdrop,      // full-viewport scrim with a data-fb-backdrop hook
  useFocusTrap,  // keep Tab/Shift-Tab inside a container
  useScrollLock, // lock body scroll while open
  useDismiss,    // wire Escape and outside-click to a callback
} from '@10x-media/form-builder/react'

DialogSurface ships the accessible baseline: role="dialog" with aria-modal, initial focus on open and focus restore on close, scroll lock, Escape and outside-click dismiss (both configurable), and a labelled close button. The drawer variant adds a surface="drawer" data hook for CSS positioning. Overlays use position: fixed (no portal yet).

Planned: a portal for overlays, popover and exit-intent triggers, and styled shadcn wrappers.

On this page