Overlays

Popover

A floating surface anchored to a trigger. Place it on any side, optionally aligned to the start or end of the trigger.

Installation

pnpm dlx @mielui/svelte add popover

Usage

Bind open on Root when another control needs to open or close the panel. onOpenChange reports changes made inside the component; setting the bound value yourself does not call it. Each Root keeps its own state.

Content has a dialog role, so give it a Title or an aria-label. While a click popover is open, Tab stays inside the panel, the page does not scroll, and content outside it is inert. Set focusTrap and lockScroll to false on Content, and inert={false} on Root, when the rest of the page must stay usable.

Trigger onclick receives the native event before the open state changes. Call preventDefault() to cancel opening or closing.

<script lang="ts">
    import * as Popover from '@mielui/svelte/components/popover';
</script>

<Popover.Root>
    <Popover.Trigger>Open</Popover.Trigger>
    <Popover.Content class="w-64" aria-label="Details">Content here</Popover.Content>
</Popover.Root>

Examples

Share form

A form, a member list, and a status line composed inside one panel.

Basic

Placements

placement on Root picks a side and an optional -start or -end alignment. The panel flips when there is no room.

Glass surface

surface="glass" on Content gives the panel a translucent, blurred background. Omit surface to inherit --mielui-surface from the theme, or set surface="solid" to override it. Glass falls back to an opaque fill when backdrop filtering is unavailable or reduced transparency is requested.

Open on hover

hoverable on Root opens the popover when the pointer rests on the trigger, as well as on click. delay is how long the pointer has to rest, in milliseconds, and defaults to 0. closeDelay keeps the panel open after the pointer leaves, 150 ms by default, so people can move onto it. A hover popover does not trap focus, lock scrolling, or make the page inert.

Dismissal and layering

A click popover closes on Escape and on a press outside. allowClickOutside={false} on Content keeps it open until Escape or until you set open to false.

While open, the popover puts an invisible layer over the page so the first outside press only closes it. Set dismissLayer={false} when the trigger has to stay usable while the panel is open, such as a text input that filters the panel. Outside presses still close the popover.

portal moves the panel to the end of the document so a parent with clipped overflow cannot cut it off. Set portal={false} to render it in place, for example inside a container you style with a container query.

refElement anchors the panel to another element or a virtual element in place of the trigger. The panel then opens to the right of that element, which is how submenus use it.

Trigger and state

Trigger is a Button and defaults to the primary variant. icon adds a chevron after the label that turns while the popover is open, and unstyled removes the Button classes. onopen runs just before this trigger opens the popover, which is the place to load the panel's data. Bind element to reach the button.

On Content, class styles the outer frame and surfaceClass styles the inner surface where your children sit.

API reference

Popover.Root

Controls popover state.

  • children
    Snippet<[]>

    Content rendered inside.

  • open Bindable
    boolean

    Whether it is open. Bind it to control the state from outside.

    Default false

  • onOpenChange
    ((open: boolean) => void)

    Called with the new state whenever it opens or closes.

  • placement
    Placement

    Preferred side and alignment relative to the trigger, such as bottom-start. It flips when there is no room.

    Default 'bottom'

  • hoverable
    boolean

    Opens on hover as well as on click.

  • delay
    number

    Milliseconds the pointer rests on the trigger before it opens.

    Default 0

  • closeDelay
    number

    Milliseconds after the pointer leaves before it closes.

    Default 150

  • inert
    boolean

    Make document content outside an open non-hover popover inert. Defaults to true.

    Default true

Popover.Content

Renders the popover surface.

  • surface
    "solid" | "glass"

    Surface treatment. Omit it to inherit --mielui-surface from the theme.

  • children Required
    Snippet<[]>

    Content rendered inside.

  • class
    (string & (ClassValue | null))

    Classes added to the element.

  • surfaceClass
    string

    Classes for the inset surface (where children live) โ€” padding, layout, background overrides. The class prop styles the outer Panel frame.

  • allowClickOutside
    boolean

    Closes when the pointer is pressed outside it. Set false to keep it open until it is dismissed another way.

    Default true

  • dismissLayer
    boolean

    Render the full-viewport dismiss layer under the panel while open. Defaults to true. Set to false for triggers that must stay clickable while open (e.g. an input-style combobox trigger); outside pointer dismissal still applies via allowClickOutside.

    Default true

  • portal
    boolean

    Moves the panel to the end of the document so ancestors cannot clip it. Set false to render it in place.

    Default true

  • refElement
    VirtualElement

    Positions the panel against this element or virtual element instead of the trigger. The panel then opens to the right of it, as a submenu does.

  • role
    "dialog" | "alertdialog" | "menu" | "listbox" | "none"

    ARIA role of the panel.

    Default 'dialog'

  • tabindex
    number

    Tab index of the panel.

    Default -1

  • focusTrap
    boolean

    Trap Tab focus inside the panel while open. Defaults to true.

    Default true

  • lockScroll
    boolean

    Lock document scrolling while the panel is open. Defaults to true.

    Default true

Popover.Title

Renders the popover title.

  • class
    string

    Classes added to the element.

  • children
    Snippet<[]>

    Content rendered inside.

Popover.Trigger

Opens the popover.

  • icon
    boolean

    Shows the chevron after the label.

    Default false

  • variant
    ButtonVariant

    Button style of the trigger.

  • size
    "sm" | "md" | "lg" | "icon"

    Control height of the trigger.

  • children
    Snippet<[]>

    Content rendered inside.

  • class
    string

    Classes added to the element.

  • element Bindable
    HTMLButtonElement | HTMLAnchorElement

    Bindable reference to the DOM element.

  • unstyled
    boolean

    Forwarded to Button: render with class alone, skipping variant/size.

  • onclick
    ((event: MouseEvent) => void)

    Called when it is clicked or activated.

  • onopen
    (() => void)

    Called immediately before this trigger opens its popover.

  • style
    string

    Inline styles for the element.