Frontend Lab
← 回到所有模式
PB10🪟 Overlay · 覆蓋層動態

Dynamic Island

動態島

難度 ★★★★標籤 變形 · morph · 通知3 min read

模式簡述

Dynamic Island:iPhone 風格的頂部變形通知條。從膠囊→展開→收合。Apple 在 iOS 16 帶起。

閒置|預設小圓角膠囊

Claude Code Prompt

💬 Claude Code Prompt
參考:PB10 dynamic-island
組件:DynamicIsland.tsx

Dynamic Island:iPhone 風格的頂部變形通知條。從膠囊→展開→收合。Apple 在 iOS 16 帶起。

限制:
- morph 動畫做不順
- 狀態擠在一起
- 忘了讓使用者點開

完整程式碼

DynamicIsland.tsx
"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)

我踩過的坑

  1. morph 動畫做不順:用 Framer Motion 的 layoutId 或 height auto + spring。沒 spring 就死板。

  2. 狀態擠在一起:collapsed 不該顯示太多字,最多 icon + 一個指標。展開後再給內文。

  3. 忘了讓使用者點開:collapsed 應該可點擊 toggle,不然只是裝飾。

相關模式

  • PB11
  • PA08

搜尋

按 ⌘K 隨時開啟