PB03▸🪟 Overlay · 覆蓋層▸彈出
Popover
彈出層
難度 ★★★★★標籤 popover · floating · anchor3 min read
模式簡述
Popover:錨定在某個 element 旁的小面板。和 tooltip 的差別是 popover 可互動(有按鈕、輸入框)。
Claude Code Prompt
參考:PB03 popover 組件:Popover.tsx Popover:錨定在某個 element 旁的小面板。和 tooltip 的差別是 popover 可互動(有按鈕、輸入框)。 限制: - 位置貼邊跑出視口 - 外部點擊沒關閉 - 箭頭三角形對不準
完整程式碼
"use client";
import { useEffect, useState } from "react";
type State = "closed" | "open";
export function Popover({ state = "open" }: { state?: State }) {
const [open, setOpen] = useState(state === "open");
useEffect(() => setOpen(state === "open"), [state]);
return (
<div className="relative grid h-[260px] w-full max-w-md place-items-center">
<div className="relative">
<button
onClick={() => setOpen((o) => !o)}
className="rounded-md border border-border bg-background/50 px-3 py-1.5 font-mono text-xs hover:border-lab-accent"
>
設定 ▾
</button>
{open && (
<div className="absolute left-1/2 top-full z-10 mt-2 w-56 -translate-x-1/2 rounded-lg border border-border bg-background p-3 shadow-xl animate-in fade-in zoom-in-95 duration-150">
<div className="absolute -top-1.5 left-1/2 h-3 w-3 -translate-x-1/2 rotate-45 border-l border-t border-border bg-background" />
<p className="mb-2 font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70">
偏好設定
</p>
<label className="flex items-center justify-between py-1 text-xs">
<span>啟用通知</span>
<input type="checkbox" defaultChecked className="accent-lab-accent" />
</label>
<label className="flex items-center justify-between py-1 text-xs">
<span>自動儲存</span>
<input type="checkbox" defaultChecked className="accent-lab-accent" />
</label>
<label className="flex items-center justify-between py-1 text-xs">
<span>深色模式</span>
<input type="checkbox" className="accent-lab-accent" />
</label>
</div>
)}
</div>
</div>
);
}何時用
- ✅ 設定面板的快速調整
- ✅ 顯示細節而不離開當前情境
- ✅ 資訊密度中等(比 tooltip 多,比 modal 少)
何時別用
- ❌ 內容超過半個螢幕(用 modal)
- ❌ 純顯示提示(用 tooltip)
- ❌ 需要使用者完成多步驟(用 dialog + stepper)
我踩過的坑
-
位置貼邊跑出視口:用 @floating-ui/react 算 flip + shift,別自己手算。
-
外部點擊沒關閉:要綁 mousedown 在 document,e.target.closest(popover) 判斷。
-
箭頭三角形對不準:用 Popper 或 floating-ui 內建的 arrow middleware。
相關模式
- PB04
- PB07