Dialog
Show a modal with configurable layout and accessible actions
Dialog presents focused content in an accessible modal with composable parts and optional Sheet adaptation.
Features
Customizable, themeable default styling
Transitions, themes, and focus props
Accessibility checks for ARIA props during development
Per-part presence lifecycle for reliable exit animations
Dialog shows content in a floating window above the page. Dialogs automatically stack above other overlays. Open the code example above for a copy-paste implementation.
Installation
Dialog is already installed in tamagui, or you can install it independently:
yarn
npm
bun
pnpm
For native apps, we recommend setting up native portals to preserve React context inside Dialog content.
Anatomy
Scoping
Dialog supports scoping which lets you mount one or more Dialog instances at the root of your app, while having a deeply nested child Trigger or Content attach to the proper parent Dialog instance.
In performance-sensitive areas this lets you render only Dialog.Trigger in
that subtree, since Dialog is not cheap to render and carries a lot of
functionality.
Here’s the basic anatomy of using scope and placing your Dialog higher up for
performance:
_layout.tsx
UserProfile.tsx
Note that the Trigger scope ties to the Dialog scope.
Dismissal behavior
By default, dialogs can be dismissed by:
- Clicking outside the dialog content (on the overlay)
- Pressing the Escape key
- Clicking a Dialog.Close element
Modal vs non-modal dialogs
- Modal dialogs (
modal={true}, which is the default):- In v1, have
disableOutsidePointerEventsset totrueby default - Still dismiss on outside click, but prevent interaction with elements behind the dialog
- Prevent right-click dismissal (right-clicks on the overlay are ignored)
- In v1, have
- Non-modal dialogs (
modal={false}):- Allow interaction with elements behind the dialog
- Dismiss on any outside click
- Do not trap focus
- Do not enable RemoveScroll while open in v3
In v3, Dialog parts own their presence lifecycle. Overlay and content can finish
exit animations before unmounting, and onTransition reports completion from
the animated part rather than from the root alone.
Preventing outside dismissal
To prevent a dialog from closing when clicking outside:
API reference
Dialog
Contains every component for the dialog. Beyond Tamagui Props, adds:
Props
children (required)
React.ReactNode
Must contain Dialog.Content
scope
string
Isolates this Dialog and its parts from other Dialog instances when needed.
open
boolean
Controlled open state of the dialog.
defaultOpen
boolean
Initial open state when uncontrolled.
onOpenChange
(open: boolean) => void
Called when the dialog opens or closes.
modal
boolean
Default:
trueWhen true, traps focus, blocks outside scroll and interaction, and portals into the root of the app. When false, the dialog renders inline and is non-blocking.
keepChildrenMounted
boolean
Default:
falseWhen true, dialog content stays mounted in the DOM even when closed. Useful for preserving state across open/close cycles or when you need faster re-opening.
disableRemoveScroll
boolean
Used to disable the automatic removal of scrolling from the page when open.
onAnimationComplete
(info: { open: boolean }) => void
Called when the dialog open or close animation completes.
Dialog.Trigger
Just Tamagui Props.
Dialog.Portal
Renders Dialog into appropriate container. Beyond Tamagui Props, adds:
Props
forceMount
boolean
Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.
unstyled
boolean
Removes all default Tamagui styles.
Dialog.Content
Main container for Dialog content, this is where you should apply animations.
Dialog.Content no longer accepts the old no-op size variant in v3.
To sit the content a level above the page, wrap it in theme="level2" (see
Surfaces and levels):
Beyond Tamagui Props, adds:
Props
forceMount
boolean
Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.
unstyled
boolean
Removes all default Tamagui styles.
disableOutsidePointerEvents
boolean
When true, hover/focus/click interactions will be disabled on elements outside the Dialog. Users will need to click twice on outside elements to interact with them: once to close the Dialog, and again to trigger the element. Note: In v1, modal dialogs have this set to true by default.
onEscapeKeyDown
(event: KeyboardEvent) => void
Called when Escape is pressed while the content is active.
onInteractOutside
(event: Event) => void
Called when pointer or focus interaction happens outside the content. Prevent default to stop dismissal.
Dialog.Overlay
Displays behind Content. Beyond Tamagui Props, adds:
Props
forceMount
boolean
Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.
Dialog.Title
Required. Can wrap in VisuallyHidden to hide.
Defaults to H2, see Headings.
Dialog.Description
Required. Can wrap in VisuallyHidden to hide.
Defaults to Paragraph, see Paragraph.
Dialog.Close
Closes the Dialog, accepts the same props as View. Recommended to use with
your own component and asChild.
Props
displayWhenAdapted
boolean
By default Close elements hide when Adapt is active. If set to true, they will show when adapted.
Dialog.FocusScope
Provides access to the underlying FocusScope component used by Dialog for focus management. Can be used to control focus behavior from a parent component.
Props
enabled
boolean
Default:
trueWhether focus management is enabled
loop
boolean
Default:
falseWhen true, tabbing from last item will focus first tabbable and shift+tab from first item will focus last tabbable
trapped
boolean
Default:
falseWhen true, focus cannot escape the focus scope via keyboard, pointer, or programmatic focus
noFocus
boolean
Default:
falseZero focus mode. While active, focus is allowed neither inside nor outside the scope. Web only.
focusOnIdle
boolean | number
Default:
trueWhen true, waits for idle before focusing. When a number, waits that many ms. This prevents reflows during animations
onMountAutoFocus
(event: Event) => void
Event handler called when auto-focusing on mount. Can be prevented
onUnmountAutoFocus
(event: Event) => void
Event handler called when auto-focusing on unmount. Can be prevented
Adapted Sheet
When used with Adapt, Dialog can hand its content to a Sheet at the matching breakpoint.
See Sheet for more props.
Use Adapt.Contents inside Sheet.Container to insert the contents given to
Dialog.Content.
Source
v2-look Dialog: scrim background on the Overlay and background/border/padding/radius/shadow on the Content, over the unstyled @tamagui/ui Dialog behavior (which keeps only positioning + pointer-event bookkeeping). This is the exact source the registry ships — copy it into your app and the examples above import from your copy.
components/tamagui/Dialog.tsxDependencies
yarn add @tamagui/core @tamagui/dialogExpects theme tokens: background, border-color. Native: requires a Portal provider at the app root for the dialog to mount above content
Need raw behavior without any skin? tamagui/unstyled re-exports the @tamagui/ui primitives (advanced).