Components

Popover

Displays rich content in a portal, triggered by a button.

php artisan blatui:add popover
<x-ui.popover>
    <x-ui.popover-trigger>
        <x-ui.button variant="outline">Open popover</x-ui.button>
    </x-ui.popover-trigger>
    <x-ui.popover-content class="w-80">
        <div class="grid gap-4">
            <div class="space-y-2">
                <h4 class="leading-none font-medium">Dimensions</h4>
                <p class="text-muted-foreground text-sm">Set the dimensions for the layer.</p>
            </div>
            <div class="grid gap-2">
                <div class="grid grid-cols-3 items-center gap-4">
                    <x-ui.label for="width">Width</x-ui.label>
                    <x-ui.input id="width" value="100%" class="col-span-2 h-8" />
                </div>
                <div class="grid grid-cols-3 items-center gap-4">
                    <x-ui.label for="maxWidth">Max. width</x-ui.label>
                    <x-ui.input id="maxWidth" value="300px" class="col-span-2 h-8" />
                </div>
                <div class="grid grid-cols-3 items-center gap-4">
                    <x-ui.label for="height">Height</x-ui.label>
                    <x-ui.input id="height" value="25px" class="col-span-2 h-8" />
                </div>
                <div class="grid grid-cols-3 items-center gap-4">
                    <x-ui.label for="maxHeight">Max. height</x-ui.label>
                    <x-ui.input id="maxHeight" value="none" class="col-span-2 h-8" />
                </div>
            </div>
        </div>
    </x-ui.popover-content>
</x-ui.popover>

Feedback

<x-ui.popover>
    <x-ui.popover-trigger>
        <x-ui.button variant="outline"><x-lucide-message-square aria-hidden="true" /> Feedback</x-ui.button>
    </x-ui.popover-trigger>
    <x-ui.popover-content class="w-80">
        <form class="grid gap-3">
            <div class="space-y-1">
                <h4 class="leading-none font-medium">Send feedback</h4>
                <p class="text-muted-foreground text-sm">We'd love to hear what went well or could be better.</p>
            </div>
            <x-ui.textarea placeholder="Your feedback..." class="min-h-24" aria-label="Your feedback" />
            <x-ui.button type="submit" size="sm" class="w-full">Send feedback</x-ui.button>
        </form>
    </x-ui.popover-content>
</x-ui.popover>

Positions

{{-- The `side` prop places the popover on any edge of the trigger. --}}
<div class="flex flex-wrap items-center justify-center gap-2">
    @foreach (['top', 'right', 'bottom', 'left'] as $side)
        <x-ui.popover>
            <x-ui.popover-trigger>
                <x-ui.button variant="outline" class="capitalize">{{ $side }}</x-ui.button>
            </x-ui.popover-trigger>
            <x-ui.popover-content side="{{ $side }}" class="w-auto">
                <p class="text-sm">Popover on the <span class="font-medium">{{ $side }}</span>.</p>
            </x-ui.popover-content>
        </x-ui.popover>
    @endforeach
</div>

Settings

<x-ui.popover>
    <x-ui.popover-trigger>
        <x-ui.button variant="outline"><x-lucide-bell aria-hidden="true" /> Notifications</x-ui.button>
    </x-ui.popover-trigger>
    <x-ui.popover-content class="w-72">
        <div class="grid gap-3">
            <h4 class="leading-none font-medium">Notifications</h4>
            <div class="flex items-center justify-between gap-4">
                <x-ui.label for="pop-email">Email</x-ui.label>
                <x-ui.switch id="pop-email" checked />
            </div>
            <div class="flex items-center justify-between gap-4">
                <x-ui.label for="pop-push">Push</x-ui.label>
                <x-ui.switch id="pop-push" />
            </div>
            <div class="flex items-center justify-between gap-4">
                <x-ui.label for="pop-sms">SMS</x-ui.label>
                <x-ui.switch id="pop-sms" />
            </div>
        </div>
    </x-ui.popover-content>
</x-ui.popover>

Share

<x-ui.popover>
    <x-ui.popover-trigger>
        <x-ui.button variant="outline"><x-lucide-share-2 aria-hidden="true" /> Share</x-ui.button>
    </x-ui.popover-trigger>
    <x-ui.popover-content class="w-80">
        <div class="grid gap-3">
            <div class="space-y-1">
                <h4 class="leading-none font-medium">Share link</h4>
                <p class="text-muted-foreground text-sm">Anyone with the link can view this page.</p>
            </div>
            <div class="flex items-center gap-2">
                <x-ui.input value="https://blatui.dev/x/8Fk2pQ" readonly aria-label="Share link" class="h-8" />
                <x-ui.button size="sm" variant="secondary"><x-lucide-link aria-hidden="true" /> Copy</x-ui.button>
            </div>
        </div>
    </x-ui.popover-content>
</x-ui.popover>

API Reference

Props, slots and exposed methods for <x-ui.popover>.

Props

Prop Type Default Description
align string 'center' Set on <x-ui.popover-content>. Aligns the panel along the trigger edge it is anchored to.
center start end
side string 'bottom' Set on <x-ui.popover-content>. Which edge of the trigger the panel opens from. Auto-flips if it would overflow the viewport.
top right bottom left
sideOffset int 4 Set on <x-ui.popover-content>. Gap in pixels between the trigger and the panel.
label string 'Popover' Set on <x-ui.popover-content>. Accessible name (aria-label) for the dialog panel.

Slots

Slot Description
default Place <x-ui.popover-trigger> and <x-ui.popover-content> here. The wrapper holds the shared open state.
trigger Content of <x-ui.popover-trigger> — the clickable element (usually a button) that toggles the popover.
content Content of <x-ui.popover-content> — the panel body shown when open. Teleported to <body> and anchored to the trigger.

Methods

Available on the component's Alpine scope — call them from markup in the slot (e.g. @click="…").

Method Description
open Reactive boolean on the shared Alpine scope. Set open = true / false from slot markup to control the panel programmatically.