Skip to content

Dropdown ​

A dropdown is a menu of things to do. That is what separates it from a Select, which is a value to choose: a select has a current value and a dropdown does not.

The items are Menu parts rather than dropdown-specific ones — MenuItem, MenuSection, MenuItemIndicator — because a dropdown is a popover with a menu inside it, and the same menu appears in other places.

ts
import { Dropdown, DropdownMenu, DropdownPopover, MenuItem } from "ropav";

Sections and separators ​

MenuSection groups items that belong together; a Separator between sections draws the line. An item that destroys something takes variant="danger", which is the one place colour is doing work in a menu.

dropdown-sections.vue
vue
<script setup lang="ts">
import {
  Button,
  Dropdown,
  DropdownMenu,
  DropdownPopover,
  Label,
  MenuItem,
  MenuSection,
  Separator,
} from "ropav";
</script>

<template>
  <Dropdown>
    <Button variant="secondary">Actions</Button>

    <DropdownPopover>
      <DropdownMenu>
        <MenuSection>
          <MenuItem id="new" text-value="New file">
            <Label>New file</Label>
          </MenuItem>
          <MenuItem id="copy" text-value="Copy link">
            <Label>Copy link</Label>
          </MenuItem>
        </MenuSection>

        <Separator />

        <MenuSection>
          <MenuItem id="delete" text-value="Delete file" variant="danger">
            <Label>Delete file</Label>
          </MenuItem>
        </MenuSection>
      </DropdownMenu>
    </DropdownPopover>
  </Dropdown>
</template>

Every item needs an id and a text-value. The id is what a selection reports; the text-value is what typeahead matches against, which matters as soon as an item's content is more than a string.

DropdownSubmenuTrigger opens a nested menu. It is an item and a trigger at once, so it takes the same id and text-value as any other item.

Accessibility ​

  • The menu is one stop in the tab order. Arrow keys move between items, typing jumps to a match, and Esc closes the menu and returns focus to the trigger.
  • A trigger with only an icon needs an aria-label — Actions, not Menu, if you can say what the actions are about.
  • The popover flips and shifts to stay in the viewport, so a menu at the edge of the window opens where it fits rather than off-screen.

API ​

PropTypeDefaultDescription
defaultOpenboolean—
isDisabledboolean—Disables the trigger, so the menu cannot be opened.
isOpenboolean—
trigger"longPress" | "press""press"How the menu is opened.

Slots: default.

EventPayload
openChangeboolean
update:isOpenboolean
PropTypeDefaultDescription
defaultSelectedKeys"all" | Iterable<CollectionKey>—
disabledBehavior"all" | "selection""all"
disabledKeysIterable<CollectionKey>—
disallowEmptySelectionboolean—
selectedKeys"all" | Iterable<CollectionKey>—
selectionBehavior"replace" | "toggle""toggle"
selectionMode"none" | "single" | "multiple""none"
shouldCloseOnSelectbooleantrueWhether choosing an item closes the menu.
size"xs" | "sm" | "md" | "lg""md"How tall a row stands, matching a field of the same size.

Slots: default, empty.

EventPayload
actionCollectionKey
selectionChangeCollectionSelection
update:selectedKeysCollectionSelection
PropTypeDefaultDescription
arrowBoundaryOffsetnumber0Distance kept between the arrow and the corner of the popover.
containerPaddingnumber12Distance kept between the popover and the edge of the viewport.
crossOffsetnumber0Distance along the cross axis.
isKeyboardDismissDisabledbooleanfalse
offsetnumber8Distance along the main axis, between the popover and its trigger.
placement"bottom" | "bottom end" | "bottom left" | "bottom right" | "bottom start" | "end" | "end bottom" | "end top" | "left" | "left bottom" | "left top" | "right" | "right bottom" | "right top" | "start" | "start bottom" | "start top" | "top" | "top end" | "top left" | "top right" | "top start"—Overrides where the popover sits relative to its trigger.
shouldFlipbooleantrueWhether the popover may flip to the other side when it does not fit.

Slots: default.

PropTypeDefaultDescription
delaynumberHOVER_DELAY_MS
isDisabledboolean—

Slots: default.

PropTypeDefaultDescription
isDisabledboolean—Disables the trigger. Falls back to the state the dropdown root supplies.
type"button" | "reset" | "submit""button"Native button type.

Slots: default.