Knit UI
GitHub

Playground

Loading playground…

false
false
true
false
true
false
false
false
false
false
Playground
<Modal
  opened={false}
  title="Modal title"
  size="md"
  shadow="xl"
  centered={false}
  fullScreen={false}
  withCloseButton
  withHeaderDivider={false}
  withOverlay
>
  Modal body content goes here.
</Modal>

Examples

Trigger

A controlled trigger — press the button to open, close button or backdrop to dismiss.

Loading example…

TriggerSourceStorybook

Sizes

All seven content widths shown via a controlled trigger for each size.

Loading example…

SizesSourceStorybook

Shadows

Each shadow elevation step (xxs–xxl) on the content panel.

Loading example…

ShadowsSourceStorybook

Centered

Vertically centred in the viewport — useful for confirmation dialogs.

Loading example…

CenteredSourceStorybook

Full Screen

Full-screen mode — no radius, no padding offset, fills the entire viewport.

Loading example…

Full ScreenSourceStorybook

Without Close Button

Close button hidden — the caller is responsible for dismissal.

Loading example…

Without Close ButtonSourceStorybook

Custom Close Label

Custom aria-label on the close button for screen-reader users.

Loading example…

Custom Close LabelSourceStorybook

Scrollable Body

Long content scrolls inside the body while the header stays pinned.

Loading example…

Scrollable BodySourceStorybook

Compound API

Compound API — compose Modal.Header, Modal.Title, and Modal.Body directly.

Loading example…

Compound APISourceStorybook

Styles

Per-slot styles targets individual parts — here the overlay, content, and title.

Loading example…

StylesSourceStorybook

With Header Divider

A hairline divider separates the pinned header from a scrolling body.

Loading example…

With Header DividerSourceStorybook

Custom Padding

Roomier padding on the header and body for a more spacious layout.

Loading example…

Custom PaddingSourceStorybook

Custom Close Button

The close control is fully customisable via closeButtonProps — here a larger, rounded button.

Loading example…

Custom Close ButtonSourceStorybook

No Overlay

No backdrop — the modal floats over the page without dimming it.

Loading example…

No OverlaySourceStorybook

Non Dismissable

A non-dismissable dialog — escape and backdrop clicks are disabled; only an explicit action closes it.

Loading example…

Non DismissableSourceStorybook

With Rich Content

Rich body content — a confirmation dialog with actions.

Loading example…

With Rich ContentSourceStorybook

Drag To Dismiss

Drag-to-dismiss (dragToDismiss) — flick the panel up to close it, the same reanimated + gesture mechanic as @knitui/sheet. The CSS enter/exit motion is unchanged; this only adds the interactive drag. Release past ~30% of the panel height (or an upward fling) dismisses; a short drag springs back. A stationary tap on the backdrop still dismisses.

Loading example…

Drag To DismissSourceStorybook

Props

PropTypeDefaultDescription
onClose required() => voidCalled when the overlay requests to close (Escape, overlay click, close button).
opened requiredbooleanfalseControlled opened state.
animationfalse | MotionPresetName | MotionPreset | undefineda subtle drop-in fade. Reduced motion is always honoured. Exit animates (the panel and scrim fade out before unmounting) unless `keepMounted` is set.Enter/exit animation — a motion preset name, an inline {@link MotionPreset}, or `false` to disable.
animationConfigSpringConfig | undefinedSpring config for the drag settle (reanimated `withSpring`).
aria-describedbystring | undefinedAdditional content description id(s).
aria-labelstring | undefined"Modal"Accessible label used when no visible title is provided.
aria-labelledbystring | undefinedExplicit label id used when composing a custom title.
centeredboolean | undefinedfalseCenter the content vertically inside the viewport.
childrenReactNodeModal body content goes here.Modal body content.
closeButtonPropsCloseButtonProps | undefinedProps forwarded to the header `CloseButton` — customise its `aria-label`, `icon`, `iconSize`, `size`, `variant`, `radius`, etc. A custom `onPress` overrides the default `onClose` wiring.
closeOnClickOutsideboolean | undefinedtrueClose when the user clicks the overlay scrim.
closeOnEscapeboolean | undefinedtrueClose when the user presses Escape (web).
disabled systemboolean | undefined
dragThresholdnumber | undefined0.3Distance dragged, as a fraction of the panel height, past which releasing dismisses (a downward fling always dismisses).
dragToDismissboolean | undefinedfalseAllow dragging the panel down to dismiss (reanimated + gesture, the same mechanic as `@knitui/sheet`). The CSS enter/exit motion is unchanged; this only adds the interactive drag-to-close.
durationnumber | undefinedAnimation speed in ms — overrides the preset's duration while keeping its easing. Ignored when `animation` is `false` or reduced motion is on.
fullScreenboolean | undefinedfalseExpand the modal to fill the entire screen.
keepMountedboolean | undefinedfalseKeep mounted while closed.
lockScrollboolean | undefinedtrueLock body scroll while opened (web).
overlayAnimationfalse | MotionPresetName | MotionPreset | undefined"fade". Reduced motion is always honoured. The content frame's own animation is supplied separately by the consumer (`Modal`/`Drawer`) on its content frame; pass `false` here to keep the scrim in lockstep when the consumer disables that.Enter/exit animation for the overlay scrim — a motion preset name, an inline {@link MotionPreset}, or `false` to disable.
overlayPropsOverlayProps | undefinedProps forwarded to the underlying `Overlay` scrim.
paddingnumber | SpaceTokens | Animated.AnimatedNode | "safe" | null | undefined"$md"Inner spacing for the header and body.
radius systemstring | number | undefined"md"Content corner radius.
returnFocusboolean | undefinedtrueReturn focus to the previously-focused element on close (web).
shadow system"xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined
xxs · xs · sm · md · lg · xl · xxl
"xl"Drop-shadow elevation of the content panel (xxs–xxl).
size systemstring | number | undefined
xxs · xs · sm · md · lg · xl · xxl
"md"Content width — key (xxs–xxl), px number, or CSS string.
styles systemModalStyles | undefinedUniform per-slot style passthrough. See {@link ModalStyles}.
theme systemThemeName | null | undefinedApplies a theme to this element
titleReactNodeModal titleModal title rendered in the header.
trapFocusboolean | undefinedtrueTrap keyboard focus while opened (web).
withCloseButtonboolean | undefinedtrueShow the close button in the header.
withHeaderDividerboolean | undefinedfalseRender a hairline divider under the header.
withinPortalboolean | undefinedtrueRender inside a `Portal`.
withOverlayboolean | undefinedtrueRender a dimmed backdrop behind the modal.
xOffsetnumber | SpaceTokens | Animated.AnimatedNode | "safe" | null | undefined"$xl"Horizontal gap from viewport edges.
yOffsetnumber | SpaceTokens | Animated.AnimatedNode | "safe" | null | undefined"$xl" (a cross-platform theme token; Mantine defaults to the web-only `5dvh`).Vertical gap from viewport edges.
zIndexnumber | undefined200Root `z-index`.

Style slots

Every part of Modal can be styled through the styles prop. Explicit props on the component always win over slot styles.

SlotUsage
bodystyles={{ body: { … } }}
closeButtonstyles={{ closeButton: { … } }}
contentstyles={{ content: { … } }}
headerstyles={{ header: { … } }}
overlaystyles={{ overlay: { … } }}
titlestyles={{ title: { … } }}
Accessibility & DOM props (2)
PropType
keyKey | null | undefined
refRef<TamaguiElement> | undefined

Plus 493 inherited style props from Box — the full Tamagui/React Native style surface, including token shorthands like p, mx, bg and c. See Tokens for the scales they accept, or the full list.