Floating Action Button
Headless floating action button and speed-dial menu (WAI-ARIA menu button pattern).
| Package | @vizejs/ui/floating-action-button |
| Maturity | stable |
| Own the source | vize lib pull floating-action-button |
| Requires | collection, composite-navigation, context, controllable-state, dismissable-layer, id |
| Aliases | fab, floating action button, speed dial, float button |
| Covers | Material FAB, Material Speed Dial, WAI-ARIA Menu Button, Ant Design FloatButton |
Usage
import { FloatingActionButton, SpeedDial, SpeedDialRoot, SpeedDialAction, SpeedDialContent, SpeedDialTrigger } from "@vizejs/ui/floating-action-button";
Or copy the source into your project with vize lib pull floating-action-button (see Source Distribution).
API
FloatingActionButton
Source: src/families/actions/floating-action-button/floating-action-button.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
placement |
FloatingActionButtonPlacement |
"bottom-end" |
Viewport corner or edge the consumer anchors the button to, mirrored to data-placement. |
extended |
boolean |
false |
Whether the button shows a visible text label next to its icon. |
disabled |
boolean |
false |
Remove the button from activation and sequential focus. |
ariaLabel |
string |
undefined |
Accessible name. Required in practice for icon-only buttons. |
Events
| Event | Payload | Description |
|---|---|---|
click |
[nativeEvent: MouseEvent] |
Fired when the button is activated. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
FloatingActionButtonSlotState |
Icon and optional label. Receives placement and extended state. |
Exposed
| Member | Type | Description |
|---|---|---|
element |
HTMLButtonElement | null |
Rendered native button. |
focus |
(options?: FocusOptions) => void |
Move focus to the button. |
SpeedDial
Source: src/families/actions/floating-action-button/speed-dial-root.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
open |
boolean |
undefined |
Controlled open state. undefined selects uncontrolled behavior. |
defaultOpen |
boolean |
false |
Initial open state for uncontrolled use. |
direction |
SpeedDialDirection |
"up" |
Direction the actions fan out; also selects the arrow keys that move between actions. |
disabled |
boolean |
false |
Disable opening and every action. |
openOnHover |
boolean |
false |
Open while a mouse or pen hovers the speed dial and close when it leaves. |
closeOnSelect |
boolean |
true |
Close and return focus to the trigger after an action is selected. |
loop |
boolean |
true |
Whether arrow-key navigation wraps at the first and last action. |
Events
| Event | Payload | Description |
|---|---|---|
update:open |
[value: boolean] |
Fired when the speed dial requests a controlled open value. |
open-change |
[value: boolean, reason: SpeedDialChangeReason, nativeEvent: Event | null] |
Fired after any distinct open-state request, with its cause. |
select |
[event: SpeedDialSelectEvent] |
Fired when an action is selected. Call preventDefault() to keep the speed dial open. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
SpeedDialSlotState |
Trigger and content. Receives the open state and direction. |
Exposed
| Member | Type | Description |
|---|---|---|
close |
— | |
contentId |
— | |
direction |
— | |
disabled |
— | |
id |
— | |
open |
— | |
openAndFocus |
— | |
setOpen |
— | |
state |
— | |
triggerId |
— |
SpeedDialRoot
Source: src/families/actions/floating-action-button/speed-dial-root.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
open |
boolean |
undefined |
Controlled open state. undefined selects uncontrolled behavior. |
defaultOpen |
boolean |
false |
Initial open state for uncontrolled use. |
direction |
SpeedDialDirection |
"up" |
Direction the actions fan out; also selects the arrow keys that move between actions. |
disabled |
boolean |
false |
Disable opening and every action. |
openOnHover |
boolean |
false |
Open while a mouse or pen hovers the speed dial and close when it leaves. |
closeOnSelect |
boolean |
true |
Close and return focus to the trigger after an action is selected. |
loop |
boolean |
true |
Whether arrow-key navigation wraps at the first and last action. |
Events
| Event | Payload | Description |
|---|---|---|
update:open |
[value: boolean] |
Fired when the speed dial requests a controlled open value. |
open-change |
[value: boolean, reason: SpeedDialChangeReason, nativeEvent: Event | null] |
Fired after any distinct open-state request, with its cause. |
select |
[event: SpeedDialSelectEvent] |
Fired when an action is selected. Call preventDefault() to keep the speed dial open. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
SpeedDialSlotState |
Trigger and content. Receives the open state and direction. |
Exposed
| Member | Type | Description |
|---|---|---|
open |
boolean |
Whether the actions are visible. |
state |
SpeedDialState |
Stable state token for styling and tests. |
direction |
SpeedDialDirection |
Direction the actions fan out. |
disabled |
boolean |
Whether the whole speed dial is disabled. |
id |
string |
Root-owned base id. |
triggerId |
string |
Id wired to the trigger. |
contentId |
string |
Id wired to the action menu. |
setOpen |
(value: boolean, event?: Event | null) => boolean |
Request a specific open value. |
openAndFocus |
(event?: Event | null) => boolean |
Open and move focus to the first enabled action. |
close |
(options?: { readonly focusTrigger?: boolean }) => boolean |
Close and optionally return focus to the trigger. |
SpeedDialAction
Source: src/families/actions/floating-action-button/speed-dial-action.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value (required) |
string |
required |
Action identity reported by select. |
label (required) |
string |
required |
Accessible name. Speed-dial actions are usually icon-only, so the label is required and also offered to the slot for a visible tooltip. |
disabled |
boolean |
false |
Skip this action during navigation and ignore activation. |
Events
| Event | Payload | Description |
|---|---|---|
click |
[nativeEvent: MouseEvent] |
Fired before the speed dial handles the selection. Call preventDefault() to skip it. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
SpeedDialActionSlotState |
Action icon and optional visible label. |
Exposed
| Member | Type | Description |
|---|---|---|
element |
HTMLButtonElement | null |
Rendered native button. |
focus |
(options?: FocusOptions) => void |
Move focus to the action. |
SpeedDialContent
Source: src/families/actions/floating-action-button/speed-dial-content.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
ariaLabel |
string |
undefined |
Accessible name for the action menu. undefined labels it with the trigger. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
SpeedDialSlotState |
SpeedDialAction children. Receives the speed-dial state. |
Exposed
| Member | Type | Description |
|---|---|---|
open |
boolean |
Whether the actions are visible. |
state |
SpeedDialState |
Stable state token for styling and tests. |
direction |
SpeedDialDirection |
Direction the actions fan out. |
disabled |
boolean |
Whether the whole speed dial is disabled. |
element |
HTMLDivElement | null |
Rendered menu element. |
SpeedDialTrigger
Source: src/families/actions/floating-action-button/speed-dial-trigger.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
ariaLabel |
string |
undefined |
Accessible name, for example "Create". Required in practice for icon-only triggers. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
SpeedDialSlotState |
Trigger icon and label. Receives the speed-dial state. |
Exposed
| Member | Type | Description |
|---|---|---|
element |
HTMLButtonElement | null |
Rendered native button. |
focus |
(options?: FocusOptions) => void |
Move focus to the trigger. |
Behavior
Normative behavior for @vizejs/ui/floating-action-button. The speed dial follows the
WAI-ARIA APG Menu Button pattern.
Every row is proven by the named test.
| State x input | Observable outcome | Proven by |
|---|---|---|
floating-action-button.vue render and click |
Native labelled button with data-placement, data-extended, and a click event; positioning stays consumer-owned. |
floating action button renders a labelled native button with placement data |
| closed speed dial | Trigger has aria-haspopup="menu", aria-expanded="false", aria-controls; the role="menu" content is hidden and labelled by the trigger; actions are menuitems named by label. |
speed dial trigger follows the menu button pattern |
| pointer activation of the trigger | The menu opens and focus stays on the trigger; open-change reports "pointer". |
speed dial trigger follows the menu button pattern |
| Enter/Space on the trigger | The menu opens and focus moves to the first enabled action. | keyboard opening focuses the first action and arrows rove past disabled actions |
| arrows, Home, End inside the menu | Roving focus moves between enabled actions along the direction axis, skipping disabled actions and wrapping when loop. |
keyboard opening focuses the first action and arrows rove past disabled actions |
| Escape inside the menu | The menu closes and focus returns to the trigger. | keyboard opening focuses the first action and arrows rove past disabled actions |
arrow matching direction on the trigger |
Opens and focuses the first action; other arrows are ignored; horizontal directions set aria-orientation="horizontal". |
the direction arrow on the trigger opens into the menu |
| action activation | select fires with the value, the menu closes ("action"), and focus returns to the trigger. |
selecting an action emits select, closes, and restores trigger focus |
select handler calls preventDefault() |
The menu stays open. | preventDefault in select keeps the speed dial open |
| outside pointer-down or Tab | The menu closes through the dismissable layer or Tab handling. | outside pointer-down and Tab close the speed dial |
openOnHover |
Mouse/pen enter opens and leave closes; touch is ignored. | hover opening is opt-in and ignores touch |
disabled or controlled open |
Disabled roots never open; controlled roots emit update:open and follow the prop. |
disabled and controlled speed dials respect their owner |
| root expose | Ids, openAndFocus, close({ focusTrigger }), setOpen, state, and direction are available. |
root exposes ids and programmatic controls |
parts outside speed-dial-root.vue |
speed-dial-trigger.vue, speed-dial-content.vue, and speed-dial-action.vue throw VIZE_UI_CONTEXT_MISSING. |
speed-dial parts require a root |
| SSR / hydration | Closed markup is byte-identical and hydrates with zero warnings. | renders byte-identical closed speed-dial markup, hydrates speed-dial markup without diagnostics |
| public types | Placement, direction, change reasons, and required action labels are closed contracts. | src/families/actions/floating-action-button/floating-action-button.types.test-d.ts |
| DOM/SSR/Vapor | Every part compiles in each renderer lane. | scripts/check-renderers.ts |
| Target | Public contract |
|---|---|
| FAB | part="root", data-vize-ui="floating-action-button", data-placement, data-extended, data-disabled |
| Root | part="root", data-vize-ui="speed-dial-root", data-state, data-direction, data-disabled |
| Trigger | part="trigger", data-vize-ui="speed-dial-trigger", data-state |
| Content | part="content", data-vize-ui="speed-dial-content", data-state, data-direction |
| Action | part="action", data-vize-ui="speed-dial-action", data-value, data-active, data-disabled |
The family ships no stylesheet.