Biji UI

Popover

An anchor-positioned floating panel that displays rich content relative to a trigger element.

Installation

biji-ui = { version = "0.5.0", features = ["popover"] }

Usage

use leptos::prelude::*;
use biji_ui::components::popover;

#[component]
pub fn MyPopover() -> impl IntoView {
    view! {
        <popover::Root positioning={popover::Positioning::Bottom}>
            <popover::Trigger class="py-1.5 px-3 text-sm rounded border">
                "Open popover"
            </popover::Trigger>
            <popover::Content
                class="z-50 p-4 text-sm rounded-lg border shadow-md transition bg-background origin-[var(--biji-transform-origin)]"
                show_class="opacity-100 scale-100 duration-150 ease-out"
                hide_class="opacity-0 scale-95 duration-100 ease-in"
            >
                <popover::Arrow class="border-t border-l border-border" />
                "Popover content goes here."
            </popover::Content>
        </popover::Root>
    }
}

RootWith

Use RootWith to access PopoverState inline via the let: binding. The state is Copy and safe to pass as a prop.

Popover is closed

use leptos::prelude::*;
use biji_ui::components::popover;

#[component]
pub fn MyPopover() -> impl IntoView {
    view! {
        <popover::RootWith let:p>
            <p class="mb-2 text-sm text-muted-foreground">
                {move || if p.open.get() { "Popover is open" } else { "Popover is closed" }}
            </p>
            <popover::Trigger class="py-1.5 px-3 text-sm rounded border">
                "Open popover"
            </popover::Trigger>
            <popover::Content
                class="z-50 p-4 text-sm rounded-lg border shadow-md transition bg-background origin-[var(--biji-transform-origin)]"
                show_class="opacity-100 scale-100 duration-150 ease-out"
                hide_class="opacity-0 scale-95 duration-100 ease-in"
            >
                "Popover content goes here."
            </popover::Content>
        </popover::RootWith>
    }
}

API Reference

Root / RootWith

NameTypeDefaultDescription
classString""CSS class applied to the root wrapper element.
positioningPositioningBottomWhere to render the content relative to the trigger.
hide_delayDuration200msHow long to wait before unmounting the content after closing begins.
arrow_sizei328Width and height of the arrow element in pixels.
openboolfalseInitial open state.
auto_focusbooltrueWhen true, focuses the first focusable element inside Content when the popover opens.
avoid_collisionsAvoidCollisionsFlipHow the overlay reacts when it would overflow the viewport.
on_open_changeOption<Callback<bool>>NoneCallback fired when the open state changes.

Trigger

NameTypeDefaultDescription
classString""CSS class applied to the trigger button.

Content

NameTypeDefaultDescription
classString""CSS class applied in both open and closed states. Use `transition` rather than `transition-all` to avoid animating position changes. Add `origin-[var(--biji-transform-origin)]` to scale animations from the trigger direction.
show_classString""CSS class applied when the popover is open.
hide_classString""CSS class applied while the popover is closing.

Arrow

NameTypeDefaultDescription
classString""CSS class applied to the arrow element.

Positioning

NameTypeDefaultDescription
TopStartPositioning Above the trigger, aligned to its left edge.
TopPositioning Above the trigger, centered.
TopEndPositioning Above the trigger, aligned to its right edge.
RightStartPositioning To the right of the trigger, aligned to its top edge.
RightPositioning To the right of the trigger, centered.
RightEndPositioning To the right of the trigger, aligned to its bottom edge.
BottomStartPositioning Below the trigger, aligned to its left edge.
BottomPositioningdefaultBelow the trigger, centered.
BottomEndPositioning Below the trigger, aligned to its right edge.
LeftStartPositioning To the left of the trigger, aligned to its top edge.
LeftPositioning To the left of the trigger, centered.
LeftEndPositioning To the left of the trigger, aligned to its bottom edge.

AvoidCollisions

NameTypeDefaultDescription
FlipAvoidCollisionsdefaultKeeps the preferred side. Flips to the opposite side if it does not fit. If neither fits, uses whichever has more space.
AutoPlaceAvoidCollisions Always places the overlay on the side with the most available space, regardless of the preferred positioning.
NoneAvoidCollisions No collision detection. Always uses the exact positioning specified.

Data Attributes

AttributeDescription
data-state"open" when the popover is visible; "closed" when hidden. Present on Trigger.

Keyboard Navigation

KeyDescription
EscapeCloses the popover and returns focus to the trigger.