Fab
fabuiFloating action button — a fixed or absolute positioned circular button for the primary screen action. Supports an icon (default), an extended label variant, mini/large sizes, four color variants, six anchor positions, and a disabled state.
Installation
$pnpm dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/fab.json$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/fab.json$yarn dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/fab.json$bunx shadcn-svelte@latest add https://uipkge.dev/r/svelte/fab.jsonManifest:
https://uipkge.dev/r/svelte/fab.jsonInstalls to:src/lib/components/ui/fab/Examples
Loading interactive previews…
Loading interactive previews…
Props
| Name | Type / Values | Default | Required |
|---|---|---|---|
variant | 'default''secondary''destructive''outline' | default | optional |
size | 'mini''default''large''extended' | default | optional |
position | 'bottom-right''bottom-left''top-right''top-left''bottom-center''inline' | bottom-right | optional |
labelLabel text — renders an extended FAB. Use children for an icon. | string | — | optional |
absoluteUse absolute instead of fixed positioning (for contained FABs). | boolean | false | optional |
ariaLabelAccessible label. Defaults to the label prop or 'Floating action'. | string | — | optional |
childemitting a <button> — the Svelte counterpart of React's `asChild`. | Snippet<[{ props: Record<string, unknown> }]> | — | optional |
refThe rendered <button>, via `bind:ref`. Stays null in `child` mode. | HTMLButtonElement | null | — | optional |
npm dependencies
Files installed (3)
src/lib/components/ui/fab/Fab.svelte2.2 kB
<script lang="ts" module> import type { Snippet } from 'svelte' import type { HTMLButtonAttributes } from 'svelte/elements' import type { FabVariants } from './fab.variants' export interface FabProps extends HTMLButtonAttributes { /** Label text — renders an extended FAB. Use children for an icon. */ label?: string variant?: FabVariants['variant'] size?: FabVariants['size'] position?: FabVariants['position'] /** Use absolute instead of fixed positioning (for contained FABs). */ absolute?: boolean /** Accessible label. Defaults to the label prop or 'Floating action'. */ ariaLabel?: string /** Render your own element with the FAB's props and styles instead of * emitting a <button> — the Svelte counterpart of React's `asChild`. */ child?: Snippet<[{ props: Record<string, unknown> }]> /** The rendered <button>, via `bind:ref`. Stays null in `child` mode. */ ref?: HTMLButtonElement | null } </script> <script lang="ts"> import { cn } from '$lib/utils' import { fabVariants } from './fab.variants' let { class: className, variant = 'default', size = 'default', position = 'bottom-right', absolute = false, label, disabled, ariaLabel, child, children, ref = $bindable(null), ...restProps }: FabProps = $props() const resolvedSize = $derived(label ? 'extended' : size) const mergedProps = $derived({ 'data-uipkge': '', 'data-slot': 'fab', 'data-variant': variant, 'data-size': resolvedSize, 'data-position': position, disabled, 'aria-label': ariaLabel || label || 'Floating action', class: cn( fabVariants({ variant, size: resolvedSize, position }), absolute && position !== 'inline' && 'absolute', className, ), ...restProps, }) </script> {#if child} {@render child({ props: mergedProps })} {:else} <!-- Capture-phase guard mirrors the Vue twin's disabled click guard. --> <button bind:this={ref} type="button" onclickcapture={(e) => { if (disabled) { e.preventDefault() e.stopPropagation() } }} {...mergedProps} > {@render children?.()} {#if label}<span class="pr-1">{label}</span>{/if} </button> {/if}src/lib/components/ui/fab/fab.variants.ts1.6 kB
import type { VariantProps } from 'class-variance-authority' import { cva } from 'class-variance-authority' export const fabVariants = cva( "inline-flex items-center justify-center gap-2 rounded-full font-medium shadow-lg transition-[color,background-color,box-shadow,transform,scale] duration-200 outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px] active:scale-95 touch-manipulation [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-6 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { default: 'bg-primary text-primary-foreground hover:bg-primary/90', secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', destructive: 'bg-destructive text-white hover:bg-destructive/90', outline: 'border bg-background text-foreground hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', }, size: { mini: "size-10 [&_svg:not([class*='size-'])]:size-4", default: 'size-14', large: "size-16 [&_svg:not([class*='size-'])]:size-7", extended: 'h-14 px-5', }, position: { 'bottom-right': 'fixed bottom-6 right-6', 'bottom-left': 'fixed bottom-6 left-6', 'top-right': 'fixed top-6 right-6', 'top-left': 'fixed top-6 left-6', 'bottom-center': 'fixed bottom-6 left-1/2 -translate-x-1/2', inline: '', }, }, defaultVariants: { variant: 'default', size: 'default', position: 'bottom-right', }, }, ) export type FabVariants = VariantProps<typeof fabVariants>src/lib/components/ui/fab/index.ts0.1 kB
export { default as Fab, type FabProps } from './Fab.svelte' export { fabVariants, type FabVariants } from './fab.variants'
Raw manifest:https://uipkge.dev/r/svelte/fab.json