Skip to content

FloatButton ​

A circular action button fixed to the bottom-right corner of the page by default, for quick actions like "New" and "Feedback"; supports a badge, a custom icon, extended text and link mode.

The demos add style="position: relative; inset: 0" to keep them in the document flow while establishing a positioning context (group/menu expansion layers anchor relative to the main button); in real use it is fixed to the bottom-right by default, adjustable via the --oas-float-button-bottom / --oas-float-button-right CSS variables (default var(--oas-space-6), i.e. 32px).

Basic usage ​

With badge

Without badge ​

Without badge

Custom icon ​

Custom icon

✎

Shape ​

shape offers two shapes: circle (default, round) / square (capsule rounded rectangle).

Shape

✎✎

Type ​

type controls visual intensity: primary (default, solid primary with white text) / default (weakened: light background with dark text).

Type

✎✎

Extended text ​

Writing text into the default slot turns the button into a horizontal capsule (icon + text in a row).

Extended text

NewFeedback

Size ​

size has five tiers: xs (24px) / sm (32px) / md (40px) / lg (default 48px) / xl (56px).

Size

Disabled ​

disabled disables the button: not clickable, oas-click not fired, with weakened styles (translucent + disabled palette).

Disabled

✎New

Dragging and magnetic snapping ​

draggable enables drag positioning: press and drag to move the button freely (free positioning under fixed, clamped inside the viewport so it never slides out). A displacement over 4px counts as a drag and releasing does not fire oas-click; within 4px it counts as a click and fires normally. Disabled state is not draggable.

magnetic works together with draggable: on release the button snaps to the nearest edge of the chosen axis — x snaps to the left/right edges, y to the top/bottom edges, with a transition (prefers-reduced-motion snaps instantly). The three buttons below are fixed to the bottom-right corner by default; press and drag to try it (the magnetic ones snap to the edge on release).

Draggable (press and drag the button within the container)

Draggable + magnetic x (snaps to the nearest left/right edge)

Draggable + magnetic y (snaps to the nearest top/bottom edge)

href renders an <a> element (native link semantics and keyboard reachability), optionally with target; when disabled it degrades to a non-clickable <span>.

Link

✈Open example

Group mode ​

mode="group": a main button with stacked child buttons. Child buttons come in two channels:

actions data channel (recommended, standard circular child buttons) — rendered by the component inside the shadow root, immune to host-page CSS overrides:

  • Action item: { label, icon?, href?, target?, badge? } — items with href render as link children (with rel="noopener noreferrer" added automatically), mutually exclusive with clickable actions
  • label serves both as the accessible name and as the bubble hint on hover / keyboard focus
  • badge: dot status dot / number (capped at 99+ above 99)
  • Selecting an action item dispatches oas-select (detail: { index, label, href? }) and collapses the group, restoring focus to the main button

slot="action" custom channel — the host provides the child elements itself, for cases the data channel cannot express: custom visuals, oas-button/custom components, framework-reactive content, per-item behaviors:

  • Children get a default circular form, but it is carried via ::slotted and can be overridden by host-page global styles (e.g. a reset's button { background: transparent }); use actions when the form must be guaranteed, or let the child carry its own visuals (e.g. oas-button)
  • Supports the label (bubble text) and badge attributes
  • The two channels are mutually exclusive; when both are provided actions wins

Shared behavior:

  • expand-direction expanding direction: up (default) / down / left / right; horizontal directions mirror automatically in RTL
  • trigger activation: click (default) / hover (falls back to click on touch screens) / manual (controlled attribute only)
  • expanded controlled expanded state + oas-expand-change event (detail: { expanded })
  • Esc collapses and refocuses the main button; an outside click collapses without refocusing

Group (actions-rendered children; see the message feedback on child click)

+

Expand event (click the main button to toggle; oas-expand-change message feedback)

+

Controlled expansion (trigger=manual: the component never toggles by itself; the host flips the expanded attribute, no event dispatched)

+

Custom children (slot custom channel: your own elements/components/framework-reactive content)

+📄

mode="menu": clicking the main button pops up an action menu (data-driven by the actions JSON; closed by Esc / outside click):

  • Action item: { label, icon?, href?, target?, badge? } — items with href render as link menu items (mutually exclusive with clickable actions)
  • badge: dot status dot / number (capped at 99+ above 99)
  • Selecting an item dispatches oas-select (detail: { index, label, href? }) and collapses automatically
  • Only vertical directions are supported: expand-direction="up" (default) / "down"
  • Keyboard reachable: opening focuses the first item, arrow keys navigate cyclically, Esc closes and refocuses the main button

Menu (click the main button to pop up; see the message feedback on selection)

☰

Badges: status dot and number capping ​

badge supports three values: a number (corner badge), dot (status dot, no number), or arbitrary text; pure numbers above 99 are capped to 99+ automatically. Group child buttons (badge attribute) and menu action items (badge field) follow the same rule.

Badge capping and status dot

Event feedback ​

Clicking dispatches oas-click (bubbles + composed), and detail.originalEvent is the native click event.

Click event

Hover hint ​

The hover hint is composed by the host: wrap oas-float-button with oas-tooltip — the tooltip treats its first child as the trigger anchor and shows the hint on hover / keyboard focus (in real fixed bottom-right usage this works the same, as the tooltip positions against the anchor). The component ships no built-in tooltip prop, keeping the FAB single-responsibility and the hint logic in the composition layer.

Tooltip composition

✎

API ​

oas-float-button ​

Attributes ​

AttributeDescriptionTypeDefault
actionsAction items JSON shared by group/menu [{label, icon?, href?, target?, badge?}] — group renders circular child buttons inside the shadow root (recommended, immune to host-page CSS overrides), menu renders an action menu; items with href render as links (rel="noopener noreferrer" added automatically); selecting emits oas-select and collapses with focus restored to the main buttonstring[]
aria-labelAccessible name: overrides the built-in label when set explicitly (icon-only defaults to locale "Quick actions"; extended text lets the visible text win)——
badgeBadge number at the top-right cornerstring—
disabledDisabled: not clickable, oas-click not fired, weakened styles; in href mode it degrades to a non-clickable spanboolean—
draggableDraggable: press and drag to move the button (free positioning under fixed, clamped inside the viewport); displacement > 4px counts as a drag, in which case releasing does not fire oas-click (within the threshold it fires normally)boolean—
expand-directionExpand direction: up (default) / down / left / right; horizontal directions mirror automatically in RTLstringup
expandedgroup/menu expanded state: the component writes the attribute itself and emits oas-expand-change on gesture expand/collapse; with trigger="manual" it is fully controlled — the component never toggles itself and the host adds/removes the attributeboolean—
hrefLink URL: when set, renders an <a> element (native link semantics and keyboard reachability) instead of a button; degrades to a span when disabledstring—
magneticMagnetic: x snaps to the nearest left/right edge, y to the nearest top/bottom edge, with a transition on release; empty means no snapping (requires draggable)string—
modeMode: single (default) / group (main button + slotted actions expand vertically) / menu (actions JSON popup menu)stringsingle
shapeShape: circle (default, round) / square (capsule rounded rectangle)stringcircle
sizeSize tier: xs (24px) / small (32px) / medium (40px) / large (default 48px) / xl (56px); sm/md/lg are accepted aliases; invalid values fall back to large with a warningstringlarge
targetLink open mode (effective in href mode, e.g. _blank)string—
triggerExpand trigger: click (default) / hover (debounced with grace period) / manual (fully controlled; outside click and Esc do not auto-collapse)stringclick
typeVisual intensity: primary (default, solid primary) / default (weakened: light background with dark text)stringprimary

Events ​

EventDescription
oas-clickClicked, detail: { originalEvent }
oas-expand-changeEmitted on expand/collapse, detail: { expanded }; the component writes expanded back in sync (with trigger="manual" the host writes it back)
oas-selectAn action item was selected in group/menu mode, detail: { index, label, href? }; the component then requests a collapse (emitting oas-expand-change; with trigger="manual" the host removes expanded to finish)

Slots ​

NameDescription
defaultExtended text: writing text into the default slot turns the button into a horizontal capsule (icon + text in a row)
actiongroup-mode child buttons (custom channel, mutually exclusive with actions): self-filled light DOM elements/components (button/a/oas-button/custom elements) for cases the data channel cannot express — custom visuals, framework-reactive content, per-item behaviors; supports label (bubble text) and badge; the default circular form is carried via ::slotted (best-effort, can be overridden by host-page CSS) — use actions for guaranteed standard circular buttons; clicking collapses the group and restores focus to the main button
iconIcon (default +)

CSS Variables ​

CSS VariableDefault
--oas-float-button-action-sizecalc(var(--oas-float-button-size) - var(--oas-space-2))
--oas-float-button-bottomvar(--oas-space-6)
--oas-float-button-rightvar(--oas-space-6)
--oas-float-button-sizevar(--oas-control-height-xl)
--oas-tooltip-bgvar(--oas-color-text-primary)
--oas-tooltip-colorvar(--oas-color-bg)

The default position is position: fixed; bottom/right, adjustable via the --oas-float-button-bottom / --oas-float-button-right CSS variables (default var(--oas-space-6)).

Released under the MIT OR Apache-2.0 License.