Skip to content

FloatButton

FloatButton component for placing a floating button in the screen corner with support for slots, badges, tooltips and complete accessibility according to W3C standards.

Usage examples

Basic FloatButton

Simple floating button

Floating button preview

vue
<script setup>
import { PlusIcon } from '@heroicons/vue/24/outline'
</script>

<template>
  <SuFloatButton 
    :icon="'PlusIcon'"
    label="Add an element"
    position="right"
  />
</template>

With badge

Button with notification badge

Button with badge "3"

vue
<script setup>
import { ChatBubbleLeftIcon } from '@heroicons/vue/24/outline'
</script>

<template>
  <SuFloatButton 
    :icon="'ChatBubbleLeftIcon'"
    label="Messages"
    badge="3"
    position="right"
  />
</template>

Floating button as link

Link to external help

vue
<script setup>
import { QuestionMarkCircleIcon } from '@heroicons/vue/24/outline'
</script>

<template>
  <SuFloatButton 
    :icon="'QuestionMarkCircleIcon'"
    label="Help center"
    href="https://help.example.com"
    target="_blank"
    position="left"
  />
</template>

With ButtonGroup

Button with action group

Main button with secondary actions

vue
<script setup>
import { PlusIcon, CogIcon, HeartIcon, ShareIcon } from '@heroicons/vue/24/outline'
</script>

<template>
  <SuFloatButton 
    :icon="'PlusIcon'"
    label="Quick actions"
    position="right"
  >
    <SuButtonGroup gap="sm" variant="secondary" size="sm">
      <SuButton :icon="'CogIcon'" iconDisplay="only" aria-label="Settings" />
      <SuButton :icon="'HeartIcon'" iconDisplay="only" aria-label="Favorites" />
      <SuButton :icon="'ShareIcon'" iconDisplay="only" aria-label="Share" />
    </SuButtonGroup>
  </SuFloatButton>
</template>

API

Props

PropTypeDefaultDescription
position'left' | 'right''right'Floating button position
offset{ x?: number, y?: number }{ x: 24, y: 24 }Custom offset in pixels
size'sm' | 'md' | 'lg''md'Floating button size
iconComponentundefinedButton icon
labelstringundefinedButton label (displayed in tooltip)
hrefstringundefinedDestination URL (transforms to link)
target'_blank' | '_self' | '_parent' | '_top'undefinedLink target
relstringundefinedLink relation
badgestringundefinedBadge text displayed in top right
variant'primary' | 'secondary' | 'outline' | 'ghost''primary'Button variant
disabledbooleanfalseDisable the button
loadingbooleanfalseLoading state
zIndexnumber1000Button z-index
hideOnScrollbooleanfalseHide when scrolling down
showTooltipbooleantrueShow tooltip on hover
tooltipPosition'top' | 'bottom' | 'left' | 'right''left'Tooltip position

Events

EventTypeDescription
@click(event: MouseEvent) => voidEmitted when button is clicked
@focus(event: FocusEvent) => voidEmitted when button receives focus
@blur(event: FocusEvent) => voidEmitted when button loses focus

Slots

SlotDescription
defaultContent displayed above the button (LinkGroup or ButtonGroup)

Advanced features

🎯 Smart positioning

The component automatically handles:

  • Fixed position: Stays visible during scroll
  • Custom offset: Precise position adjustment
  • Safe areas: iPhone notch support (safe-area-inset)
  • Responsive: Automatic mobile adjustment

🏷️ Notification badge

The badge provides visual feedback for:

  • Notifications: Number of unread messages
  • Alerts: Status indicators
  • Counters: Pending items
  • Animation: Pulse to attract attention

💬 Smart tooltip

The tooltip automatically adapts:

  • Position: Adjusts based on button position
  • Content: Uses label as text
  • Accessibility: Linked via aria-describedby
  • Responsive: Adapted size on mobile

📱 Responsive behavior

  • Mobile: Automatically reduced offsets (16px instead of 24px)
  • Safe areas: Support for notches and navigation bars
  • Tooltip: Reduced size on small screens
  • Slot: Maximum width adapted to screen

Accessibility

The FloatButton component follows WCAG 2.1 AA standards:

✅ Accessibility features

  • Keyboard navigation: Support for Enter and Space keys
  • Visible focus: Clear and contrasted focus indicator
  • Accessible labels: Automatic or custom aria-label
  • Linked tooltips: Association via aria-describedby
  • Accessible badges: Voice announcement of badge content
  • Contrast: WCAG AA compliant contrast ratios (4.5:1 minimum)
  • Minimum sizes: Respects minimum touch target sizes (44px)
  • Dark mode: Automatically adapted contrast
  • High contrast: Support for prefers-contrast: high
  • Reduced motion: Respects prefers-reduced-motion

🎯 Best practices

vue
<template>
  <!-- Floating button with accessible label -->
  <SuFloatButton 
    :icon="'PlusIcon'"
    label="Add a new element"
    position="right"
  />

  <!-- External link with security -->
  <SuFloatButton 
    :icon="'QuestionMarkCircleIcon'"
    label="Open help center"
    href="https://help.example.com"
    target="_blank"
    position="left"
  />

  <!-- With badge and description -->
  <SuFloatButton 
    :icon="'ChatBubbleLeftIcon'"
    label="Unread messages"
    badge="5"
    aria-describedby="messages-help"
  />
  <div id="messages-help" class="sr-only">
    You have 5 unread messages
  </div>

  <!-- With slot and appropriate role -->
  <SuFloatButton 
    :icon="'CogIcon'"
    label="Action menu"
    role="button"
    aria-haspopup="true"
  >
    <ButtonGroup role="menu" aria-label="Quick actions">
      <Button role="menuitem">Action 1</Button>
      <Button role="menuitem">Action 2</Button>
    </ButtonGroup>
  </SuFloatButton>
</template>

Keyboard navigation

KeyAction
TabNavigate to/from floating button
EnterActivate button or follow link
SpaceActivate button
EscapeClose slot (if open)

Common use cases

💬 Support and help

  • Live chat: Quick access to customer support
  • Help center: Link to documentation
  • Contact: Phone, email, form

➕ Primary actions

  • Add: Create a new element
  • Compose: Write a message, article
  • Create: New project, document

🔧 Tools and settings

  • Settings: Quick access to preferences
  • Tools: Advanced features
  • Shortcuts: Frequent actions

📱 Mobile navigation

  • Menu: Main navigation on mobile
  • Back to top: Scroll to top of page
  • Share: Quick content sharing

Best practices

✅ Do

  • Use descriptive label for accessibility
  • Limit to 1-2 floating buttons per page
  • Place primary actions on the right (more accessible)
  • Use badges for important notifications
  • Test on mobile and with screen readers

❌ Don't

  • Hide essential features in the slot
  • Use too many floating buttons (visual pollution)
  • Forget the label for accessibility
  • Place button over important content
  • Use excessive animations

Performance

🚀 Built-in optimizations

  • Passive events: Optimized scroll listeners
  • CSS transitions: Hardware-accelerated animations
  • Lazy rendering: Slot rendered only when needed
  • Automatic cleanup: Event listener removal

📊 Minimal impact

  • Generated CSS: ~2KB gzipped
  • JavaScript: Lightweight and optimized logic
  • Rendering: No impact on page performance
  • Accessibility: No performance compromises

Publié sous licence MIT.