Dialog

Displays a modal overlay with animated transitions and gesture-based dismissal.

Import

import { Dialog, useDialog, useDialogAnimation } from 'heroui-native';

Anatomy

<Dialog>
  <Dialog.Trigger>...</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay>...</Dialog.Overlay>
    <Dialog.Content>
      <Dialog.Close>...</Dialog.Close>
      <Dialog.Title>...</Dialog.Title>
      <Dialog.Description>...</Dialog.Description>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog>
  • Dialog: Root component that manages open state and provides context to child components.
  • Dialog.Trigger: Pressable element that opens the dialog when pressed.
  • Dialog.Portal: Renders dialog content in a portal with centered layout and animation control.
  • Dialog.Overlay: Background overlay that appears behind the dialog content, typically closes dialog when pressed.
  • Dialog.Content: Main dialog container with gesture support for drag-to-dismiss.
  • Dialog.Close: Close button that dismisses the dialog when pressed.
  • Dialog.Title: Dialog title text with semantic heading role.
  • Dialog.Description: Dialog description text that provides additional context.

Usage

Basic Dialog

Simple dialog with title, description, and close button.

<Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
  <Dialog.Trigger asChild>
    <Button>Open Dialog</Button>
  </Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay />
    <Dialog.Content>
      <Dialog.Close />
      <Dialog.Title>...</Dialog.Title>
      <Dialog.Description>...</Dialog.Description>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog>

Custom Animations

Configure open and close animations with spring or timing. The closeDelay should typically match your closing animation duration.

<Dialog
  isOpen={isOpen}
  onOpenChange={setIsOpen}
  closeDelay={200} // Match this with closing animation duration
  animation={{
    entering: {
      type: 'spring',
      config: { damping: 130, stiffness: 1100 },
    },
    exiting: {
      type: 'timing',
      config: { duration: 200 }, // Should match closeDelay
    },
  }}
>
  <Dialog.Trigger>...</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay />
    <Dialog.Content>...</Dialog.Content>
  </Dialog.Portal>
</Dialog>

Custom Backdrop

Replace the default overlay with custom content.

<Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
  <Dialog.Trigger>...</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className="bg-transparent">
      <BlurView style={StyleSheet.absoluteFill} />
    </Dialog.Overlay>
    <Dialog.Content>...</Dialog.Content>
  </Dialog.Portal>
</Dialog>

Scrollable Content

Handle long content with scroll views.

<Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
  <Dialog.Trigger>...</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay />
    <Dialog.Content>
      <Dialog.Close />
      <Dialog.Title>...</Dialog.Title>
      <View className="h-[300px]">
        <ScrollView>...</ScrollView>
      </View>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog>

Form Dialog

Dialog with text inputs and keyboard handling.

<Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
  <Dialog.Trigger>...</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay />
    <KeyboardAvoidingView behavior="padding">
      <Dialog.Content>
        <Dialog.Close />
        <Dialog.Title>...</Dialog.Title>
        <TextField>...</TextField>
        <Button onPress={handleSubmit}>Submit</Button>
      </Dialog.Content>
    </KeyboardAvoidingView>
  </Dialog.Portal>
</Dialog>

Example

import { Button, Dialog } from 'heroui-native';
import { View } from 'react-native';
import { useState } from 'react';

export default function DialogExample() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
      <Dialog.Trigger asChild>
        <Button variant="primary">Open Dialog</Button>
      </Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Overlay />
        <Dialog.Content>
          <Dialog.Close />
          <View className="mb-5 gap-1.5">
            <Dialog.Title>Confirm Action</Dialog.Title>
            <Dialog.Description>
              Are you sure you want to proceed with this action? This cannot be
              undone.
            </Dialog.Description>
          </View>
          <View className="flex-row justify-end gap-3">
            <Dialog.Close asChild>
              <Button variant="ghost" size="sm">
                Cancel
              </Button>
            </Dialog.Close>
            <Button size="sm">Confirm</Button>
          </View>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog>
  );
}

API Reference

Dialog

proptypedefaultdescription
childrenReact.ReactNode-Dialog content and trigger elements
isOpenboolean-Controlled open state of the dialog
isDefaultOpenbooleanfalseInitial open state when uncontrolled
closeDelaynumber300Delay in milliseconds before dialog closes (should match closing animation duration)
isDismissKeyboardOnClosebooleantrueWhether to dismiss keyboard when dialog closes
animationDialogRootAnimation-Animation configuration
onOpenChange(value: boolean) => void-Callback when open state changes
...ViewPropsViewProps-All standard React Native View props are supported

DialogRootAnimation

Animation configuration for dialog root component. Can be:

  • false or "disabled": Disable only root animations
  • "disable-all": Disable all animations including children
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
entering.valueSpringAnimationConfig | TimingAnimationConfig{ type: 'timing',
config: { duration: 200,
easing: Easing.out(Easing.ease) } }
Animation configuration for opening
exiting.valueSpringAnimationConfig | TimingAnimationConfig{ type: 'timing',
config: { duration: 150,
easing: Easing.bezier(0.4, 0, 1, 1) } }
Animation configuration for closing

SpringAnimationConfig

proptypedefaultdescription
type'spring'-Animation type (must be 'spring')
configWithSpringConfig-Reanimated spring animation configuration

TimingAnimationConfig

proptypedefaultdescription
type'timing'-Animation type (must be 'timing')
configWithTimingConfig-Reanimated timing animation configuration

Dialog.Trigger

proptypedefaultdescription
childrenReact.ReactNode-Trigger element content
asChildboolean-Render as child element without wrapper
...PressablePropsPressableProps-All standard React Native PressableProps props are supported

Dialog.Portal

proptypedefaultdescription
childrenReact.ReactNode-Portal content (overlay and dialog)
classNamestring-Additional CSS classes for portal container
styleStyleProp<ViewStyle>-Additional styles for portal container
hostNamestring-Optional portal host name for specific container
forceMountboolean-Force mount when closed for animation purposes

Dialog.Overlay

proptypedefaultdescription
childrenReact.ReactNode-Custom overlay content
classNamestring-Additional CSS classes for overlay
styleViewStyle-Additional styles for overlay container
animationDialogOverlayAnimation-Animation configuration
isCloseOnPressbooleantrueWhether pressing overlay closes dialog
forceMountboolean-Force mount when closed for animation purposes
...PressablePropsPressableProps-All standard React Native Pressable props are supported

DialogOverlayAnimation

Animation configuration for dialog overlay component. Can be:

  • false or "disabled": Disable all animations
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
opacity.value[number, number, number][0, 1, 0]Opacity values [idle, open, close]

Dialog.Content

proptypedefaultdescription
childrenReact.ReactNode-Dialog content
classNamestring-Additional CSS classes for content container
styleStyleProp<ViewStyle>-Additional styles for content container
onLayout(event: LayoutChangeEvent) => void-Layout event handler
animationDialogContentAnimation-Animation configuration
isSwipeablebooleantrueWhether the dialog content can be swiped to dismiss
forceMountboolean-Force mount when closed for animation purposes
...Animated.ViewPropsAnimated.ViewProps-All Reanimated Animated.View props are supported

DialogContentAnimation

Animation configuration for dialog content component. Can be:

  • false or "disabled": Disable all animations
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
opacity.value[number, number, number][0, 1, 0]Opacity values [idle, open, close]
scale.value[number, number, number][0.97, 1, 0.97]Scale values [idle, open, close]

Dialog.Close

proptypedefaultdescription
childrenReact.ReactNode-Custom close button content
classNamestring-Additional CSS classes for close button
iconPropsDialogCloseIconProps-Configuration for default close icon
hitSlopnumber12Hit slop area for the close button
asChildboolean-Render as child element without wrapper
...TouchableOpacityPropsTouchableOpacityProps-All standard React Native TouchableOpacity props are supported

DialogCloseIconProps

proptypedescription
sizenumberIcon size (default: 18)
colorstringIcon color (default: theme color muted)

Dialog.Title

proptypedefaultdescription
childrenReact.ReactNode-Title content
classNamestring-Additional CSS classes for title
...TextPropsTextProps-All standard React Native Text props are supported

Dialog.Description

proptypedefaultdescription
childrenReact.ReactNode-Description content
classNamestring-Additional CSS classes for description
...TextPropsTextProps-All standard React Native Text props are supported

Hooks

useDialog

Hook to access dialog primitive context.

const { isOpen, onOpenChange } = useDialog();
propertytypedescription
isOpenbooleanCurrent open state
onOpenChange(value: boolean) => voidFunction to change open state

useDialogAnimation

Hook to access dialog animation context for advanced customization.

const { dialogState, progress, isDragging, isGestureReleaseAnimationRunning } =
  useDialogAnimation();
propertytypedescription
dialogState'idle' | 'open' | 'close'Internal dialog state
progressSharedValue<number>Animation progress (0=idle, 1=open, 2=close)
isDraggingSharedValue<boolean>Whether dialog is being dragged
isGestureReleaseAnimationRunningSharedValue<boolean>Whether gesture release animation is running

On this page