Skip to content
Areia
Esc
navigateopen⌘Jpreview
On this page

Dropdown

A menu of actions or choices triggered by a button.

A dropdown menu for actions, navigation, and compact option controls.

Source Code

Dropdown is backed by @areia/slots and wires open state, positioning, keyboard navigation, typeahead, item selection, checkbox items, and radio items.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown trigger={<Button>Add</Button>}>
    <Dropdown.Item value="component">Component</Dropdown.Item>
    <Dropdown.Item value="primitive">Primitive</Dropdown.Item>
    <Dropdown.Item value="example">Example</Dropdown.Item>
  </Dropdown>
));

Import

import { Dropdown } from "areia";

Usage

Prefer composing Dropdown.Trigger and Dropdown.Content as children. The trigger, children, and items props remain available as shortcuts.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown>
    <Dropdown.Trigger>
      <Button>Menu</Button>
    </Dropdown.Trigger>
    <Dropdown.Content>
      <Dropdown.Item value="edit">Edit</Dropdown.Item>
      <Dropdown.Item value="duplicate">Duplicate</Dropdown.Item>
      <Dropdown.Separator />
      <Dropdown.Item value="delete" variant="danger">
        Delete
      </Dropdown.Item>
    </Dropdown.Content>
  </Dropdown>
));

Dropdown is available as an alias if that reads better in your code.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown trigger={<Button>Actions</Button>}>
    <Dropdown.Group>
      <Dropdown.Label>Project</Dropdown.Label>
      <Dropdown.Item value="rename">Rename</Dropdown.Item>
      <Dropdown.Item value="duplicate">Duplicate</Dropdown.Item>
    </Dropdown.Group>
    <Dropdown.Separator />
    <Dropdown.Item value="delete" variant="danger">
      Delete
    </Dropdown.Item>
  </Dropdown>
));

Use Dropdown.Static(...) for static markup or when you want to initialize behavior yourself. For most application usage, call Dropdown(...).

Examples

Basic

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown trigger={<Button>Add</Button>}>
    <Dropdown.Item value="component">Component</Dropdown.Item>
    <Dropdown.Item value="primitive">Primitive</Dropdown.Item>
    <Dropdown.Item value="example">Example</Dropdown.Item>
  </Dropdown>
));

Inset Items

Use inset on items without an icon to align their text with selection indicators or icon-bearing items.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown trigger={<Button>Edit</Button>}>
    <Dropdown.Item value="rename">Rename</Dropdown.Item>
    <Dropdown.Item value="duplicate">Duplicate</Dropdown.Item>
    <Dropdown.Separator />
    <Dropdown.Item value="move" inset>
      Move to folder
    </Dropdown.Item>
    <Dropdown.Item value="favorite" inset>
      Add to favorites
    </Dropdown.Item>
    <Dropdown.Separator />
    <Dropdown.Item value="delete" variant="danger">
      Delete
    </Dropdown.Item>
  </Dropdown>
));

Change Events

Use onSelect on the root to respond to accepted item selections.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha
  .state("lastAction", "")
  .render(({ state }) => (
    <div class="flex flex-col items-start gap-3">
      <Dropdown
        trigger={<Button>Actions</Button>}
        onSelect={(value) => {
          state.lastAction(value);
        }}
      >
        <Dropdown.Item value="duplicate">
          Duplicate
        </Dropdown.Item>
        <Dropdown.Item value="rename">Rename</Dropdown.Item>
        <Dropdown.Separator />
        <Dropdown.Item value="delete" variant="danger">
          Delete
        </Dropdown.Item>
      </Dropdown>
      <p class="text-sm text-areia-subtle">
        Last action:{" "}
        <span class="text-areia-default">
          {state.lastAction() || "None"}
        </span>
      </p>
    </div>
  ));

Checkbox Items

Use checkbox items for independently toggleable options.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha
  .state("visible", ["sidebar", "wrap"])
  .render(({ state }) => (
    <Dropdown
      trigger={<Button>View Options</Button>}
      defaultValues={state.visible()}
      closeOnSelect={false}
      onValuesChange={(values) => {
        state.visible(values);
      }}
    >
      <Dropdown.Group>
        <Dropdown.Label>Display</Dropdown.Label>
        <Dropdown.CheckboxItem
          value="sidebar"
          checked={state.visible().includes("sidebar")}
        >
          Show sidebar
        </Dropdown.CheckboxItem>
        <Dropdown.CheckboxItem
          value="lines"
          checked={state.visible().includes("lines")}
        >
          Show line numbers
        </Dropdown.CheckboxItem>
        <Dropdown.CheckboxItem
          value="wrap"
          checked={state.visible().includes("wrap")}
        >
          Word wrap
        </Dropdown.CheckboxItem>
      </Dropdown.Group>
    </Dropdown>
  ));

Radio Items

Use radio items for a single selected value.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha
  .state("density", "comfortable")
  .render(({ state }) => (
    <Dropdown
      trigger={<Button>Density</Button>}
      defaultValue={state.density()}
      closeOnSelect={false}
      onValueChange={(value) => {
        state.density(value ?? "comfortable");
      }}
    >
      <Dropdown.Label>Table density</Dropdown.Label>
      <Dropdown.RadioItem
        value="compact"
        checked={state.density() === "compact"}
      >
        Compact
      </Dropdown.RadioItem>
      <Dropdown.RadioItem
        value="comfortable"
        checked={state.density() === "comfortable"}
      >
        Comfortable
      </Dropdown.RadioItem>
      <Dropdown.RadioItem
        value="spacious"
        checked={state.density() === "spacious"}
      >
        Spacious
      </Dropdown.RadioItem>
    </Dropdown>
  ));

Custom Trigger

Pass any Areia or Ilha-rendered content as the trigger.

AR
import { ilha } from "ilha";
import { Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown
    trigger={
      <span class="flex size-8 items-center justify-center rounded-full bg-areia-accent text-sm font-medium text-white">
        AR
      </span>
    }
    triggerClass="rounded-full"
  >
    <Dropdown.Item value="profile">Profile</Dropdown.Item>
    <Dropdown.Item value="settings">Settings</Dropdown.Item>
    <Dropdown.Separator />
    <Dropdown.Item value="logout" variant="danger">
      Log out
    </Dropdown.Item>
  </Dropdown>
));

Use Dropdown.LinkItem for semantic links.

import { ilha } from "ilha";
import { Button, Dropdown } from "areia";

export default ilha.render(() => (
  <Dropdown trigger={<Button>Resources</Button>}>
    <Dropdown.LinkItem href="/settings" value="settings">
      Settings
    </Dropdown.LinkItem>
    <Dropdown.LinkItem href="/docs" value="docs">
      Documentation
    </Dropdown.LinkItem>
    <Dropdown.Separator />
    <Dropdown.LinkItem
      href="<https://ilha.build/llms.txt"
>      external
      value="ilha-llms"
    >
      Ilha llms.txt
    </Dropdown.LinkItem>
  </Dropdown>
));

API Reference

Root component that manages the dropdown state.

Prop Type Default Description
trigger unknown - Content rendered inside the trigger button.
children unknown - Composed dropdown slots, or menu content when no Dropdown.Content child is present.
items DropdownItemInput[] - Convenience item descriptors. Ignored when children is provided.
defaultOpen boolean false Initial open state.
defaultValue string | null null Initial radio item value.
defaultValues string[] [] Initial checkbox item values.
closeOnSelect boolean true Whether selecting an item closes the menu.
side "top" | "right" | "bottom" | "left" "bottom" Preferred side for the popup.
align "start" | "center" | "end" "start" Preferred alignment relative to the trigger.
onSelect (value: string) => void - Fires when a user selects an item.
onValueChange (value: string | null) => void - Fires when the radio value changes.
onValuesChange (values: string[]) => void - Fires when checkbox values change.
onOpenChange (open: boolean) => void - Called when open state changes.
onPortalMounted (container: HTMLElement) => void - After portaled menu mounts on open. See Dialog docs, Ilha + portaled overlays.
triggerClassName string - Alias for triggerClass.
contentClassName string - Alias for contentClass.

Button that opens the dropdown.

Accepts standard button attributes plus class and className.

Popup container for menu content.

Accepts standard div attributes plus class and className.

Individual menu item for actions.

Prop Type Default Description
value string - Selection value emitted by events.
children unknown - Item content.
label unknown - Convenience label when using item descriptors.
icon unknown - Content displayed before the label.
shortcut unknown - Content displayed at the end of the item.
variant "default" | "danger" "default" Visual style of the item.
selected boolean false Shows the selection indicator initially.
inset boolean false Adds left padding to align text.
disabled boolean false Disables interaction.

A menu item rendered as an anchor.

Prop Type Default Description
href string - URL to navigate to.
external boolean false Adds target="_blank" and rel="noreferrer".
variant "default" | "danger" "default" Visual style of the item.
inset boolean false Adds left padding to align text.

A menu item that toggles membership in the root values array.

Prop Type Default Description
value string - Checkbox value.
checked boolean false Initial checked state and rendered indicator state.
disabled boolean false Disables interaction.

A menu item that sets the root value.

Prop Type Default Description
value string - Radio value.
checked boolean false Initial checked state and rendered indicator state.
disabled boolean false Disables interaction.

Non-interactive label for a group of items.

Wrapper for grouping related labels and items.

Visual divider between menu sections.

Trailing shortcut hint for an item.

Was this page helpful?