Dialog
A general-purpose modal dialog that overlays the screen and focuses user attention on content or actions.
The Dialog component is a general-purpose modal overlay built with React Native's Modal API. It supports controlled and uncontrolled state, a compound component API with header, footer, title, description, and close button parts, and a backdrop overlay that dismisses on press.
Preview
Installation
npx novaui-cli add dialogImport
import {
Dialog,
DialogTrigger,
DialogPortal,
DialogOverlay,
DialogClose,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
} from 'novaui-components'Basic Usage
The Dialog is a compound component with these parts:
Dialog- Root container with open/close stateDialogTrigger- Button that opens the dialogDialogPortal- Renders content in a React Native ModalDialogOverlay- Semi-transparent backdropDialogContent- The modal content container with close buttonDialogHeader- Groups the title and descriptionDialogFooter- Groups the action buttonsDialogTitle- The dialog headingDialogDescription- The dialog body textDialogClose- A button that closes the dialog
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
DialogClose,
} from 'novaui-components'
import { Button } from 'novaui-components'
import { Text } from 'react-native'
export function BasicDialog() {
return (
<Dialog>
<DialogTrigger>
<Button variant="outline" label="Open Dialog" />
</DialogTrigger>
<DialogPortal>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose>
<Button variant="outline" label="Cancel" />
</DialogClose>
<Button label="Save changes" />
</DialogFooter>
</DialogContent>
</DialogPortal>
</Dialog>
)
}Without Close Button
Hide the built-in close icon with showCloseButton={false}:
<Dialog>
<DialogTrigger>
<Button variant="outline" label="No Close Icon" />
</DialogTrigger>
<DialogPortal>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>Terms of Service</DialogTitle>
<DialogDescription>
Please read and accept the terms of service before continuing.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose>
<Button variant="outline" label="Decline" />
</DialogClose>
<Button label="Accept" />
</DialogFooter>
</DialogContent>
</DialogPortal>
</Dialog>Controlled State
Control the dialog open/close state programmatically:
import { useState } from 'react'
export function ControlledDialog() {
const [open, setOpen] = useState(false)
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger>
<Button variant="outline" label="Controlled Dialog" />
</DialogTrigger>
<DialogPortal>
<DialogContent>
<DialogHeader>
<DialogTitle>Controlled State</DialogTitle>
<DialogDescription>
This dialog's state is managed externally via the open and onOpenChange props.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose>
<Button variant="outline" label="Close" />
</DialogClose>
</DialogFooter>
</DialogContent>
</DialogPortal>
</Dialog>
)
}With Form Content
Use the dialog for forms or interactive content:
import { useState } from 'react'
import { View, TextInput } from 'react-native'
export function FormDialog() {
const [open, setOpen] = useState(false)
const handleSubmit = () => {
// Process form data
setOpen(false)
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger>
<Button variant="outline" label="Edit Profile" />
</DialogTrigger>
<DialogPortal>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>
Update your profile information below.
</DialogDescription>
</DialogHeader>
<View className="gap-4 py-4">
<View className="gap-2">
<Text className="text-sm font-medium">Name</Text>
<TextInput
className="h-10 w-full rounded-md border border-input bg-background px-3"
placeholder="Your name"
/>
</View>
<View className="gap-2">
<Text className="text-sm font-medium">Email</Text>
<TextInput
className="h-10 w-full rounded-md border border-input bg-background px-3"
placeholder="your@email.com"
/>
</View>
</View>
<DialogFooter>
<DialogClose>
<Button variant="outline" label="Cancel" />
</DialogClose>
<Button label="Save" onPress={handleSubmit} />
</DialogFooter>
</DialogContent>
</DialogPortal>
</Dialog>
)
}Props API
Dialog Props
Extends React.ComponentPropsWithoutRef<typeof View> and includes:
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Callback when open state changes |
DialogTrigger Props
Extends React.ComponentPropsWithoutRef<typeof Pressable>:
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as the child element instead of a Pressable |
DialogContent Props
Extends React.ComponentPropsWithoutRef<typeof View>:
| Prop | Type | Default | Description |
|---|---|---|---|
showCloseButton | boolean | true | Whether to show the close (X) button |
className | string | - | Additional CSS classes |
DialogHeader Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
DialogFooter Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
DialogTitle Props
Extends React.ComponentPropsWithoutRef<typeof Text>:
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
DialogDescription Props
Extends React.ComponentPropsWithoutRef<typeof Text>:
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
DialogClose Props
Extends React.ComponentPropsWithoutRef<typeof Pressable>:
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as the child element instead of a Pressable |
Accessibility
- Uses React Native
Modalfor proper overlay behavior onRequestClosehandles the Android back button- Backdrop press dismisses the dialog
- Close button is provided by default for easy dismissal
Best Practices
-
Use for general content: Dialogs are for forms, settings, confirmations, and any focused content — use
AlertDialogfor destructive confirmations -
Keep it focused: Each dialog should serve a single purpose
-
Provide a clear exit: Always include a close button or cancel action
-
Responsive sizing: Content uses
max-w-lgby default — override withclassNamefor wider dialogs -
Don't nest dialogs: Avoid opening a dialog from within another dialog
Related Components
- Use
AlertDialogfor destructive confirmation prompts - Use
Sheetfor side panels or bottom sheets - Use
Drawerfor mobile-friendly bottom drawers