Phoundry UI

ButtonDropdown

Button that opens a dropdown menu on click, powered by the ContextMenu overlay system.

import { ButtonDropdown } from 'phoundry-ui';

Basic

Show code
<ButtonDropdown items={[
  { label: 'New File', action: () => {} },
  { label: 'Open...', action: () => {} },
  { type: 'separator' },
  { label: 'Save', action: () => {} },
]}>File</ButtonDropdown>

Variants

Show code
<ButtonDropdown variant="primary" items={items}>Primary</ButtonDropdown>
<ButtonDropdown variant="outline" items={items}>Outline</ButtonDropdown>
<ButtonDropdown variant="danger" items={items}>Danger</ButtonDropdown>

Sizes

Show code
<ButtonDropdown size="xs" items={items}>Extra Small</ButtonDropdown>
<ButtonDropdown size="sm" items={items}>Small</ButtonDropdown>
<ButtonDropdown size="md" items={items}>Medium</ButtonDropdown>
<ButtonDropdown size="lg" items={items}>Large</ButtonDropdown>

Split: sizes (singleClickAction)

Show code
<ButtonDropdown size="xs" variant="secondary" items={items} singleClickAction={onSave}>Label</ButtonDropdown>
<ButtonDropdown size="sm" variant="secondary" items={items} singleClickAction={onSave}>Label</ButtonDropdown>
<ButtonDropdown size="md" variant="secondary" items={items} singleClickAction={onSave}>Label</ButtonDropdown>
<ButtonDropdown size="lg" variant="secondary" items={items} singleClickAction={onSave}>Label</ButtonDropdown>

Split: variants (singleClickAction)

Show code
<ButtonDropdown variant="primary" items={items} singleClickAction={onPrimary}>Primary</ButtonDropdown>
<ButtonDropdown variant="secondary" items={items} singleClickAction={onAction}>Secondary</ButtonDropdown>
<ButtonDropdown variant="outline" items={items} singleClickAction={onAction}>Outline</ButtonDropdown>
<ButtonDropdown variant="danger" items={dangerItems} singleClickAction={onArchive}>Archive</ButtonDropdown>

Split: with icon (singleClickAction)

Show code
<ButtonDropdown
  icon={PhiIcons.edit}
  variant="primary"
  items={items}
  singleClickAction={() => saveNow()}
>Save</ButtonDropdown>
<ButtonDropdown
  icon={PhiIcons.launch}
  items={items}
  singleClickAction={openInEditor}
>Export</ButtonDropdown>

Without Arrow

Show code
<ButtonDropdown items={items} showArrow={false}>No Arrow</ButtonDropdown>

Placement

Show code
<ButtonDropdown items={items} placement="bottom-end">Bottom End</ButtonDropdown>
<ButtonDropdown items={items} placement="top-start">Top Start</ButtonDropdown>

Loading, disabled, tooltip

loading shows the same spinner as Button and blocks opening the menu. Icon-only triggers still need title for accessibility.

Show code
<ButtonDropdown items={items} loading>Saving…</ButtonDropdown>
<ButtonDropdown items={items} disabled>Unavailable</ButtonDropdown>
<ButtonDropdown items={items} iconOnly title="More actions" variant="ghost" />

Props

PropTypeDefaultDescription
items requiredMenuItem[] | () => MenuItem[]Menu items to display. Can be a static array or a function that returns items lazily.
placement PopoverPlacement'bottom-end'Where the dropdown opens relative to the button (top…right-end; see popover placement types).
showArrow booleantrueShow the chevron indicator. When singleClickAction is set, the chevron is always shown (this prop is effectively ignored in split mode).
singleClickAction (e: MouseEvent) => voidSplit control: the main label area runs this handler; the chevron segment opens the menu. Renders as two <button>s; href is ignored. element bind targets the left button.
...buttonProps Omit<ButtonProps, "onclick" | "href" | "target" | "rel">Same fields as Button (variant, size, icon, loading, disabled, active, title, noTooltip, class, element bind, etc.). href / link mode is not supported — use Button + separate menu if you need a link trigger.

Usage tips

  • Pass items as a function for lazy evaluation — useful when menu items depend on current state.
  • The dropdown uses the same ContextMenu overlay, so it requires provideContextMenu() (or setupOverlays()) in a parent layout.
  • Set showArrow={false} to hide the chevron for a cleaner look (not used when singleClickAction is set).