Speed Dial
Floating action button that fans out secondary actions with staggered scale-in animation. Trigger is a primary icon-button.
<arc-speed-dial> Overview
>
SpeedDial is a floating action button (FAB) pattern that reveals a cluster of secondary action buttons when activated. The trigger button — rendered as a prominent icon-button — fans out child actions in a configurable direction (up, down, left, or right) with a staggered scale-in animation that gives each item a satisfying cascade entrance. This pattern is borrowed from Material Design but adapted to the ARC UI token system with accent-primary glow and surface-overlay backdrops.
SpeedDial is best suited for mobile and tablet interfaces where screen space is limited but quick access to two to five frequent actions is important. Common use cases include "compose" flows in messaging apps, quick-add actions in project management tools, and creation shortcuts in creative applications. The floating position ensures the trigger is always reachable without scrolling.
The component manages its own open/closed state and dispatches `arc-open`, `arc-close`, and `arc-action` events. The `arc-action` event includes the index of the selected item so your application can map each position to a specific handler. Clicking outside the expanded dial or pressing Escape closes it automatically. For a menu of text-labeled items rather than icon actions, consider DropdownMenu instead.Guidelines
When to use
- Limit secondary actions to two to five items for quick scanning
- Use recognizable icons for each action — tooltips can add context
- Place in bottom-right for right-handed thumb reach on mobile
- Use SpeedDial for creation or composition actions that benefit from quick access
- Close the dial after an action is selected to avoid visual clutter
When not to use
- Do not use SpeedDial for navigation — it is for actions, not route changes
- Do not add more than five actions — use a full menu or action sheet instead
- Do not place SpeedDial in a scrollable container — it should float above content
- Do not use text labels on the action items — icons only keeps the pattern compact
- Do not show SpeedDial on desktop when a toolbar with labeled buttons would be clearer
Features
- Floating action button with staggered scale-in animation
- Configurable fan direction: up, down, left, or right
- Fixed position in bottom-right or bottom-left corner
- `arc-open` and `arc-close` events for state tracking
- `arc-action` event with index of selected item
- Auto-close on outside click or Escape keypress
- Keyboard accessible with Tab and Enter activation
- Accent-primary glow on trigger and action items
- Token-driven theming via CSS custom properties
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<script type="module" src="@arclux/arc-ui"></script>
<arc-speed-dial direction="up" position="bottom-right" id="dial">
<arc-icon-button slot="action" name="pencil-simple" aria-label="Edit"></arc-icon-button>
<arc-icon-button slot="action" name="image" aria-label="Image"></arc-icon-button>
<arc-icon-button slot="action" name="share" aria-label="Share"></arc-icon-button>
</arc-speed-dial>
<script>
const dial = document.querySelector('#dial');
dial.addEventListener('arc-action', (e) => {
console.log('action index:', e.detail.index);
});
</script> import { SpeedDial, IconButton } from '@arclux/arc-ui-react';
export function QuickActions() {
return (
<SpeedDial
direction="up"
position="bottom-right"
onArcAction={(e) => console.log('action:', e.detail.index)}
>
<IconButton slot="action" icon="edit" aria-label="Edit" />
<IconButton slot="action" icon="image" aria-label="Image" />
<IconButton slot="action" icon="share" aria-label="Share" />
</SpeedDial>
);
} <script setup>
import { SpeedDial, IconButton } from '@arclux/arc-ui-vue';
function onAction(e) {
console.log('action:', e.detail.index);
}
</script>
<template>
<SpeedDial direction="up" position="bottom-right" @arc-action="onAction">
<IconButton slot="action" icon="edit" aria-label="Edit" />
<IconButton slot="action" icon="image" aria-label="Image" />
<IconButton slot="action" icon="share" aria-label="Share" />
</SpeedDial>
</template> <script>
import { SpeedDial, IconButton } from '@arclux/arc-ui-svelte';
</script>
<SpeedDial
direction="up"
position="bottom-right"
on:arc-action={(e) => console.log('action:', e.detail.index)}
>
<IconButton slot="action" icon="edit" aria-label="Edit" />
<IconButton slot="action" icon="image" aria-label="Image" />
<IconButton slot="action" icon="share" aria-label="Share" />
</SpeedDial> import { Component } from '@angular/core';
import { SpeedDial, IconButton } from '@arclux/arc-ui-angular';
@Component({
imports: [SpeedDial, IconButton],
template: `
<arc-speed-dial
direction="up"
position="bottom-right"
(arc-action)="onAction($event)"
>
<arc-icon-button slot="action" icon="edit" aria-label="Edit" />
<arc-icon-button slot="action" icon="image" aria-label="Image" />
<arc-icon-button slot="action" icon="share" aria-label="Share" />
</arc-speed-dial>
`,
})
export class QuickActionsComponent {
onAction(e: CustomEvent) {
console.log('action:', e.detail.index);
}
} import { SpeedDial, IconButton } from '@arclux/arc-ui-solid';
export function QuickActions() {
return (
<SpeedDial
direction="up"
position="bottom-right"
onArcAction={(e) => console.log('action:', e.detail.index)}
>
<IconButton slot="action" icon="edit" aria-label="Edit" />
<IconButton slot="action" icon="image" aria-label="Image" />
<IconButton slot="action" icon="share" aria-label="Share" />
</SpeedDial>
);
} import { SpeedDial, IconButton } from '@arclux/arc-ui-preact';
export function QuickActions() {
return (
<SpeedDial
direction="up"
position="bottom-right"
onArcAction={(e) => console.log('action:', e.detail.index)}
>
<IconButton slot="action" icon="edit" aria-label="Edit" />
<IconButton slot="action" icon="image" aria-label="Image" />
<IconButton slot="action" icon="share" aria-label="Share" />
</SpeedDial>
);
} API
-
openbooleanfalse - Whether the secondary actions are currently visible.
-
direction'up' | 'down' | 'left' | 'right''up' - The direction in which child actions fan out from the trigger.
-
position'bottom-right' | 'bottom-left''bottom-right' - Fixed viewport corner where the speed dial is anchored.
-
itemsArray<{icon: string, label: string, value?: string}>[] - Array of secondary action items to display when the speed dial is open. Each item needs an icon and label.
Events
-
arc-close - Fired when the speed dial collapses.
-
arc-open - Fired when the speed dial expands.
-
arc-action - Fired when a secondary action is selected with detail: { index }.
See Also
- Icon Button Compact button that renders an icon with optional text label, supporting ghost, secondary, and primary variants.
- Float Bar Viewport-bottom floating toolbar with surface-overlay background, backdrop blur, and spring easing. For bulk actions, unsaved-changes prompts.
- Dropdown Menu Menu dropdown triggered by a button with keyboard navigation.