Anthony Garand

Anthony Garand

Front-End Engineer @ Towbook

Composing a Radix Dialog inside of a Dropdown

This is a basic example of how to compose a Radix Dialog inside of a Radix Dropdown. The key parts to note is the `DropdownMenu.Item` is used as the `Dialog.Trigger` with the `asChild` prop. Also, the `DropdownMenu.Item` has a `onSelect` handler that prevents the default action of the `DropdownMenu.Item` which is to close the menu.

<DropdownMenu.Root>
  <DropdownMenu.Trigger asChild>
    <Button>Actions</Button>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <Dialog.Root>
      <Dialog.Trigger asChild>
        <DropdownMenu.Item onSelect={(e) => e.preventDefault()}>
          Open Dialog
        </DropdownMenu.Item>
      </Dialog.Trigger>
      <Dialog.Content>My Dialog Content</Dialog.Content>
    </Dialog.Root>
  </DropdownMenu.Content>
</DropdownMenu.Root>

Conditionally Hiding the Dropdown

If you wanted to extend this further, you could hide the dropdown when the Dialog is open by controlling the state of the dialog with `React.useState` using the `open, onOpenChange` props on `Dialog.Root`, setting the state in the `onSelect` of the `DropdownMenu.Item` and setting `hidden=isDialogOpen` on the `DropdownMenu.Content` element.

const [isDialogOpen, setIsDialogOpen] = React.useState(false);

<DropdownMenu.Root>
  <DropdownMenu.Trigger asChild>
    <Button>Actions</Button>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content hidden={isDialogOpen}>
    <Dialog.Root open={isDialogOpen} onOpenChange={setIsDialogOpen}>
      <Dialog.Trigger asChild>
        <DropdownMenu.Item onSelect={(e) => {
          e.preventDefault();
          setIsDialogOpen(true);
        }}>
          Open Dialog
        </DropdownMenu.Item>
      </Dialog.Trigger>
      <Dialog.Content>My Dialog Content</Dialog.Content>
    </Dialog.Root>
  </DropdownMenu.Content>
</DropdownMenu.Root>