Marble UI
← Components

Floating Action Button

Preview: Single

Floating action button. With `actions` it becomes a speed dial: the main button toggles a stack of labelled mini-buttons (aria-expanded). `fixed` pins it to the viewport, otherwise to the nearest positioned parent.

Import

import { FloatButton } from '@marbleui/ui'

Props

<FloatButton>

PropTypeDefaultDescription
icon *requiredReactNode—
label *requiredstring—
actionsFloatAction[]—
classNamestring—
fixedboolean—
onPress() => void—
position'bottom-right' | 'bottom-left' | 'top-right''bottom-right'

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: React Aria Button. Follow the primitive's docs for the full keyboard map.

Usage notes

Round button pinned to a corner for a screen’s main action; with actions it becomes a speed dial. For actions on a selection use ActionBar.

<FloatButton fixed label="New message" icon={<PlusIcon />} onPress={compose} />
<FloatButton label="Create" icon={<PlusIcon />} actions={[
  { id: 'doc', label: 'Document', icon: <FileIcon />, onPress: newDoc },
  { id: 'task', label: 'Task', icon: <CheckIcon />, onPress: newTask },
]} />
  • Without fixed it’s absolute, so the parent needs relative. position: bottom-right (default), bottom-left, top-right.
  • label is required: it names the icon-only button and is its tooltip.
  • With actions, onPress is ignored: the button toggles the dial (aria-expanded) and turns its icon 45°, so a plus reads as a close mark.
  • The dial closes on Escape (focus returns to the main button), an outside click, or a pick. The main button comes first in tab order, then the mini-buttons.
Example source · show
import { FloatButton } from './float-button'

const I = ({ d }: { d: string }) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden><path d={d} /></svg>
const Stage = ({ children }: { children: React.ReactNode }) => <div className="relative h-72 w-96 overflow-hidden rounded-xl border border-border bg-surface-muted">{children}</div>
export const styles = {
  Single: () => <Stage><FloatButton label="New message" icon={<I d="M12 5v14M5 12h14" />} /></Stage>,
  'Speed dial': () => <Stage><FloatButton label="Create" icon={<I d="M12 5v14M5 12h14" />} actions={[{ id: 'doc', label: 'Document', icon: <I d="M14 2H6v20h12V6zM14 2v4h4" /> }, { id: 'img', label: 'Image', icon: <I d="M3 3h18v18H3zM8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4M21 15l-5-5L5 21" /> }, { id: 'task', label: 'Task', icon: <I d="m5 12 5 5L20 7" /> }]} /></Stage>,
}

Source: packages/ui/src/float-button/float-button.tsx

Catalog

Category
inputs
Priority
Extra
Primitive
composed
React Aria
Button
Base UI
Button