PB12▸🪟 Overlay · 覆蓋層▸對話框
Action Sheet (iOS)
iOS 動作清單
難度 ★★★★★標籤 iOS · 底部 · apple3 min read
模式簡述
Action Sheet:iOS 風格從底部彈出的選項清單。手指拇指可達區,破壞性動作標紅,最下方有「取消」。
Claude Code Prompt
參考:PB12 action-sheet 組件:ActionSheet.tsx Action Sheet:iOS 風格從底部彈出的選項清單。手指拇指可達區,破壞性動作標紅,最下方有「取消」。 限制: - 沒在頂部加 grab handle - 取消按鈕沒和選項分開 - 破壞性動作沒紅字
完整程式碼
"use client";
import { useEffect, useState } from "react";
type State = "closed" | "open" | "destructive";
export function ActionSheet({ state = "open" }: { state?: State }) {
const [open, setOpen] = useState(state !== "closed");
useEffect(() => setOpen(state !== "closed"), [state]);
const destructive = state === "destructive";
return (
<div className="relative h-[340px] w-full max-w-sm overflow-hidden rounded-2xl border border-border bg-background/30">
<div className="grid h-full place-items-center">
<button
onClick={() => setOpen(true)}
className="rounded-md border border-border bg-background/50 px-3 py-1.5 font-mono text-xs hover:border-lab-accent"
>
開啟 Action Sheet
</button>
</div>
{open && (
<>
<div
onClick={() => setOpen(false)}
className="absolute inset-0 bg-black/40 animate-in fade-in duration-200"
/>
<div className="absolute inset-x-2 bottom-2 space-y-2 animate-in slide-in-from-bottom duration-300">
<div className="overflow-hidden rounded-2xl bg-background/95 backdrop-blur-xl">
<p className="px-4 py-3 text-center text-[11px] text-muted-foreground">
{destructive ? "刪除此項目嗎?" : "選擇操作"}
</p>
{destructive && (
<button className="flex w-full items-center justify-center border-t border-border/40 px-4 py-3 text-base font-medium text-red-500 hover:bg-red-500/5">
刪除
</button>
)}
<button className="flex w-full items-center justify-center border-t border-border/40 px-4 py-3 text-base text-lab-accent hover:bg-lab-accent/5">
{destructive ? "保留並隱藏" : "拍照"}
</button>
<button className="flex w-full items-center justify-center border-t border-border/40 px-4 py-3 text-base text-lab-accent hover:bg-lab-accent/5">
{destructive ? "回報問題" : "從相簿選取"}
</button>
</div>
<button
onClick={() => setOpen(false)}
className="w-full rounded-2xl bg-background/95 px-4 py-3 text-base font-semibold text-lab-accent backdrop-blur-xl hover:bg-background"
>
取消
</button>
</div>
</>
)}
</div>
);
}何時用
- ✅ 手機端的多選項操作(分享、儲存、刪除)
- ✅ 想營造原生 app 質感的 web 介面
- ✅ 選項 3-7 個之間(多了就要分組或滾動)
何時別用
- ❌ 桌面端(很違和,請改 dropdown)
- ❌ 選項超過 8 個(會超出螢幕)
- ❌ 需要輸入文字(這時候是 modal)
我踩過的坑
-
沒在頂部加 grab handle:iOS 規範會有一條 36x5px 的灰色把手,視覺暗示可拖。
-
取消按鈕沒和選項分開:應該空一格背景色,視覺上明確分組。
-
破壞性動作沒紅字:刪除、登出要用 system red (#FF3B30) 警告。
相關模式
- PB01
- PB02