vwf .

Developer Docs

Quick reference guides with props tables, usage examples, and best practices for rapid development

Components/Docs/FloatingActionButton

FloatingActionButton

FloatingActionButton

A prominent button for primary actions like creating services. Fixed position with gradient background, responsive positioning, and multiple variants including expandable action menus.

Quick Example

The FAB is currently visible in the bottom-right corner of this page! Try hovering over it.

Basic FAB (always shown):

📋 Props Reference

FloatingActionButton accepts the following props:

PropTypeDefaultDescription
onclickFunctionundefinedClick handler for the button
iconstring'add'Oracle JET icon name (without oj-ux-ico- prefix)
labelstringundefinedOptional label text (shown on hover, changes to pill shape)
positionstring'bottom-right'Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'
hideOnMobilebooleanfalseHide on mobile devices (useful for mobile-only navigation patterns)
classstring''Additional CSS classes

🚀 Basic Usage

Simple and labeled FAB examples:

Simple FAB

import { FloatingActionButton } from 'shared-components/ui/FloatingActionButton.js';

FloatingActionButton({
  icon: 'add',
  onclick: () => router.navigate('/services/new')
})

With Label (Pill Shape)

FloatingActionButton({
  icon: 'add-circle',
  label: 'Create Service',
  onclick: () => router.navigate('/services/new')
})

📍 Position Variants

FAB supports 4 corner positions with responsive sizing:

Bottom Right (Default)

FloatingActionButton({
  position: 'bottom-right',
  icon: 'add',
  onclick: handleCreate
})

Bottom Left

FloatingActionButton({
  position: 'bottom-left',
  icon: 'help',
  onclick: showHelp
})

Top Right

FloatingActionButton({
  position: 'top-right',
  icon: 'settings',
  onclick: openSettings
})

Top Left

FloatingActionButton({
  position: 'top-left',
  icon: 'menu',
  onclick: toggleMenu
})

Responsive Positioning

FAB automatically adjusts distance from edges:

✓Mobile: 80px from edges (above navigation bars)

✓Desktop: 32px from edges (comfortable spacing)

📱 Hide on Mobile

Use hideOnMobile when you have mobile-specific navigation (like bottom tabs):

FloatingActionButton({
  icon: 'add',
  hideOnMobile: true,
  onclick: createService
})
// FAB hidden on mobile, shown on desktop

🔧 Pre-configured Components

VWF provides 2 ready-to-use FAB components:

1. CreateServiceFAB

Pre-configured for service creation navigation:

import { CreateServiceFAB } from 'shared-components/ui/FloatingActionButton.js';

// Simple drop-in component
CreateServiceFAB()

// Automatically navigates to /services/new
// Shows "Create Service" label on hover

2. QuickActionsFAB

Expandable menu with multiple quick actions:

Click the + button to expand:

import { QuickActionsFAB } from 'shared-components/ui/FloatingActionButton.js';

// Expandable action menu
QuickActionsFAB()

// Built-in actions:
// - Offer Service
// - Request Help
// - Create Event

🎨 Custom Icons

Use any Oracle JET icon (omit oj-ux-ico- prefix):

// Common FAB icons
FloatingActionButton({ icon: 'add' })           // Plus icon
FloatingActionButton({ icon: 'add-circle' })    // Plus in circle
FloatingActionButton({ icon: 'edit' })          // Edit/pencil
FloatingActionButton({ icon: 'compose' })       // Compose message
FloatingActionButton({ icon: 'camera' })        // Take photo
FloatingActionButton({ icon: 'help' })          // Help/question
FloatingActionButton({ icon: 'filter' })        // Filter options

✅ Best Practices

Follow these guidelines for effective FAB usage:

✓ Do This

✓Use for primary creation actions

✓Limit to one FAB per page

✓Use bottom-right for consistency

✓Hide on mobile if you have bottom tabs

✓Use descriptive aria-label

✓Use QuickActionsFAB for multiple actions

✓Keep labels short (2-3 words)

✗ Avoid This

✗Use multiple FABs on same page

✗Use for secondary actions

✗Block important content

✗Use for destructive actions (delete)

✗Forget mobile positioning (covers nav)

✗Use without click handler

✗Use long labels (pill gets too wide)

⭐ Key Features

FloatingActionButton provides these essential capabilities:

★

Fixed Positioning

Always visible, 4 corner positions available

★

Gradient Background

Sunrise to sunset gradient with shadow effects

★

Responsive Sizing

Automatic spacing adjusts for mobile vs desktop

★

Smooth Animations

Scale on hover, active states, label expansion

★

Shape Morphing

Circle without label, pill shape with label

★

Pre-configured Variants

CreateServiceFAB and QuickActionsFAB ready to use

💼 Common Use Cases

Real-world examples of FAB usage:

1. Service Creation

import { CreateServiceFAB } from 'shared-components/ui/FloatingActionButton.js';

// In your services list page
export const ServicesPage = () => {
  return div(
    { class: 'container mx-auto p-4' },

    h1('My Services'),

    // Service list content
    ...services.val.map(service => ServiceCard(service)),

    // FAB for quick creation
    CreateServiceFAB()
  );
};

2. Quick Actions Menu

import { QuickActionsFAB } from 'shared-components/ui/FloatingActionButton.js';

// In your dashboard
export const Dashboard = () => {
  return div(
    { class: 'container mx-auto p-4' },

    DashboardContent(),

    // Expandable quick actions
    QuickActionsFAB()
  );
};

3. Custom Action

FloatingActionButton({
  icon: 'filter',
  label: 'Filter',
  position: 'top-right',
  onclick: () => {
    showFilterModal.val = true;
  }
})

4. Chat/Message Compose

FloatingActionButton({
  icon: 'compose',
  label: 'New Message',
  onclick: () => router.navigate('/messages/new'),
  'aria-label': 'Compose new message'
})

5. Add Photo

FloatingActionButton({
  icon: 'camera',
  onclick: () => {
    fileInput.click();
  },
  'aria-label': 'Add photo'
})

📲 Mobile Considerations

Important considerations for mobile usage:

Bottom Navigation Conflict

If your app has bottom navigation, FAB will cover it on mobile:

// Option 1: Hide on mobile
FloatingActionButton({
  icon: 'add',
  hideOnMobile: true
})

// Option 2: Add to bottom nav instead
BottomNav({
  items: [
    { icon: 'home', label: 'Home' },
    { icon: 'add', label: 'Create' },  // FAB action in nav
    { icon: 'profile', label: 'Profile' }
  ]
})

Thumb Zone

FAB is positioned at 80px from bottom on mobile - perfect for thumb reach:

// Automatic responsive positioning
// Mobile: bottom-[80px] (above bottom nav, in thumb zone)
// Desktop: bottom-[32px] (comfortable desktop spacing)

♿ Accessibility

Ensuring FAB is accessible to all users:

Always Provide aria-label

FloatingActionButton({
  icon: 'add',
  onclick: createService,
  'aria-label': 'Create new service'  // Descriptive label for screen readers
})

Keyboard Navigation

FAB is fully keyboard accessible:

✓Tab: Focus the FAB

✓Enter/Space: Activate the button

✓Focus visible with ring styles

🛠️ Custom Quick Actions Menu

Create your own expandable FAB with custom actions:

const isOpen = van.state(false);

const customActions = [
  { icon: 'document', label: 'New Document', action: () => createDoc() },
  { icon: 'folder', label: 'New Folder', action: () => createFolder() },
  { icon: 'link', label: 'Import Link', action: () => importLink() }
];

div(
  { class: 'fixed bottom-20 right-4 md:bottom-8 md:right-8 z-40' },

  // Action menu
  () => isOpen.val && div(
    { class: 'absolute bottom-16 right-0 flex flex-col gap-2 mb-2' },
    ...customActions.map(action =>
      button({
        class: 'flex items-center gap-3 px-4 py-2 bg-white rounded-full shadow-lg',
        onclick: () => {
          isOpen.val = false;
          action.action();
        }
      },
        span({ class: `oj-ux-ico-${action.icon}` }),
        span(action.label)
      )
    )
  ),

  // Main FAB
  FloatingActionButton({
    icon: 'plus',
    onclick: () => isOpen.val = !isOpen.val,
    class: () => isOpen.val && 'rotate-45'
  })
)

🔗 Integration Patterns

Common integration patterns with other VWF features:

With Router (Navigation)

import { router } from 'utils/fileBasedRouterV2.js';

FloatingActionButton({
  icon: 'add',
  onclick: () => router.navigate('/services/new')
})

With Modal (Show Dialog)

const showCreateModal = van.state(false);

div(
  FloatingActionButton({
    icon: 'plus',
    onclick: () => showCreateModal.val = true
  }),

  () => showCreateModal.val ? CreateServiceModal({
    isOpen: showCreateModal,
    onClose: () => showCreateModal.val = false
  }) : ''
)

With Toast (Feedback)

FloatingActionButton({
  icon: 'add',
  onclick: () => {
    showToast('Opening service form...', 'info');
    router.navigate('/services/new');
  }
})

Explore More Components

Browse other component categories