Popover

点击(或悬停)在触发器旁浮起的面板。介于 dropdown 和 tooltip 之间 — 可放任意内容(信息卡 / 迷你表单 / 确认提示)。4 个放置位置(上/右/下/左)CSS 定位(无碰撞检测),可选箭头,trigger="click"(默认)/ "hover"。Alpine 驱动,ESC 或外部点击关闭。

最简 — triggerSlot + slot

<x-popover>
    <x-slot:triggerSlot>
        <x-button appearance="outline" color="neutral" size="sm">
            <x-i type="question-circle" variant="linear" class="w-4 h-4" /> Help
        </x-button>
    </x-slot:triggerSlot>
    <p class="font-medium mb-1">About this field</p>
    <p class="text-sm text-base-content/70">Enter the email address you used at signup. We'll send a reset link if it matches an account.</p>
</x-popover>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-base-content/10 hover:bg-base-content hover:text-base-100 focus-visible:ring-base-content cursor-pointer"><svg class="w-4 h-4" viewbox="0 0 24 24">
<g fill="none">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5"></circle>
<path stroke="currentColor" stroke-linecap="round" stroke-width="1.5" d="M10.125 8.875a1.875 1.875 0 1 1 2.828 1.615c-.475.281-.953.708-.953 1.26V13"></path>
<circle cx="12" cy="16" r="1" fill="currentColor"></circle>
</g></svg> Help</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 top-full left-1/2 -translate-x-1/2 mt-2 w-72 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 border-l border-t"></div>
<p class="font-medium mb-1">
            About this field
        </p>
<p class="text-sm text-base-content/70">
            Enter the email address you used at signup. We'll send a reset link if it matches an account.
        </p>
</div>
</div>

placement — top / right / bottom (default) / left

<x-popover placement="top" width="w-56">
    <x-slot:triggerSlot><x-button appearance="outline" color="neutral" size="sm">top</x-button></x-slot:triggerSlot>
    <p class="text-sm">placement="<code>top</code>" — opens above the trigger.</p>
</x-popover>
<x-popover placement="right" width="w-56">
    <x-slot:triggerSlot><x-button appearance="outline" color="neutral" size="sm">right</x-button></x-slot:triggerSlot>
    <p class="text-sm">placement="<code>right</code>" — opens to the right.</p>
</x-popover>
<x-popover placement="bottom" width="w-56">
    <x-slot:triggerSlot><x-button appearance="outline" color="neutral" size="sm">bottom</x-button></x-slot:triggerSlot>
    <p class="text-sm">placement="<code>bottom</code>" — the default.</p>
</x-popover>
<x-popover placement="left" width="w-56">
    <x-slot:triggerSlot><x-button appearance="outline" color="neutral" size="sm">left</x-button></x-slot:triggerSlot>
    <p class="text-sm">placement="<code>left</code>" — opens to the left.</p>
</x-popover>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-base-content/10 hover:bg-base-content hover:text-base-100 focus-visible:ring-base-content cursor-pointer">top</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 bottom-full left-1/2 -translate-x-1/2 mb-2 w-56 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 border-r border-b"></div>
<p class="text-sm">
            placement="<code>top</code>" — opens above the trigger.
        </p>
</div>
</div>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-base-content/10 hover:bg-base-content hover:text-base-100 focus-visible:ring-base-content cursor-pointer">right</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 left-full top-1/2 -translate-y-1/2 ml-2 w-56 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 left-0 top-1/2 -translate-x-1/2 -translate-y-1/2 border-l border-b"></div>
<p class="text-sm">
            placement="<code>right</code>" — opens to the right.
        </p>
</div>
</div>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-base-content/10 hover:bg-base-content hover:text-base-100 focus-visible:ring-base-content cursor-pointer">bottom</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 top-full left-1/2 -translate-x-1/2 mt-2 w-56 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 border-l border-t"></div>
<p class="text-sm">
            placement="<code>bottom</code>" — the default.
        </p>
</div>
</div>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-base-content/10 hover:bg-base-content hover:text-base-100 focus-visible:ring-base-content cursor-pointer">left</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 right-full top-1/2 -translate-y-1/2 mr-2 w-56 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 right-0 top-1/2 translate-x-1/2 -translate-y-1/2 border-r border-t"></div>
<p class="text-sm">
            placement="<code>left</code>" — opens to the left.
        </p>
</div>
</div>

confirmation prompt — 在 Delete 按钮正上方确认

<x-popover placement="top" width="w-64">
    <x-slot:triggerSlot>
        <x-button color="error" appearance="outline" size="sm">Delete</x-button>
    </x-slot:triggerSlot>
    <p class="font-medium mb-2">Delete this item?</p>
    <p class="text-sm text-base-content/70 mb-3">This action can't be undone.</p>
    <div class="flex justify-end gap-2">
        <x-button size="sm" appearance="ghost" x-on:click="open = false">Cancel</x-button>
        <x-button size="sm" color="error" x-on:click="open = false">Delete</x-button>
    </div>
</x-popover>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-error border-error hover:bg-error hover:text-error-content focus-visible:ring-error cursor-pointer">Delete</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 bottom-full left-1/2 -translate-x-1/2 mb-2 w-64 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 border-r border-b"></div>
<p class="font-medium mb-2">
            Delete this item?
        </p>
<p class="text-sm text-base-content/70 mb-3">
            This action can't be undone.
        </p>
<div class="flex justify-end gap-2">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-transparent hover:bg-base-200 focus-visible:ring-base-300 cursor-pointer" x-on:click="open = false">Cancel</button>
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-error text-error-content border-error hover:bg-error/90 focus-visible:ring-error cursor-pointer" x-on:click="open = false">Delete</button>
</div>
</div>
</div>

mini form — 筛选 panel

<x-popover placement="bottom" width="w-80">
    <x-slot:triggerSlot>
        <x-button appearance="outline" color="neutral">Filter</x-button>
    </x-slot:triggerSlot>
    <p class="font-medium mb-2">Filter results</p>
    <x-input size="sm" label="Keyword" name="q" />
    <div class="mt-3">
        <x-select size="sm" label="Sort by" name="sort">
            <option value="new">Newest</option>
            <option value="old">Oldest</option>
        </x-select>
    </div>
    <div class="flex justify-end gap-2 mt-4">
        <x-button size="sm" appearance="ghost" x-on:click="open = false">Cancel</x-button>
        <x-button size="sm" color="primary" x-on:click="open = false">Apply</x-button>
    </div>
</x-popover>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-md)] px-[var(--px-field-md)] text-[length:var(--text-field-md)] gap-2 bg-transparent text-base-content border-base-content/10 hover:bg-base-content hover:text-base-100 focus-visible:ring-base-content cursor-pointer">Filter</button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 top-full left-1/2 -translate-x-1/2 mt-2 w-80 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 border-l border-t"></div>
<p class="font-medium mb-2">
            Filter results
        </p>
<div class="w-full">
<div class="flex items-baseline justify-between mb-1.5">
<label for="q_6a7e9b7ae7ac5" class="block text-[length:var(--text-field-sm)] font-medium text-base-content">Keyword</label>
</div>
<div class="flex items-stretch transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)]">
<div class="relative flex-1 min-w-0 flex items-stretch">
<input type="text" id="q_6a7e9b7ae7ac5" name="q" class="flex-1 min-w-0 w-full bg-transparent border-0 outline-none placeholder:text-base-content/40 peer text-[length:var(--text-field-sm)] px-[var(--px-input-sm)]">
</div>
</div>
</div>
<div class="mt-3">
<div class="w-full">
<div class="flex items-baseline justify-between mb-1.5">
<label for="sort_6a7e9b7ae7b42" class="block text-[length:var(--text-field-sm)] font-medium text-base-content">Sort by</label>
</div>
<div class="relative w-full" x-data="{ open: false, multi: false, placeholder: '请选择', values: [], options: [], init() { const sel = this.$refs.native; this.options = Array.from(sel.options) .filter(o =&gt; !o.hidden) .map(o =&gt; ({ value: o.value, label: o.text, disabled: o.disabled })); // Defer reading selectedOptions until after Alpine finishes applying // this tree's other bindings (notably wire:model/x-model on the native // &lt;select&gt; itself). Without this, init() runs before the child select's // own binding corrects its value, so the cached `values` — and the // trigger label bound to it — get stuck on the pre-bind SSR state // (placeholder or first &lt;option&gt;) even though the native select and // the Livewire property end up correct. this.$nextTick(() =&gt; { this.values = Array.from(sel.selectedOptions).map(o =&gt; o.value).filter(v =&gt; v !== ''); }); }, toggle(value, isDisabled) { if (isDisabled) return; if (this.multi) { const i = this.values.indexOf(value); if (i &gt;= 0) this.values.splice(i, 1); else this.values.push(value); } else { this.values = [value]; this.open = false; } this.sync(); }, remove(value) { this.values = this.values.filter(v =&gt; v !== value); this.sync(); }, sync() { const sel = this.$refs.native; Array.from(sel.options).forEach(o =&gt; o.selected = this.values.includes(o.value)); sel.dispatchEvent(new Event('change', { bubbles: true })); }, isSelected(v) { return this.values.includes(v); }, optionFor(v) { return this.options.find(o =&gt; o.value === v); }, }" @keydown.escape.window="open = false" @click.outside="open = false">
<select x-ref="native" id="sort_6a7e9b7ae7b42" class="sr-only" tabindex="-1" aria-hidden="true" name="sort">
<option value="new">
                            Newest
                        </option>
<option value="old">
                            Oldest
                        </option>
</select>
<button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"><span class="flex-1 min-w-0 flex items-center flex-wrap gap-1"></span></button>
<template x-if="!multi">
<button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"><span class="flex-1 min-w-0 flex items-center flex-wrap gap-1"><span :class="values.length ? 'truncate text-[length:var(--text-field-sm)] text-base-content' : 'truncate text-[length:var(--text-field-sm)] text-base-content text-base-content/40'" x-text="values.length ? optionFor(values[0])?.label : placeholder"></span></span></button>
</template><button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"></button>
<template x-if="multi &amp;&amp; values.length === 0">
<button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"><span class="truncate text-[length:var(--text-field-sm)] text-base-content text-base-content/40" x-text="placeholder"></span></button>
</template><button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"></button>
<template x-if="multi &amp;&amp; values.length &gt; 0">
<button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"></button>
<template x-for="v in values" :key="v">
<button type="button" class="relative w-full flex items-center gap-2 text-left transition-colors rounded-[var(--radius-field)] bg-base-100 tune-border border-base-300 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary h-[var(--h-field-sm)] px-[var(--px-input-sm)] py-1 cursor-pointer" @click="open = !open" :aria-expanded="open"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full border text-[length:var(--text-field-xs)] bg-base-200 text-base-content border-base-300"><span x-text="optionFor(v)?.label"></span>
<button type="button" class="shrink-0 inline-flex text-current/60 hover:text-current cursor-pointer" @click.stop="remove(v)" aria-label="Remove"><svg class="size-3" viewbox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg></button></span></button>
</template>
</template><svg class="pointer-events-none shrink-0 size-4 text-base-content/40 transition-transform" :class="open ? 'rotate-180' : ''" viewbox="0 0 20 20" fill="currentcolor" aria-hidden="true">
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 011.06 0L10 11.94l3.72-3.72a.75.75 0 111.06 1.06l-4.25 4.25a.75.75 0 01-1.06 0L5.22 9.28a.75.75 0 010-1.06z" clip-rule="evenodd"></path></svg>
<ul x-show="open" x-cloak="" x-transition.opacity.duration.100ms="" class="absolute z-40 mt-1 w-full max-h-72 overflow-auto bg-base-100 tune-border border-base-300 rounded-[var(--radius-field)] shadow-[var(--shadow-box)] p-1" role="listbox" :aria-multiselectable="multi">
<template x-for="opt in options" :key="opt.value">
</template>
<li class="flex items-center justify-between gap-2 px-3 py-2 rounded-[var(--radius-field)] cursor-pointer text-base-content hover:bg-base-200 transition-colors text-[length:var(--text-field-sm)]" :class="(isSelected(opt.value) ? 'bg-base-200 font-medium ' : '') + (opt.disabled ? 'opacity-50 cursor-not-allowed pointer-events-none' : '')" role="option" :aria-selected="isSelected(opt.value)" @click="toggle(opt.value, opt.disabled)">
<span x-text="opt.label"></span>
<svg x-show="isSelected(opt.value)" class="shrink-0 size-4 text-base-content" viewbox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="3" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path></svg>
</li>
</ul>
</div>
</div>
</div>
<div class="flex justify-end gap-2 mt-4">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-transparent hover:bg-base-200 focus-visible:ring-base-300 cursor-pointer" x-on:click="open = false">Cancel</button>
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-primary text-primary-content border-primary hover:bg-primary/90 focus-visible:ring-primary cursor-pointer" x-on:click="open = false">Apply</button>
</div>
</div>
</div>

trigger=hover (仅供展示信息,不要加入 inputs)

All times are shown in

JST
unless stated otherwise.

<p class="text-sm">All times are shown in
    <x-popover trigger="hover" placement="top" width="w-fit">
        <x-slot:triggerSlot>
            <span class="underline decoration-dotted cursor-help font-medium">JST</span>
        </x-slot:triggerSlot>
        <p class="text-sm">Japan Standard Time (UTC+9)</p>
    </x-popover>
    unless stated otherwise.
</p>
<p class="text-sm">
    All times are shown in
</p>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:mouseenter="open = true" x-on:mouseleave="open = false" class="inline-block cursor-pointer">
<span class="underline decoration-dotted cursor-help font-medium">JST</span>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 bottom-full left-1/2 -translate-x-1/2 mb-2 w-fit rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-lg">
<div class="absolute w-2 h-2 rotate-45 bg-base-100 border-base-300 bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 border-r border-b"></div>
<p class="text-sm">
            Japan Standard Time (UTC+9)
        </p>
</div>
</div>unless stated otherwise.
<p></p>

context menu — 通过 `arrow=false` + `padding="p-1"` 去除行间多余留白 (自 v0.3.20 起)

<x-popover :arrow="false" width="w-48" padding="p-1">
    <x-slot:triggerSlot>
        <x-button appearance="ghost" size="sm" class="!p-1">
            <x-i type="more-horizontal" variant="linear" class="w-5 h-5" />
        </x-button>
    </x-slot:triggerSlot>
    <ul class="text-sm">
        <li><a href="#" class="block hover:bg-base-200 rounded px-3 py-1.5">Edit</a></li>
        <li><a href="#" class="block hover:bg-base-200 rounded px-3 py-1.5">Duplicate</a></li>
        <li><a href="#" class="block hover:bg-base-200 rounded px-3 py-1.5 text-error">Delete</a></li>
    </ul>
</x-popover>
<div x-data="{ open: false }" @keydown.escape.window="open = false" class="relative inline-block w-fit">
<div x-on:click="open = !open" x-on:click.outside="open = false" class="inline-block cursor-pointer">
<button class="inline-flex items-center justify-center whitespace-nowrap font-medium tracking-wide transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 rounded-[var(--radius-field)] border-[length:var(--border)] h-[var(--h-field-sm)] px-[var(--px-field-sm)] text-[length:var(--text-field-sm)] gap-1.5 bg-transparent text-base-content border-transparent hover:bg-base-200 focus-visible:ring-base-300 cursor-pointer !p-1"><!-- Icon not found: solar/more-horizontal-linear --></button>
</div>
<div x-show="open" x-cloak="" x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" role="dialog" class="absolute z-50 top-full left-1/2 -translate-x-1/2 mt-2 w-48 rounded-[var(--radius-box)] bg-base-100 tune-border border-base-300 shadow-[var(--shadow-box)] p-1">
<ul class="text-sm">
<li>
<a href="#" class="block hover:bg-base-200 rounded px-3 py-1.5">Edit</a>
</li>
<li>
<a href="#" class="block hover:bg-base-200 rounded px-3 py-1.5">Duplicate</a>
</li>
<li>
<a href="#" class="block hover:bg-base-200 rounded px-3 py-1.5 text-error">Delete</a>
</li>
</ul>
</div>
</div>