Installation
Nothing to add. This component ships as source in your download, so it is already in your project.
src/vui/dropdown-menu.tsx@viliha/vui-react/dropdown-menuThe exported names are at the top of that file. The import path is an alias the download's tsconfig.json points at src/vui/, so you can move that folder and change one line rather than every file that imports from it.
Usage
import {
Dropdown,
DropdownItem,
DropdownSeparator,
DropdownLabel,
StaticOverlays,
} from "@viliha/vui-react/dropdown-menu";Exports
Everything this family exports. They are read from the source, so this list is what the package actually ships.
| Prop | Type | Default |
|---|---|---|
| Dropdown | component | — |
| DropdownItem | component | — |
| DropdownSeparator | component | — |
| DropdownLabel | component | — |
| StaticOverlays | component | — |
Dropdown props
| Prop | Type | Default | What it does |
|---|---|---|---|
| label | string | — | |
| icon? | React.ReactNode | — | |
| align? | "start" | "end" | "start" | |
| children | React.ReactNode | ((close: () => void) => React.ReactNode) | — | The panel's contents. A function receives a `close` callback. |
| ariaLabel? | string | — | Accessible name for icon-only triggers (when label is empty). |
| active? | boolean | — | Render the trigger as a compact toolbar button (default) or a plain one. |
| labelClassName? | string | — | Extra classes on the label text — e.g. `hidden sm:inline` to hide it on mobile so the trigger collapses to an icon-only button. |
| trigger? | React.ReactNode | ((open: boolean) => React.ReactNode) | — | Replace the trigger's contents entirely. The default trigger is a toolbar button: an icon and a truncated label. An account menu is not that. |
| panelClassName? | string | — | Extra classes on the panel, for a menu that is not a list of plain items. |
| offset? | number | 0 | The gap between the trigger's bottom and the panel's top, in pixels. **Zero by default: a menu attaches to its trigger's border**. |
| placement? | "bottom" | "right" | "bottom" | Which side of the trigger the panel opens on. `"bottom"` by default. |
| title? | string | — | The trigger's native `title`, for a hover hint. `ariaLabel` names the control for assistive tech and is invisible to a mouse. |
| bare? | boolean | — | Whether the trigger renders as a button at all. A bare slot for an avatar row wants no chrome. |
| triggerClassName? | string | — | The bare trigger's own classes. `bare` says "not a toolbar button"; it cannot also know what the caller's trigger *is*. |
| staticId? | string | — | The id the static edition pairs this trigger with its panel by. Rendered as `data-vui-menu` on the trigger and used by `scripts/page-templates.mjs` to find the panel that belongs to it. |
| onOpenChange? | (open: boolean) => void | — | Called when the menu opens or closes. |
DropdownItem props
| Prop | Type | Default | What it does |
|---|---|---|---|
| children | React.ReactNode | — | |
| onSelect? | () => void | — | |
| checked? | boolean | — | |
| icon? | React.ReactNode | — | |
| disabled? | boolean | — | The action exists here but cannot be taken right now. |
| title? | string | — | Why it is unavailable. Pair it with `disabled` rather than leaving a reader to guess. |
| trailing? | React.ReactNode | — | A mark at the row's far edge, after the label. |
| variant? | "destructive" | — | `destructive` for a row that deletes, revokes or closes something. **The absence of this is why twelve kebab menus were hand-rolled**. |
DropdownLabel props
| Prop | Type | Default |
|---|---|---|
| children | React.ReactNode | — |
Customize
Every value this component draws comes from the theme: the colours, the radius, the control height and the type scale. Change a token and this moves with everything else, which is the difference between theming the product and overriding a component. See Theming for the token contract, and Swapping defaults for replacing the markup itself.