PE07▸⌨️ Input · 進階輸入▸開關
iOS Toggle Switch
iOS 開關
難度 ★★★★★標籤 iOS · switch · apple3 min read
模式簡述
iOS Toggle Switch:圓形 thumb 在膠囊軌道上左右滑。iOS 設定頁標配。比 checkbox 更明確的 on/off。
飛航模式
Wi-Fi 自動連線
Claude Code Prompt
參考:PE07 ios-toggle 組件:IOSToggle.tsx iOS Toggle Switch:圓形 thumb 在膠囊軌道上左右滑。iOS 設定頁標配。比 checkbox 更明確的 on/off。 限制: - 沒做即時 feedback - 色彩對比不夠 - 沒鍵盤支援
完整程式碼
"use client";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
type State = "off" | "on" | "disabled";
export function IOSToggle({ state = "off" }: { state?: State }) {
const [on, setOn] = useState(state === "on");
useEffect(() => setOn(state === "on"), [state]);
const disabled = state === "disabled";
return (
<div className="w-full max-w-md">
<div className="space-y-4 rounded-xl border border-border bg-background/30 p-4">
{[
{ label: "飛航模式", forced: false },
{ label: "Wi-Fi 自動連線", forced: true },
].map((row, idx) => {
const value = idx === 0 ? on : true;
return (
<div key={row.label} className="flex items-center justify-between">
<span className="text-sm text-foreground">{row.label}</span>
<button
onClick={() => idx === 0 && !disabled && setOn((v) => !v)}
disabled={disabled && idx === 0}
className={cn(
"relative h-7 w-12 rounded-full transition-colors duration-200",
value ? "bg-emerald-500" : "bg-zinc-600/40",
disabled && idx === 0 && "opacity-50",
)}
>
<span
className={cn(
"absolute top-0.5 h-6 w-6 rounded-full bg-white shadow-md transition-transform duration-200",
value ? "translate-x-[22px]" : "translate-x-0.5",
)}
/>
</button>
</div>
);
})}
</div>
</div>
);
}何時用
- ✅ 設定頁的功能開關(飛航模式、通知)
- ✅ 需要立即生效的二元切換
- ✅ 想營造 iOS 質感的 web app
何時別用
- ❌ 需要「儲存」才生效的設定(toggle 給人立即生效錯覺)
- ❌ 二元以外的選擇(用 segmented control)
- ❌ 桌面端嚴肅介面(用 checkbox 更標準)
我踩過的坑
-
沒做即時 feedback:toggle 後 API 還沒回,但畫面已經切換。失敗要 revert + toast。
-
色彩對比不夠:on 用 emerald-500、off 用 zinc-600/40,視覺差異明顯。
-
沒鍵盤支援:space 鍵應該 toggle,跟原生 checkbox 一致。
相關模式
- PE08
- PB12