# Fab Floating Action Button (FAB) component for primary actions with expandable menu options. Each example uses a container with `position: relative` and explicit height to position the FAB correctly. ## Tag `Fab` ## Props | Prop | Type | Default | Description | | :----------- | :-------------------------------------- | :--------------- | :----------------------------------------------- | | `icon` | `string \| VNode \| Signal` | `-` | Main FAB icon | | `label` | `string \| VNode \| Signal` | `-` | Text label for main button | | `actions` | `Array \| Signal` | `[]` | Array of action buttons that expand from FAB | | `position` | `string` | `'bottom-6 right-6'` | CSS position classes (e.g., 'bottom-6 left-6') | | `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) | ### Action Structure | Property | Type | Description | | :---------- | :--------------------------- | :----------------------------------------------- | | `label` | `string \| VNode` | Label text shown next to action button | | `icon` | `string \| VNode` | Icon for the action button | | `onclick` | `function` | Click handler | | `class` | `string` | Additional CSS classes for the action button | ## Live Examples ### Basic FAB

Live Demo

```javascript const BasicDemo = () => { return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Fab({ icon: '➕', actions: [ { icon: '📝', label: 'New Note', onclick: () => Toast('Create note', 'alert-info', 2000) }, { icon: '📷', label: 'Take Photo', onclick: () => Toast('Open camera', 'alert-info', 2000) }, { icon: '📎', label: 'Attach File', onclick: () => Toast('Attach file', 'alert-info', 2000) } ] }) ]); }; Mount(BasicDemo, '#demo-basic'); ``` ### With Label

Live Demo

```javascript const LabelDemo = () => { return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Fab({ label: 'Create', icon: '✨', actions: [ { icon: '📝', label: 'Document', onclick: () => Toast('New document', 'alert-success', 2000) }, { icon: '🎨', label: 'Design', onclick: () => Toast('New design', 'alert-success', 2000) }, { icon: '📊', label: 'Spreadsheet', onclick: () => Toast('New spreadsheet', 'alert-success', 2000) } ] }) ]); }; Mount(LabelDemo, '#demo-label'); ``` ### Different Positions

Live Demo

```javascript const PositionsDemo = () => { const position = $('bottom-6 right-6'); return Div({ class: 'relative h-[500px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Div({ class: 'absolute top-4 left-4 z-20 bg-base-200 p-2 rounded-lg shadow' }, [ Select({ value: position, options: [ { value: 'bottom-6 right-6', label: 'Bottom Right' }, { value: 'bottom-6 left-6', label: 'Bottom Left' }, { value: 'top-6 right-6', label: 'Top Right' }, { value: 'top-6 left-6', label: 'Top Left' } ], onchange: (e) => position(e.target.value) }) ]), Div({ class: 'absolute inset-0 flex items-center justify-center text-sm opacity-50 pointer-events-none' }, [ 'FAB position changes relative to this container' ]), Fab({ position: () => position(), icon: '🧭', actions: [ { icon: '⬅️', label: 'Bottom Left', onclick: () => position('bottom-6 left-6') }, { icon: '➡️', label: 'Bottom Right', onclick: () => position('bottom-6 right-6') }, { icon: '⬆️', label: 'Top Right', onclick: () => position('top-6 right-6') }, { icon: '⬇️', label: 'Top Left', onclick: () => position('top-6 left-6') } ] }) ]); }; Mount(PositionsDemo, '#demo-positions'); ``` ### Color Variants

Live Demo

```javascript const ColorsDemo = () => { const variant = $('primary'); const variants = { primary: { class: 'btn-primary', icon: '🔵' }, secondary: { class: 'btn-secondary', icon: '🟣' }, accent: { class: 'btn-accent', icon: '🔴' }, info: { class: 'btn-info', icon: '🔷' }, success: { class: 'btn-success', icon: '🟢' }, warning: { class: 'btn-warning', icon: '🟡' }, error: { class: 'btn-error', icon: '🔴' } }; return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Div({ class: 'absolute top-4 left-4 z-20 bg-base-200 p-2 rounded-lg shadow' }, [ Select({ value: variant, options: Object.keys(variants).map(v => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) })), onchange: (e) => variant(e.target.value) }) ]), Fab({ class: variants[variant()].class, icon: variants[variant()].icon, actions: [ { icon: '📝', label: 'Action 1', onclick: () => Toast('Action 1', 'alert-info', 2000) }, { icon: '🎨', label: 'Action 2', onclick: () => Toast('Action 2', 'alert-info', 2000) }, { icon: '⚙️', label: 'Action 3', onclick: () => Toast('Action 3', 'alert-info', 2000) } ] }) ]); }; Mount(ColorsDemo, '#demo-colors'); ``` ### Reactive Actions

Live Demo

```javascript const ReactiveActions = () => { const count = $(0); const actions = () => [ { icon: '🔢', label: `Count: ${count()}`, onclick: () => {} }, { icon: '➕', label: 'Increment', onclick: () => count(count() + 1) }, { icon: '➖', label: 'Decrement', onclick: () => count(count() - 1) }, { icon: '🔄', label: 'Reset', onclick: () => count(0) } ]; return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Fab({ icon: () => count() > 0 ? `🔢 ${count()}` : '🎛️', actions: actions }) ]); }; Mount(ReactiveActions, '#demo-reactive'); ``` ### Document Actions

Live Demo

```javascript const DocumentActions = () => { const saved = $(false); const handleSave = () => { saved(true); Toast('Document saved!', 'alert-success', 2000); setTimeout(() => saved(false), 3000); }; return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Div({ class: 'absolute inset-0 flex flex-col items-center justify-center' }, [ Div({ class: 'text-6xl mb-4' }, '📄'), Div({ class: 'text-sm opacity-70' }, 'Untitled Document'), () => saved() ? Div({ class: 'mt-4' }, Alert({ type: 'success', message: '✓ Saved successfully' })) : null ]), Fab({ icon: '✏️', actions: [ { icon: '💾', label: 'Save', onclick: handleSave }, { icon: '📋', label: 'Copy', onclick: () => Toast('Copied!', 'alert-info', 2000) }, { icon: '✂️', label: 'Cut', onclick: () => Toast('Cut!', 'alert-info', 2000) }, { icon: '📎', label: 'Share', onclick: () => Toast('Share dialog', 'alert-info', 2000) } ] }) ]); }; Mount(DocumentActions, '#demo-document'); ``` ### Messaging FAB

Live Demo

```javascript const MessagingFAB = () => { const unread = $(3); return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Div({ class: 'absolute inset-0 flex flex-col items-center justify-center' }, [ Div({ class: 'text-6xl mb-4' }, '💬'), Div({ class: 'text-sm opacity-70' }, 'Messages'), () => unread() > 0 ? Div({ class: 'badge badge-error mt-2' }, `${unread()} unread`) : null ]), Fab({ icon: () => `💬${unread() > 0 ? ` ${unread()}` : ''}`, class: 'btn-primary', actions: [ { icon: '👤', label: 'New Message', onclick: () => Toast('Start new conversation', 'alert-info', 2000) }, { icon: '👥', label: 'Group Chat', onclick: () => Toast('Create group', 'alert-info', 2000) }, { icon: '📞', label: 'Voice Call', onclick: () => Toast('Start call', 'alert-info', 2000) }, { icon: '📹', label: 'Video Call', onclick: () => Toast('Start video call', 'alert-info', 2000) }, { icon: '🔔', label: () => `Mark as read (${unread()})`, onclick: () => { unread(0); Toast('All messages read', 'alert-success', 2000); } } ] }) ]); }; Mount(MessagingFAB, '#demo-messaging'); ``` ### Flower Style FAB

Live Demo

```javascript const FlowerDemo = () => { return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Div({ class: 'absolute inset-0 flex items-center justify-center text-sm opacity-50' }, [ 'Flower style FAB (quarter circle arrangement)' ]), Fab({ icon: '🌸', class: 'fab-flower', actions: [ { icon: '📷', label: 'Camera', onclick: () => Toast('Camera', 'alert-info', 2000) }, { icon: '🎨', label: 'Gallery', onclick: () => Toast('Gallery', 'alert-info', 2000) }, { icon: '🎤', label: 'Voice', onclick: () => Toast('Voice', 'alert-info', 2000) }, { icon: '📍', label: 'Location', onclick: () => Toast('Location', 'alert-info', 2000) } ] }) ]); }; Mount(FlowerDemo, '#demo-flower'); ``` ### All Variants

Live Demo

```javascript const VariantsDemo = () => { const actions = [ { icon: '⭐', label: 'Favorite', onclick: () => Toast('Favorited', 'alert-info', 2000) }, { icon: '🔔', label: 'Remind', onclick: () => Toast('Reminder set', 'alert-info', 2000) }, { icon: '📅', label: 'Schedule', onclick: () => Toast('Scheduled', 'alert-info', 2000) } ]; return Div({ class: 'relative h-[400px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ Div({ class: 'grid grid-cols-2 gap-4 p-4 h-full' }, [ Div({ class: 'relative border rounded-lg bg-base-200' }, [ Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Primary'), Fab({ icon: '🔵', class: 'btn-primary', actions, position: 'bottom-6 left-6' }) ]), Div({ class: 'relative border rounded-lg bg-base-200' }, [ Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Secondary'), Fab({ icon: '🟣', class: 'btn-secondary', actions, position: 'bottom-6 right-6' }) ]), Div({ class: 'relative border rounded-lg bg-base-200' }, [ Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Accent'), Fab({ icon: '🔴', class: 'btn-accent', actions, position: 'top-6 left-6' }) ]), Div({ class: 'relative border rounded-lg bg-base-200' }, [ Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Success'), Fab({ icon: '🟢', class: 'btn-success', actions, position: 'top-6 right-6' }) ]) ]) ]); }; Mount(VariantsDemo, '#demo-variants'); ```