Skip to content

← All components

Navigation and interaction

DropdownMenu

Roving-focus action menu with typeahead.

Live example

Usage

Each example includes the complete adapter-specific parameter reference. Copy it as a starting point, then remove options your use case does not need.

React

tsx
import { DropdownMenu } from "@cofob/design-system-react";

/**
 * Complete DropdownMenu parameter reference.
 * @param items
 *   type: readonly adapter-specific item[]
 *   required
 *   example: {items}
 * @param trigger
 *   type: ReactNode | Svelte snippet with trigger controls
 *   default: —
 *   example: <Button>Open</Button> / trigger snippet
 * @param triggerLabel/label
 *   type: string
 *   default: "Open menu"
 *   example: "Accessible label"
 * @param open/defaultOpen
 *   type: boolean; controlled or initial state
 *   default: false
 *   example: true
 * @param onOpenChange
 *   type: (open: boolean) => void
 *   default: —
 *   example: {handleOpenChange}
 * @param onSelect
 *   type: (item: MenuItem) => void
 *   default: —
 *   example: {handleSelect}
 * @param size
 *   type: "sm" | "md" | "lg" (plus heading sizes)
 *   default: "md"
 *   example: "md"
 * @param placement
 *   type: "top" | "right" | "bottom" | "left"
 *   default: "bottom"
 *   example: "bottom"
 * @param div attributes
 *   type: native element attributes
 *   default: —
 *   example: class / style / aria-* / data-*
 */
export function DropdownMenuExample() {
  return (
    <DropdownMenu trigger="Actions" items={items} />
  );
}

Svelte

svelte
<script lang="ts">
  import { DropdownMenu } from "@cofob/design-system-svelte";

  // Complete DropdownMenu parameter reference.
  // items
  //   type: readonly adapter-specific item[]
  //   required
  //   example: {items}
  // trigger
  //   type: ReactNode | Svelte snippet with trigger controls
  //   default: —
  //   example: <Button>Open</Button> / trigger snippet
  // triggerLabel/label
  //   type: string
  //   default: "Open menu"
  //   example: "Accessible label"
  // open/defaultOpen
  //   type: boolean; controlled or initial state
  //   default: false
  //   example: true
  // onOpenChange
  //   type: (open: boolean) => void
  //   default: —
  //   example: {handleOpenChange}
  // onSelect
  //   type: (item: MenuItem) => void
  //   default: —
  //   example: {handleSelect}
  // size
  //   type: "sm" | "md" | "lg" (plus heading sizes)
  //   default: "md"
  //   example: "md"
  // placement
  //   type: "top" | "right" | "bottom" | "left"
  //   default: "bottom"
  //   example: "bottom"
  // div attributes
  //   type: native element attributes
  //   default: —
  //   example: class / style / aria-* / data-*
</script>

<DropdownMenu label="Actions" items={items} />

HTML

html
<!--
  Complete DropdownMenu parameter reference.
  items
    type: readonly adapter-specific item[]
    required
    example: {items}
  trigger
    type: ReactNode | Svelte snippet with trigger controls
    default: —
    example: <Button>Open</Button> / trigger snippet
  triggerLabel/label
    type: string
    default: "Open menu"
    example: "Accessible label"
  open/defaultOpen
    type: boolean; controlled or initial state
    default: false
    example: true
  onOpenChange
    type: (open: boolean) => void
    default: —
    example: {handleOpenChange}
  onSelect
    type: (item: MenuItem) => void
    default: —
    example: {handleSelect}
  size
    type: "sm" | "md" | "lg" (plus heading sizes)
    default: "md"
    example: "md"
  placement
    type: "top" | "right" | "bottom" | "left"
    default: "bottom"
    example: "bottom"
  div attributes
    type: native element attributes
    default: —
    example: class / style / aria-* / data-*
-->
<div class="cf-menu" role="menu" data-cf-menu>…</div>

<script type="module">
  import { initDesignSystem } from "@cofob/design-system-css";

  const designSystem = initDesignSystem(document);
  window.addEventListener("pagehide", () => designSystem.destroy(), { once: true });
</script>

Parameters

Adapter differences are explicit. Native element attributes are forwarded in React and Svelte and can be written directly in HTML.

ParameterTypeDefaultAdaptersExampleDescription
itemsrequiredreadonly adapter-specific item[]requiredReact · Svelte · HTML{items}Structured items including IDs, labels, disabled state, and optional destinations.
triggerReactNode | Svelte snippet with trigger controlsReact · Svelte · HTML<Button>Open</Button> / trigger snippetTrigger content; Svelte snippets receive accessible trigger controls.
triggerLabel/labelstring"Open menu"React · Svelte · HTML"Accessible label"Accessible trigger name; adapter name differs.
open/defaultOpenboolean; controlled or initial statefalseReact · Svelte · HTMLtrueUse open/bind:open for controlled state or defaultOpen for initial state.
onOpenChange(open: boolean) => voidReact · Svelte · HTML{handleOpenChange}Reports every user-driven open state transition.
onSelect(item: MenuItem) => voidReact · Svelte · HTML{handleSelect}Runs when an enabled menu item is selected.
size"sm" | "md" | "lg" (plus heading sizes)"md"React · Svelte · HTML"md"Applies a design-system size token.
placement"top" | "right" | "bottom" | "left""bottom"React · Svelte · HTML"bottom"Preferred side; collision handling may choose a safer position.
div attributesnative element attributesReact · Svelte · HTMLclass / style / aria-* / data-*Forwards native class/style, accessibility, event, and data attributes to the root element.