Dropdown
The panel a select, a combobox and a menu all open in.
A dropdown is the panel that opens under a trigger, together with the code that places it. It carries no meaning of its own about what the panel is for.
Three things open in it, and those are what to choose between:
| Opens in a dropdown | What it does | Guidance |
|---|---|---|
| Select | Stores a value, one or several | select |
| Combobox | Stores a value, and filters the list as you type | combobox |
| Menu | Runs a command, such as navigating or signing out | menu |
Decide which of the three you need before reaching for this page. Menu holds that choice.
Why this page exists
ui/Dropdown is one of the most-used library modules in the product and carried no guidance. The only prose about it was filed under the name menu, and that page said the construct did not exist.
The Storybook stories show a container rather than a menu. Alongside With Icons and With Submenu, it ships With Checkboxes, With Checkboxes On The Left and With Radio Group.
Anatomy
| Part | Description |
|---|---|
| Trigger | A select box, an avatar, an icon button, or a kebab (⋯). It belongs to the component inside the panel, not to the panel |
| Panel | The popover container: surface, border, radius, shadow |
| Item | One row. Whether a row is an option, a result or a command is decided by the component inside |
| Group header (optional) | A label above a run of related items |
| Divider (optional) | A separator between groups of items |
| Submenu (optional) | A nested panel opened from a single item |
Rules
- Match the trigger to the behaviour. A select box means the panel stores a value. An avatar, icon button or kebab means it runs commands. Never use a select box for a panel whose items run commands.
- Put selection controls on the left. The component allows either side, and ships a story for each, so the system picks one. The trailing checkmark is the exception, and it belongs to single select.
- Keep group headers unselectable. A header that responds to activation is an item, and it should look like one.
- Dim disabled items rather than hiding them. A list that changes shape between visits cannot be learned.
What this page cannot tell you
Whether ui/Select and ui/Combobox are built on ui/Dropdown. The React source is in appsignal-server, and only the construct inventory is joined into this site. The inventory records modules, class roots and stories, not which module imports which. What is established is that the three share a panel, and that Dropdown is general enough to carry any of them.
When a submenu is warranted. The code ships a With Submenu story. The design library draws no submenu, so there is no guidance here on nesting depth or touch behaviour.
What happens when the panel runs out of room. A Positioning story exists, so placement is the component's responsibility, but neither side documents the behaviour at the edge of the viewport.
Where it exists
ui-dropdown--basic-dropdown (open it in Storybook). One of 11 stories. Drag the bottom edge to resize. ⚠️ The frame renders the component at the frame's own width, so in a narrow pane you are seeing a narrow rendering rather than the canonical one.| axis | value |
|---|---|
| React module | yes — shared UI library |
| React tier | library |
| CSS class | .c-dropdown |
| CSS files | dropdown.css |
| Storybook | yes |
| Figma | not mapped |
| Uses in product | 64 |
| Uses in admin | 0 |
| Seen as | css-class-attribute, jsx-tag |
| Join provenance | inferred:kebab |
An empty cell above is a measurement, not an omission: every axis is printed whether or not it is populated. What each one costs is on /gaps.md, linked from the axis name wherever this page has a gap.
Members
A member is attached to its parent at module scope, so it is imported through the parent and versioned with it. Members have no page of their own: they declare no CSS class, carry no story and join no Figma set, and their uses are counted against the parent rather than separately.
None. Nothing is attached to this component as a member.