Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Mobile

FAB

Mobile

FAB React component for Tailwind CSS v4

Bottom Tab BarHaptic Button
Live props
Content
label
Layout
layout
position
side
offset16px
safeArea
Appearance
extended
variant
tone
color
size
radius
State
defaultOpen
Behavior
hideOnScroll
hideOnKeyboard
scrim
closeOnAction
haptics
shortcut
Code
import { Fab } from "@/components/ui/fab"

<Fab />
  1. Home
  2. Components
  3. Mobile
  4. FAB
Pro

FAB React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React floating action button (FAB) for a phone screen's main action, with a labeled or radial speed dial and a label that folds on scroll.

Tap the round button in the thumb zone. Without actions it runs its one action; with actions the page dims and a speed dial rises from it, nearest action first, while the plus turns into an x and the phone ticks once. Vertical dials show a label chip beside each round action and the whole row is the target; radial dials fly small round actions out on an arc (a half arc when centered) and show each label as a tooltip on hover, focus or a long press. Tap an action to run it and close the dial, tap the dimmed page or the x to close without choosing. With a label the button starts extended ("Add"); scroll down and it folds to the icon, scroll up and the label comes back. With hideOnScroll it slides out while you scroll down and returns when you scroll up, never while it is open or focused, and it steps aside while the on-screen keyboard is up. It sits above the bottom tab bar and the sticky buy bar and clears the home indicator (once, never twice). Keyboard: Enter, Space or ArrowUp open the dial and focus the nearest action; ArrowUp / ArrowDown move (radial dials also Left / Right), Home / End jump, Enter or Space runs, Escape closes and returns focus to the button, Tab closes and moves on. shortcut opens it from anywhere. With a mouse the button and every action tint on hover; while the button shows only its icon (or has a shortcut) hovering or focusing it shows its name and the shortcut in a tooltip, and a long press shows it on touch.

FAB is a Pro React component in the React mobile components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add fab, together with Tooltip, Navigation, useScrollState, useKeyboardInset, useShortcut and 5 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add fab

FAB is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import Fab from @/components/ui/fab.

import { FileText, Handshake, StickyNote, UserPlus } from "lucide-react"
import { Fab, type FabAction } from "@/components/ui/fab"

export function ClientsFab({ onCreate }: { onCreate: (kind: string) => void }) {
  const actions: FabAction[] = [
    { id: "client", label: "New client", icon: <UserPlus />, onSelect: () => onCreate("client") },
    { id: "invoice", label: "New invoice", icon: <FileText />, onSelect: () => onCreate("invoice") },
    { id: "quote", label: "New quote", icon: <Handshake />, href: "/quotes/new" },
    { id: "note", label: "Note", icon: <StickyNote />, onSelect: () => onCreate("note") },
  ]
  return (
    <Fab
      label="Add"
      actions={actions}
      shortcut="n"
      labels={{ open: "Show create actions", close: "Hide create actions", menu: "Create" }}
    />
  )
}

Props

  • labeldefault ""
    string

    The extended label ("Add") and the button's accessible name. Without it the name is labels.open / labels.close with actions, else labels.action.

  • icondefault "<Plus />"
    ReactNode

    The button's icon. Unsized svgs follow the size (20 / 24 / 28px).

  • openIcon
    ReactNode

    Shown while the dial is open. Default: the plus turns 45 degrees into an x; a custom icon cross-fades to an <X />.

  • actionsdefault "[]"
    FabAction[]

    The speed dial, 2 to 6 entries: { id, label, icon, onSelect?, href?, tone?: "neutral" | "danger", disabled? }. Actions with href render a NavLink and close the dial. Without actions the FAB is a plain button (onClick).

  • onClick
    (event: MouseEvent<HTMLButtonElement>) => void

    The action when there is no dial. With actions it runs before the dial toggles; preventDefault keeps it closed.

  • layoutdefault "vertical"
    "vertical" | "radial"

    vertical: a column of labeled actions above the button (Material). radial: small round actions on a quarter arc around it (a half arc when centered), labels as tooltips.

  • extendeddefault "auto"
    "auto" | "always" | "never"

    Needs a label. auto: the label shows at the top of the page and while scrolling up, and folds to the icon while scrolling down. always keeps it, never shows the icon alone.

  • variantdefault "solid"
    "solid" | "soft" | "surface"

    solid: filled with the tone. soft: a tinted fill that stays opaque over the page. surface: a popover-colored button with a toned icon (Material 3 surface FAB).

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Semantic color. neutral is black in light mode and white in dark mode; brand is for the one hero action of a marketplace.

  • colordefault ""
    string

    Any CSS color. Replaces the tone; text on a solid fill turns black or white by lightness.

  • sizedefault "md"
    "sm" | "md" | "lg"

    Button 48 / 56 / 64px with 20 / 24 / 28px icons and a 14 / 15 / 16px label; dial actions 40 / 44 / 48px (sm grows to 44px on touch).

  • radiusdefault "full"
    "none" | "sm" | "md" | "lg" | "full"

    Corner shape, 0 / 12 / 16 / 20px at md and scaled per size; full is a circle, a pill when extended. Dial actions follow.

  • defaultOpendefault false
    boolean

    Starts with the dial open. Control it with open and onOpenChange.

  • open
    boolean

    The dial's open state, controlled.

  • onOpenChange
    (open: boolean) => void

    Runs when the dial opens or closes.

  • positiondefault "fixed"
    "fixed" | "sticky" | "absolute"

    fixed to the viewport (the app default); sticky to the bottom of its scroll container (render it as the last child: phone frames, panels); absolute inside a relative container (a map, a card).

  • sidedefault "end"
    "end" | "start" | "center"

    Logical side, so end is right in left-to-right pages and left in right-to-left ones. center opens a half-arc dial.

  • offsetdefault 16
    number

    px from the side and from what is below it: the bottom tab bar (--bottom-bar-offset), the sticky buy bar (--cta-bar-offset) and the home indicator.

  • hideOnScrolldefault false
    boolean

    Slides out while you scroll down, following the finger, and comes back when you scroll up. Never while open or focused.

  • hideOnKeyboarddefault true
    boolean

    Steps aside while the on-screen keyboard is open (and closes an open dial), so it never covers the field you type in.

  • scrimdefault true
    boolean

    Dims and softly blurs the page behind an open dial; a tap on it closes. Without it a press anywhere else closes.

  • closeOnActiondefault true
    boolean

    Closes the dial after an action runs. Actions with href always close.

  • hapticsdefault true
    boolean

    A light tick when the dial opens and when an action runs, on touch only (never for a mouse click or a key).

  • shortcutdefault ""
    string

    A key combo that opens the dial (or runs the action), e.g. "n" or "mod+shift+n". Shown in the button's tooltip and set as aria-keyshortcuts.

  • safeAreadefault true
    boolean

    Keeps clear of the home indicator and the notch with env(safe-area-inset-*). The insets are 0 on desktops.

  • scrollTarget
    HTMLElement | Window | RefObject<HTMLElement | null> | null

    What scrolls, for extended="auto" and hideOnScroll. Default: the nearest ScrollContainerProvider, else (sticky and absolute) the scroll parent, else the window.

  • linkComponent
    (props: LinkComponentProps) => ReactNode

    The router link for actions with href. Default: the LinkProvider's component, else a plain <a>.

  • labelsdefault "DEFAULT_FAB_LABELS"
    Partial<FabLabels>

    Screen reader strings: open "Open actions", close "Close actions", menu "Actions", action "Create". Pass only the keys you translate.

  • classNames
    Partial<Record<"scrim" | "actions" | "action" | "actionLabel" | "actionIcon" | "trigger" | "icon" | "label", string>>

    Extra classes for the inner parts. className goes on the positioned root.

Parts

  • FabAction

    type

    One speed dial action: id, label, icon, onSelect or href (a router link that closes the dial), tone ("neutral" | "danger") and disabled.

  • DEFAULT_FAB_LABELS

    constant

    The English screen reader strings: open "Open actions", close "Close actions", menu "Actions", action "Create".

Examples

Radial dial over a map

Three round actions fly out on a quarter arc; hover, focus or long-press one for its label.

Compose button

No actions: the FAB is the action. The label shows at the top and folds while you read down the inbox.

Above a bottom tab bar

Both sticky in one scroller: the tab bar writes --bottom-bar-offset and the FAB sits on top of it.

Sizes and radius

48, 56 and 64px, as a circle or a rounded square.

Surface variant in brand

The Material 3 surface FAB: a popover-colored button with a brand icon and label for the marketplace's one hero action.

Centered half-arc dial

A centered FAB spreads its actions over a half arc; arrow keys move left and right along it.

Hide on scroll

Slides away while you scroll down and returns on scroll up, never while open or focused.

Dependencies

motionlucide-reacttooltipnavigationuse-scroll-stateuse-keyboard-insetuse-shortcutuse-controllable-statehapticsmotiontonesui-config

Files

  • components/ui/fab.tsx

FAQ

Is the React FAB component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install FAB?

Run npx wingo-ui@latest add fab. It also adds the Wingo UI items it builds on (Tooltip, Navigation, useScrollState, useKeyboardInset, useShortcut and 5 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/fab.

See also

Bottom Tab BarSticky CTA BarBack To TopAction SheetuseScrollStatehookHapticslib

More React mobile components

Haptic ButtonInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker Wheel
All 15 React mobile components

Articles using this component

  • React Floating Action Button: Speed Dial and Safe Areas

    Mobile UI in React · Oct 16, 2026 · 9 min read

  • React Bottom Navigation Bar in Next.js: Safe Areas, Badges

    Mobile UI in React · Oct 9, 2026 · 8 min read

  • Tailwind Safe Area Insets: Bottom Bars, FABs and Toasts

    Mobile UI in React · Oct 9, 2026 · 12 min read

PreviousBottom Tab BarNext Haptic Button
16:40

Clients

12 clients · 3 overdue

$195,266
Active
TI
Tech Solutions Inc.
Chicago·Active
$12,480.00
SL
Summit Logistics
Denver·Active
$48,920.50
CG
Construct Group
Dallas·Active
$103,400.00
DC
Dental Art Clinic
Miami·Active
$5,600.00
NS
Northwind Studio
Chicago·Active
$9,870.00
PS
Pixel Studio
San Francisco·Active
$3,450.00
Overdue
GP
Greenleaf Pharmacy
Portland·Overdue
$7,315.20
WB
Westside Books
Portland·Overdue
$2,980.75
Prospects and negotiations
GR
Green House Realty
Seattle·Negotiating
$0.00
CC
Carter Consulting
Austin·Prospect
$0.00
B
Bistro 21
New York·Prospect
$0.00
Inactive
OB
Old Mill Bakery
Nashville·Inactive
$1,250.00

Tap the button for the dial; scroll the list and the label folds away

hideOnScroll off · hideOnKeyboard on · hidden false · offset 16px · safeArea on

extended auto · scrim on · closeOnAction on · haptics on · shortcut none