PB10▸🪟 Overlay · 覆蓋層▸動態
Dynamic Island
動態島
難度 ★★★★★標籤 變形 · morph · 通知3 min read
模式簡述
Dynamic Island:iPhone 風格的頂部變形通知條。從膠囊→展開→收合。Apple 在 iOS 16 帶起。
●
Claude Code Prompt
參考:PB10 dynamic-island 組件:DynamicIsland.tsx Dynamic Island:iPhone 風格的頂部變形通知條。從膠囊→展開→收合。Apple 在 iOS 16 帶起。 限制: - morph 動畫做不順 - 狀態擠在一起 - 忘了讓使用者點開
完整程式碼
"use client";
import { useEffect, useState } from "react";
import { Music2, Phone } from "lucide-react";
import { cn } from "@/lib/utils";
type State = "idle" | "notification" | "activity";
export function DynamicIsland({ state = "idle" }: { state?: State }) {
const [mode, setMode] = useState<State>(state);
useEffect(() => setMode(state), [state]);
return (
<div className="relative grid h-[260px] w-full max-w-md place-items-center">
<div
className={cn(
"flex items-center justify-center overflow-hidden rounded-full bg-black text-white transition-all duration-500 ease-out",
mode === "idle" && "h-7 w-28",
mode === "notification" && "h-12 w-72 px-4",
mode === "activity" && "h-14 w-80 px-3",
)}
>
{mode === "idle" && <span className="font-mono text-[10px] text-white/40">●</span>}
{mode === "notification" && (
<div className="flex items-center gap-2.5">
<Phone className="h-4 w-4 text-green-400" />
<div className="text-xs">
<p className="font-medium">媽媽</p>
<p className="text-[11px] text-white/60">來電中⋯</p>
</div>
</div>
)}
{mode === "activity" && (
<div className="flex w-full items-center gap-2.5">
<div className="grid h-9 w-9 place-items-center rounded-md bg-gradient-to-br from-pink-500 to-orange-500">
<Music2 className="h-4 w-4" />
</div>
<div className="flex-1 text-xs">
<p className="truncate font-medium">Bohemian Rhapsody</p>
<p className="truncate text-[11px] text-white/60">Queen</p>
</div>
<div className="flex h-7 w-7 items-end justify-center gap-0.5 pb-1">
<span className="h-2 w-0.5 animate-pulse bg-orange-400" />
<span className="h-3 w-0.5 animate-pulse bg-orange-400 [animation-delay:120ms]" />
<span className="h-1.5 w-0.5 animate-pulse bg-orange-400 [animation-delay:240ms]" />
</div>
</div>
)}
</div>
</div>
);
}何時用
- ✅ 全站持續性的通知(播放中、上傳中、來電)
- ✅ 想做出 Apple 風格 brand 感的 marketing site
- ✅ 需要極簡又不打斷使用者的 status indicator
何時別用
- ❌ 桌面端傳統介面(很違和)
- ❌ 通知量大或多種類(用 toast 堆疊)
- ❌ 需要 user 互動完成的任務(用 modal)
我踩過的坑
-
morph 動畫做不順:用 Framer Motion 的 layoutId 或 height auto + spring。沒 spring 就死板。
-
狀態擠在一起:collapsed 不該顯示太多字,最多 icon + 一個指標。展開後再給內文。
-
忘了讓使用者點開:collapsed 應該可點擊 toggle,不然只是裝飾。
相關模式
- PB11
- PA08