Play/Pause Morph
播放三角形與暫停長條之間平順變形的圖形按鈕,支援受控/非受控雙模式與選填進度環。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
0.4
<PlayPauseMorph />
安裝
npx shadcn@latest add https://webberui.com/r/play-pause-morph.json或在 components.json 設定 registries 後,改用 @webberui/play-pause-morph 安裝。
安裝依賴後,從 registry JSON(/r/play-pause-morph.json 的 files[0].content)複製 play-pause-morph.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
import { PlayPauseMorph } from "@/components/ui/play-pause-morph";
<PlayPauseMorph defaultPlaying={false} onPlayingChange={(p) => console.log(p)} />受控模式與進度環
const [playing, setPlaying] = React.useState(false);
<PlayPauseMorph
size="lg"
playing={playing}
onPlayingChange={setPlaying}
progress={0.42}
/>傳入 playing 即進入受控模式,內建狀態停用,開關完全由你的 state 主導。傳入 progress(0–1)時,按鈕外圈會多出一圈進度環。
Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
playing | boolean | — | 受控播放狀態;提供時由外部主導 |
defaultPlaying | boolean | false | 非受控模式的初始播放狀態 |
onPlayingChange | (playing: boolean) => void | — | 切換時觸發,回傳切換後的狀態 |
variant | "solid" | "soft" | "ghost" | "solid" | 視覺變體 |
size | "sm" | "md" | "lg" | "md" | 尺寸(32 / 40 / 48px) |
progress | number | — | 選填 0–1 進度;提供時顯示外圈進度環 |
playLabel | string | "播放" | 暫停中的 aria-label(按下會播放) |
pauseLabel | string | "暫停" | 播放中的 aria-label(按下會暫停) |
其餘 <button> 原生屬性(disabled、onClick、className…)皆可透傳。在 onClick 中呼叫 preventDefault() 可攔下該次切換(適合先做非同步授權)。
細節
- 播放三角形沿中線切成左右兩塊四邊形,與暫停的兩根長條採用相同的四點路徑結構,因此可逐點內插 SVG 的
d屬性,讓圖形真正「變形」而非淡入淡出。 - morph 採用彈簧過場,收放帶有自然的回彈手感。
- 進度環以
pathLength正規化為 1,用strokeDashoffset表示已播放比例,數值變動時平順補間。
可及性
- 以原生
<button>實作,Enter/Space皆可觸發,焦點有清晰的focus-visible外框。 aria-label隨狀態切換:播放中為「暫停」、暫停中為「播放」,明確描述按下後的動作。- 圖形以
aria-hidden對輔助科技隱藏,避免朗讀無意義的向量內容。 - 使用者系統開啟「減少動態效果」時,morph 與縮放回饋直接定格切換,不影響功能。