SpeedDial
A floating main button that expands a list of sub-actions, commonly used for quick actions like "New/Share"; aria-expanded stays in sync, clicking outside / Esc collapses it, with no orphan popups.
The demos add
style="position: static"to avoid fixed positioning affecting the page layout; in real use it is fixed to the bottom-right by default. The expansion direction of the sub-actions is controlled bydirection.
Expansion direction
direction supports up (default) / down / left / right; the first sub-action is always closest to the main button.
Directions: up / down / left / right
Cascade animation
On expansion, the sub-actions fade in one after another (transition-delay = index × 30ms per item) and disappear simultaneously on collapse. The animation is built in with no configuration needed; under prefers-reduced-motion the cascade delay is zeroed and transitions are disabled (everything appears at once, for accessibility). The demos above already use it when expanded.
Arc geometry expansion
geometry controls how the sub-actions are laid out: linear (default, chained layout) / circle (full circle, evenly spaced starting from the top) / semi-circle (a 180° half circle around the direction axis) / quarter-circle (a 90° arc whose starting quadrant follows direction: up=top-left, down=bottom-right, left=bottom-left, right=top-right). radius sets the arc radius in px (default 96, invalid values fall back to 96).
Angle rule: circle starts at the top and spaces evenly clockwise; semi-circle sweeps from "main direction − 90°" to "main direction + 90°" (up=upper half, down=lower half, left=left half, right=right half); quarter-circle is a 90° arc starting at the main direction (the first action stays closest to the main button). In arc mode the sub-actions no longer participate in the chained layout; the --cascade-i cascade and hide-label bubbles are unaffected, and under prefers-reduced-motion the arc transition is skipped (actions appear in place).
circle: full circle spaced from the top
semi-circle: half circle around the direction axis
quarter-circle: 90° quadrant follows direction (up=top-left / right=top-right)
radius: adjust the arc radius (circle)
Text-only actions
icon can be omitted to show only the label; for icon-only sub-actions use hide-label (see the next section).
Text only / icon only
Icon-only sub-actions (label on hover)
With hide-label: true a sub-action renders only its icon (a circular small button) and the label is visually hidden; hovering / keyboard focus reveals a text bubble (pure CSS transition, no JS overlay). The bubble position adapts to the expansion direction: up places it to the left of the action, down to the right, left/right above — always on the outer side of the action so it never covers neighboring actions. An action with hide-label but no renderable icon falls back to showing the label (a one-time console.warn in dev). Arrow-key roving navigation and the oas-select event are unaffected.
Icon-only sub-actions (label on hover)
Events
Clicking the main button to expand/collapse fires oas-open (detail: { open, reason }); clicking a sub-action fires oas-select (detail: { index, label }) and collapses automatically. reason marks the source of the open/collapse: toggle (main button click) / outside (outside click) / escape (Esc) / select (action selection) / hover (hover trigger).
Event feedback
Hover trigger
With trigger="hover", hovering the main button expands and moving away collapses after a 120ms grace period (moving back into the panel during the grace period keeps it open); touch devices automatically fall back to click behavior.
Hover trigger
Custom main button icon
The main button shows a default "+"; pass a custom icon through the default slot (it still rotates 45° when expanded).
Custom main button icon
Keyboard navigation
When expanded, the first sub-action is focused automatically (hover-triggered expansion does not steal focus); arrow keys move between actions (vertical expansion uses ArrowUp/ArrowDown, horizontal expansion uses ArrowLeft/ArrowRight, wrapping around), Home/End jump to the first/last, and Esc collapses and returns focus to the main button.
Keyboard navigation
Controlled open
The open attribute is controlled: setting/removing it externally expands/collapses, and the component's own clicks also sync the attribute and fire oas-open (clicking outside / Esc still collapses).
Controlled expansion
API
oas-speed-dial
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
actions | Sub-action JSON ([{ label, icon?, 'hide-label'? }]; hide-label: true renders the sub-action as a circular icon-only button with the label visually hidden, shown as a text bubble on hover/keyboard focus; falls back to showing the label when no renderable icon is provided) | string | [] |
direction | Expansion direction | string | up |
geometry | Expansion geometry: linear (default, chained layout) / circle (full circle, evenly spaced from the top) / semi-circle (half circle around the direction axis) / quarter-circle (90° arc whose starting quadrant follows direction: up=top-left, down=bottom-right, left=bottom-left, right=top-right) | string | linear |
open | Expanded state (controlled) | boolean | — |
radius | Arc radius in px (default 96; only effective when geometry is not linear; invalid values fall back to 96) | — | — |
trigger | Trigger mode: click (default) | hover (open on hover, collapse on leave with a 120ms grace period; falls back to click on touch devices) | string | click |
Events
| Event | Description |
|---|---|
oas-open | Expanded/collapsed, detail: { open, reason }; reason is toggle / outside / escape / select / hover (source marker, backward compatible with the open field) |
oas-select | A sub-action was selected, detail: { index, label }, then it collapses automatically |
Slots
| Name | Description |
|---|---|
| default | Custom icon for the main button; when provided it replaces the default + (45° rotation on expansion is preserved) |
CSS Variables
| CSS Variable | Default |
|---|---|
--oas-tooltip-bg | var(--oas-color-text-primary) |
--oas-tooltip-color | var(--oas-color-bg) |
SpeedDialAction fields:
| Field | Description | Type |
|---|---|---|
label | Action text | string |
icon | Icon name (a key of @oas-ui/icons built-in icon set) | string |
hide-label | When true, renders only the icon (a circular small button); the label is visually hidden and appears as a text bubble on hover / keyboard focus. Falls back to showing the label when no renderable icon is provided | boolean |
Behavior: clicking the main button toggles expansion (aria-expanded synced); trigger="hover" switches to hover trigger (touch devices fall back to click); clicking outside or pressing Esc collapses (after Esc, focus returns to the main button); clicking a sub-action collapses and fires oas-select; when expanded, the first sub-action is focused automatically (except for hover-triggered expansion) and arrow keys / Home / End navigate between actions; hide-label sub-actions keep an accessible name via aria-label. The default position is position: fixed; bottom/right, overridable. The document-level listener is only attached while expanded and disconnected during cleanup — no orphan popups.