Floating UI Svelte
Please note this section will be the future home of the Floating UI Svelte integrateion guide, an upcoming open-source library from Skeleton Labs. While this project is in development, we have provided several Svelte-specific components to act as temporary substitutions. Note that these components will remain available until our next major release (Skeleton v4.x). However, the goal will be to replace these with Floating UI Svelte as soon as possible.
Components
Popover
Triggers an anchored popover when you click the trigger element. View API Reference.
<script lang="ts"> import { Popover } from '@skeletonlabs/skeleton-svelte'; import IconX from 'lucide-svelte/icons/x';
let openState = $state(false);
function popoverClose() { openState = false; }</script>
<Popover bind:open={openState} positioning={{ placement: 'top' }} triggerBase="btn preset-tonal" contentBase="card bg-surface-200-800 p-4 space-y-4 max-w-[320px]" arrow arrowBackground="!bg-surface-200 dark:!bg-surface-800"> {#snippet trigger()}Click Me{/snippet} {#snippet content()} <header class="flex justify-between"> <p class="font-bold type-scale-5">Popover Example</p> <button class="btn-icon hover:preset-tonal" onclick={popoverClose}><IconX /></button> </header> <article> <p class="opacity-60"> This will display a basic popover with a header and body. This also includes a title, description, and close button. </p> </article> {/snippet}</Popover>
// Use the following settings to populate the `positioning` component property.// See also: https://floating-ui.com/docs/middleware
export type PositioningOptions = { /** Whether the popover should be hidden when the reference element is detached */ hideWhenDetached?: boolean; /** The strategy to use for positioning */ strategy?: "absolute" | "fixed"; /** The initial placement of the floating element */ placement?: "top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end"; /** The offset of the floating element */ offset?: { mainAxis?: number; crossAxis?: number; }; /** The main axis offset or gap between the reference and floating elements */ gutter?: number; /** The secondary axis offset or gap between the reference and floating elements */ shift?: number; /** The virtual padding around the viewport edges to check for overflow */ overflowPadding?: number; /** The minimum padding between the arrow and the floating element's corner. */ arrowPadding?: number; /** Whether to flip the placement */ flip?: boolean | Placement[]; /** Whether the popover should slide when it overflows. */ slide?: boolean; /** Whether the floating element can overlap the reference element */ overlap?: boolean; /** Whether to make the floating element same width as the reference element */ sameWidth?: boolean; /** Whether the popover should fit the viewport. */ fitViewport?: boolean; /** The overflow boundary of the reference element */ boundary?: () => Boundary; /** Options to activate auto-update listeners */ listeners?: boolean | AutoUpdateOptions; /** Function called when the placement is computed */ onComplete?(data: ComputePositionReturn): void; /** Function called when the floating element is positioned or not */ onPositioned?(data: { placed: boolean; }): void; /** Function that returns the anchor rect */ getAnchorRect?: (element: HTMLElement | VirtualElement | null) => AnchorRect | null; /** A callback that will be called when the popover needs to calculate its position. */ updatePosition?: (data: { updatePosition: () => Promise<void>; }) => void | Promise<void>;}
Tooltip
Triggers an anchored popover when you hover the trigger element. View API Reference.
<script lang="ts"> import { Tooltip } from '@skeletonlabs/skeleton-svelte'; let openState = $state(false);</script>
<Tooltip bind:open={openState} positioning={{ placement: 'top' }} triggerBase="underline" contentBase="card preset-filled p-4" openDelay={200}> {#snippet trigger()}Hover Me{/snippet} {#snippet content()}This is a tooltip.{/snippet}</Tooltip>
// Use the following settings to populate the `positioning` component property.// See also: https://floating-ui.com/docs/middleware
export type PositioningOptions = { /** Whether the popover should be hidden when the reference element is detached */ hideWhenDetached?: boolean; /** The strategy to use for positioning */ strategy?: "absolute" | "fixed"; /** The initial placement of the floating element */ placement?: "top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end"; /** The offset of the floating element */ offset?: { mainAxis?: number; crossAxis?: number; }; /** The main axis offset or gap between the reference and floating elements */ gutter?: number; /** The secondary axis offset or gap between the reference and floating elements */ shift?: number; /** The virtual padding around the viewport edges to check for overflow */ overflowPadding?: number; /** The minimum padding between the arrow and the floating element's corner. */ arrowPadding?: number; /** Whether to flip the placement */ flip?: boolean | Placement[]; /** Whether the popover should slide when it overflows. */ slide?: boolean; /** Whether the floating element can overlap the reference element */ overlap?: boolean; /** Whether to make the floating element same width as the reference element */ sameWidth?: boolean; /** Whether the popover should fit the viewport. */ fitViewport?: boolean; /** The overflow boundary of the reference element */ boundary?: () => Boundary; /** Options to activate auto-update listeners */ listeners?: boolean | AutoUpdateOptions; /** Function called when the placement is computed */ onComplete?(data: ComputePositionReturn): void; /** Function called when the floating element is positioned or not */ onPositioned?(data: { placed: boolean; }): void; /** Function that returns the anchor rect */ getAnchorRect?: (element: HTMLElement | VirtualElement | null) => AnchorRect | null; /** A callback that will be called when the popover needs to calculate its position. */ updatePosition?: (data: { updatePosition: () => Promise<void>; }) => void | Promise<void>;}
Combobox
Triggers an anchored popover list when you tap the arrow. Includes auto-suggestion via typeahead. View API Reference.
<script lang="ts"> import { Combobox } from '@skeletonlabs/skeleton-svelte';
interface ComboxData { label: string; value: string; }
const comboboxData: ComboxData[] = [ { label: 'United States', value: 'US' }, { label: 'Germany', value: 'DE' }, { label: 'Japan', value: 'JP' } ];
let selectedCountry = $state(['US']);</script>
<Combobox data={comboboxData} bind:value={selectedCountry} label="Select Country" placeholder="Select..." />
Modal
Generate modals or dialogs that require a user’s immediate attention. View API Reference.
<script lang="ts"> import { Modal } from '@skeletonlabs/skeleton-svelte';
let openState = $state(false);
function modalClose() { openState = false; }</script>
<Modal bind:open={openState} triggerBase="btn preset-tonal" contentBase="card bg-surface-100-900 p-4 space-y-4 shadow-xl max-w-screen-sm" backdropClasses="backdrop-blur-sm"> {#snippet trigger()}Open Modal{/snippet} {#snippet content()} <header class="flex justify-between"> <h2 class="h2">Modal Example</h2> </header> <article> <p class="opacity-60"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Nam, ab adipisci. Libero cumque sunt quis error veritatis amet, expedita voluptatem. Quos repudiandae consequuntur voluptatem et dicta quas, reprehenderit velit excepturi? </p> </article> <footer class="flex justify-end gap-4"> <button type="button" class="btn preset-tonal" onclick={modalClose}>Cancel</button> <button type="button" class="btn preset-filled" onclick={modalClose}>Confirm</button> </footer> {/snippet}</Modal>
<script lang="ts"> import { Modal } from '@skeletonlabs/skeleton-svelte';
let drawerState = $state(false);
function drawerClose() { drawerState = false; }</script>
<!--Tips for Drawer modals:- Use `contentBase` to set styles, incuding height/width- Set justify-start to align to the left- Clear the align and padding styles- Use `positionerClasses` to set the- Set transition.x values that matches content width in pixels-->
<Modal bind:open={drawerState} triggerBase="btn preset-tonal" contentBase="bg-surface-100-900 p-4 space-y-4 shadow-xl w-[480px] h-screen" positionerJustify="justify-start" positionerAlign="" positionerPadding="" transitionsPositionerIn={{ x: -480, duration: 200 }} transitionsPositionerOut={{ x: -480, duration: 200 }}> {#snippet trigger()}Open Drawer{/snippet} {#snippet content()} <header class="flex justify-between"> <h2 class="h2">Drawer Example</h2> </header> <article> <p class="opacity-60"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Nam, ab adipisci. Libero cumque sunt quis error veritatis amet, expedita voluptatem. Quos repudiandae consequuntur voluptatem et dicta quas, reprehenderit velit excepturi? </p> </article> <footer> <button type="button" class="btn preset-filled" onclick={drawerClose}>Close Drawer</button> </footer> {/snippet}</Modal>
Native Browser APIs
Skeleton will always favor native browser APIs over third-party libraries such as Floating UI Svelte. The following is a list of current and upcoming incoming APIs we will aim to support in the future, but are not quite standardized cross-browser yet.