Popover
An anchored panel that opens next to a trigger and holds interactive content — quick settings, a small form, more than a tooltip can carry
Preview
<script lang="ts">
import { Popover } from "fancy-ui-svelte";
let width = $state("100%");
let height = $state("25px");
</script>
<Popover class="w-[220px]">
{#snippet trigger()}
⚙ Options
{/snippet}
<span class="text-[13px] font-semibold">Dimensions</span>
<div class="flex gap-2">
<input
bind:value={width}
aria-label="Width"
class="border-input bg-background text-foreground min-w-0 flex-1 rounded-[6px] border px-2 py-[5px] text-[12px]"
/>
<input
bind:value={height}
aria-label="Height"
class="border-input bg-background text-foreground min-w-0 flex-1 rounded-[6px] border px-2 py-[5px] text-[12px]"
/>
</div>
</Popover>Installation
Usage
<script lang="ts">
import { Popover } from 'fancy-ui-svelte';
</script>
<Popover />Examples
Basic Usage
A Dimensions panel with two labelled fields, matching the mockup.
<script lang="ts">
import { Popover } from "$lib/fancy-ui/popover";
let width = $state("100%");
let height = $state("25px");
</script>
<Popover class="w-[220px]">
{#snippet trigger()}
⚙ Options
{/snippet}
<span class="text-[13px] font-semibold">Dimensions</span>
<div class="flex gap-2">
<input
bind:value={width}
aria-label="Width"
class="border-input bg-background text-foreground min-w-0 flex-1 rounded-[6px] border px-2 py-[5px] text-[12px]"
/>
<input
bind:value={height}
aria-label="Height"
class="border-input bg-background text-foreground min-w-0 flex-1 rounded-[6px] border px-2 py-[5px] text-[12px]"
/>
</div>
</Popover>Sides
The panel placed on each of the four sides.
<script lang="ts">
import { Popover } from "$lib/fancy-ui/popover";
const sides = ["top", "right", "bottom", "left"] as const;
</script>
<div class="flex flex-wrap items-center gap-6">
{#each sides as side (side)}
<Popover {side}>
{#snippet trigger()}
{side}
{/snippet}
<span class="text-popover-foreground text-[12px]">Placed on {side}</span>
</Popover>
{/each}
</div>With Form
An interactive form inside the panel, closing itself on submit — bind:open plus focus-trapped input and button.
<script lang="ts">
import { Popover } from "$lib/fancy-ui/popover";
import { Button } from "$lib/fancy-ui/button";
let open = $state(false);
let email = $state("");
let sent = $state("");
function invite() {
sent = email;
email = "";
open = false;
}
</script>
<Popover bind:open class="w-[240px]">
{#snippet trigger()}
Invite a teammate
{/snippet}
<span class="text-[13px] font-semibold">Invite by email</span>
<input
bind:value={email}
type="email"
placeholder="email@example.com"
class="border-input bg-background text-foreground w-full rounded-[8px] border px-3 py-[7px] text-[12px]"
/>
<Button size="sm" fullWidth onclick={invite}>Send invite</Button>
</Popover>
{#if sent}
<p class="text-muted-foreground mt-2 text-[12px]">Invited {sent}.</p>
{/if}Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | false | Whether the panel is open. Bindable |
onOpenChange | (open: boolean) => void | - | Called with the new value whenever the panel opens or closes, however the change happened |
side | "top" | "bottom" | "left" | "right" | "bottom" | Side of the trigger to place the panel on. Flips when it would overflow |
align | "start" | "center" | "end" | "center" | Alignment along the trigger's cross axis |
offset | number | 8 | Gap in pixels between the trigger and the panel |
dismissible | boolean | true | Whether Escape and an outside click close the panel |
class | string | - | Additional CSS classes, merged onto the panel |
ref | HTMLDivElement | null | null | Bindable reference to the panel element |
Slots
| Slot | Description |
|---|---|
trigger | The trigger's content, rendered inside the real <button> this component owns and wires up |
children | The panel's content |
Links
Related components
AlertDialog
A confirmation dialog for consequential, hard-to-undo actions — fixed confirm/cancel actions, never dismissed by an outside click
Dialog
A modal panel with a title, description, body and free-form footer — portals out, traps focus, and locks the page's scroll while open
Drawer
A modal bottom sheet with a grab handle, draggable shut with a downward swipe — for filters, quick actions, or any touch-first task