Dialog

A modal dialog component that overlays the main UI. Dialogs trap focus and prevent interaction with the underlying content, following accessibility best practices.

Props

Dialog component

PropTypeRequiredDescription
labelstringYesDialog title displayed in the header
childrenReactNodeYesDialog content
close() => voidYesFunction to close the dialog

useDialog hook

ParameterTypeDescription
DialogComponent(props: { close: () => void } & Input) => JSX.ElementComponent to render inside the dialog
options.closeOnOutsideClickbooleanWhether clicking outside closes the dialog

Returns:

  • open(input?: Input) - Function to open the dialog with optional input data
  • close() - Function to close the dialog programmatically

Basic usage

Click the button to open a dialog:

import { Dialog, useDialog } from "aidos-ui";

function MyDialog({ close }) {
  return (
    <Dialog close={close} label="Settings">
      <Row padding="medium" align="center" justify="space-between">
        <Span>Dark mode</Span>
        <DarkModeToggle />
      </Row>
    </Dialog>
  );
}

function App() {
  const { open } = useDialog(
    ({ close }) => <MyDialog close={close} />,
    { closeOnOutsideClick: true }
  );

  return (
    <Button color="primary" onClick={() => open()}>
      Open Settings
    </Button>
  );
}

Passing data to dialog

Use TypeScript generics to pass data when opening the dialog:

interface UserData {
  name: string;
  email: string;
}

function EditUserDialog({ close, name, email }: { close: () => void } & UserData) {
  return (
    <Dialog close={close} label="Edit User">
      <Column padding="medium" gap="medium">
        <TextInput value={name} onValueChange={() => {}} />
        <TextInput value={email} onValueChange={() => {}} />
        <Button color="primary" onClick={close}>
          Save
        </Button>
      </Column>
    </Dialog>
  );
}

function App() {
  const { open } = useDialog<UserData>(
    ({ close, name, email }) => (
      <EditUserDialog close={close} name={name} email={email} />
    ),
    { closeOnOutsideClick: false }
  );

  return (
    <Button
      color="secondary"
      onClick={() => open({ name: "John", email: "john@example.com" })}
    >
      Edit User
    </Button>
  );
}

Dialog options

Close on outside click

Control whether clicking the backdrop closes the dialog:

// Dialog closes when clicking outside
const { open } = useDialog(
  ({ close }) => <MyDialog close={close} />,
  { closeOnOutsideClick: true }
);

// Dialog stays open until explicitly closed
const { open } = useDialog(
  ({ close }) => <MyDialog close={close} />,
  { closeOnOutsideClick: false }
);

Closing the dialog

Dialogs can be closed in several ways:

  1. Close button - Built into the Dialog header
  2. Escape key - Native dialog behavior
  3. Outside click - When closeOnOutsideClick: true
  4. Programmatically - Using the close function
function ConfirmDialog({ close, onConfirm }) {
  return (
    <Dialog close={close} label="Confirm">
      <Column padding="medium" gap="medium">
        <P>Are you sure you want to proceed?</P>
        <Row gap="medium" justify="end">
          <Button bare color="secondary" onClick={close}>
            Cancel
          </Button>
          <Button
            color="primary"
            onClick={() => {
              onConfirm();
              close();
            }}
          >
            Confirm
          </Button>
        </Row>
      </Column>
    </Dialog>
  );
}

Setup

The DialogProvider must wrap your app to enable dialogs. This is typically included in the Providers component:

import { Providers } from "aidos-ui";

function App() {
  return (
    <Providers>
      {/* Your app content */}
    </Providers>
  );
}

Accessibility

  • Uses native <dialog> element with showModal() for proper modal behavior
  • Focus is trapped within the dialog
  • Escape key closes the dialog
  • Focus returns to the triggering element when closed
  • Backdrop prevents interaction with underlying content