Components
Modal (Dialog)

Modal (Dialog)

Installation

To get started, install Headless UI via npm:

npm install headlessui-react-native

Basic example

Modals are built using the Modal, ModalPanel, and ModalTitle components:

import { Modal, ModalPanel, ModalTitle } from "headlessui-react-native";
import React, { useState } from "react";
import { Button, Text, TextStyle, View, ViewStyle } from "react-native";
 
export function ModalExample() {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <View>
      <Button title="Open dialog" onPress={() => setIsOpen(true)} />
      <Modal onClose={() => setIsOpen(false)} open={isOpen}>
        <View style={modalContainerStyle}>
          <ModalPanel style={modalPanelStyle}>
            <ModalTitle style={modalTitleStyle}>Payment successful</ModalTitle>
            <View style={modalPanelContentStyle}>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
            </View>
            <Button title="Got it, thanks!" onPress={() => setIsOpen(false)} />
          </ModalPanel>
        </View>
      </Modal>
    </View>
  );
}
 
const modalContainerStyle: ViewStyle = {
  width: "100%",
  height: "100%",
  alignItems: "center",
  justifyContent: "center",
  padding: 40,
  backgroundColor: "rgba(0, 0, 0, 0.5)",
};
const modalPanelStyle = {
  padding: 20,
  width: 300,
  backgroundColor: "white",
};
const modalTitleStyle: TextStyle = { fontSize: 20, fontWeight: "700" };
const modalPanelContentStyle = { paddingTop: 20, paddingBottom: 20 };

Examples

Showing/hiding the modal

Modals are controlled components, meaning that you have to provide and manage the open state yourself using the open prop and the onClose callback.

The onClose callback is called when an modal is dismissed, which happens when the user clicks outside the ModalPanel. In this callback set the open state back to false to close the modal.

import {  Modal, ModalPanel, ModalTitle } from 'headlessui-react-native'
import { useState } from 'react'
 
function Example() {
  // The open/closed state lives outside of the `Modal` and is managed by you
  let [isOpen, setIsOpen] = useState(true)
 
  function async handleDeactivate() {
    await fetch('/deactivate-account', { method: 'POST' })
    setIsOpen(false)
  }
 
  return (
    <Modal open={isOpen} onClose={() => setIsOpen(false)}>
      <ModalPanel>
        <ModalTitle>Deactivate account</ModalTitle>
        <Text>This will permanently deactivate your account</Text>
        <Text>Are you sure you want to deactivate your account? All of your data will be permanently removed.</Text>
 
        {/*
          You can render additional buttons to dismiss your
          modal by setting `open` to `false`.
        */}
        <Button title="Cancel" onPress={() => setIsOpen(false)}/>
        <Button title="Deactivate" onPress={handleDeactivate}/>
      </ModalPanel>
    </Modal>
  )
}

For situations where you don't have easy access to your open/close state, Headless UI provides a CloseButton component that will close the nearest modal ancestor when clicked.

import { CloseButton } from "headlessui-react-native";
import { MyModal } from "./my-modal";
 
function Example() {
  return (
    <MyModal>
      {/* ... */}
      <CloseButton>
        <Text>Cancel</Text>
      </CloseButton>
    </MyModal>
  );
}

Scrollable modals

import { Modal, ModalPanel, ModalTitle } from "headlessui-react-native";
import React, { useState } from "react";
import { Button, Text, TextStyle, View, ViewStyle } from "react-native";
 
export function ScrollableModalExample() {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <View>
      <Button title="Open dialog" onPress={() => setIsOpen(true)} />
      <Modal onClose={() => setIsOpen(false)} open={isOpen}>
        <View style={modalContainerStyle}>
          <ModalPanel scrollable style={modalPanelStyle}>
            <ModalTitle style={modalTitleStyle}>Payment successful</ModalTitle>
            <View style={modalPanelContentStyle}>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
              <Text>
                Your payment has been successfully submitted. We’ve sent you an
                email with all of the details of your order.
              </Text>
            </View>
            <Button title="Got it, thanks!" onPress={() => setIsOpen(false)} />
          </ModalPanel>
        </View>
      </Modal>
    </View>
  );
}
 
const modalContainerStyle: ViewStyle = {
  width: "100%",
  height: "100%",
  alignItems: "center",
  justifyContent: "center",
  padding: 40,
  backgroundColor: "rgba(0, 0, 0, 0.5)",
};
const modalPanelStyle = {
  padding: 20,
  width: 300,
  backgroundColor: "white",
};
const modalTitleStyle: TextStyle = { fontSize: 20, fontWeight: "700" };
const modalPanelContentStyle = { paddingTop: 20, paddingBottom: 20 };

Component API

Modal

The main modal component. This has predefined roles, so it cannot be rendered as another component using the as prop.

PropDefaultDescription
openfalseBoolean Whether the modal is open or not.
onCloseCalled when the Modal is dismissed (via outside click of the ModalPanel). Typically used to close the modal by setting open to false.
Render PropDescription
openBoolean Whether the modal is open or not.

ModalPanel

This indicates the panel of your actual Modal. Clicking outside of this component will trigger the onClose of the Modal component.

PropDefaultDescription
asViewString The element the modal panel should render as.
Render PropDescription
openBoolean Whether the modal is open or not.

ModalTitle

This is the title for your Modal.

PropDefaultDescription
asTextString The element the modal title should render as.
Render PropDescription
openBoolean Whether the modal is open or not.

CloseButton

This button will close the nearest Modal ancestor when clicked.

PropDefaultDescription
asPressableString The element the close button should render as.