Frontend Lab
← 回到所有模式
PC01🧭 Navigation · 導航頁籤

Tabs

頁籤

難度 ★★★★★標籤 tabs · indicator · 鍵盤3 min read

模式簡述

Tabs:平行內容切換。indicator 動畫滑過去比直接跳更高級。鍵盤要支援左右箭頭。

當前面板:概覽 的內容
第 1 個|首個 active

Claude Code Prompt

💬 Claude Code Prompt
參考:PC01 tabs
組件:Tabs.tsx

Tabs:平行內容切換。indicator 動畫滑過去比直接跳更高級。鍵盤要支援左右箭頭。

限制:
- indicator 直接跳不動畫
- ARIA 屬性沒寫對
- 重置 tab 內 state 沒處理

完整程式碼

Tabs.tsx
"use client";
import { useEffect, useState } from "react";
import { motion } from "framer-motion";

type State = "first" | "second" | "third";
const TABS = ["概覽", "設定", "整合"];

export function Tabs({ state = "first" }: { state?: State }) {
const idx = state === "first" ? 0 : state === "second" ? 1 : 2;
const [active, setActive] = useState(idx);
useEffect(() => setActive(idx), [idx]);

return (
  <div className="w-full max-w-md">
    <div className="flex gap-1 border-b border-border">
      {TABS.map((t, i) => (
        <button
          key={t}
          onClick={() => setActive(i)}
          className="relative px-4 py-2 text-sm transition"
        >
          <span className={i === active ? "text-foreground" : "text-muted-foreground"}>{t}</span>
          {i === active && (
            <motion.div
              layoutId="tab-indicator"
              className="absolute inset-x-0 -bottom-px h-0.5 bg-lab-accent"
              transition={{ type: "spring", stiffness: 400, damping: 30 }}
            />
          )}
        </button>
      ))}
    </div>
    <div
      className="mt-5 rounded-md border border-border bg-background/30 p-4 text-sm text-muted-foreground"
      style={{ fontFamily: "var(--font-zh)" }}
    >
      當前面板:<span className="text-foreground">{TABS[active]}</span> 的內容
    </div>
  </div>
);
}

何時用

  • ✅ 設定頁的不同子區塊
  • ✅ 資料的不同視角(日/週/月)
  • ✅ 詳情頁的子內容分頁

何時別用

  • ❌ 分頁是順序流程(用 stepper)
  • ❌ 分頁超過 5 個(用 dropdown 或 sidebar)
  • ❌ 每個 tab 內容是不同 URL(用一般 nav)

我踩過的坑

  1. indicator 直接跳不動畫:用 Framer layoutId 滑過去,瞬間升級。

  2. ARIA 屬性沒寫對:role='tablist' tab + 'tabpanel' + aria-selected。鍵盤要 ArrowLeft/Right。

  3. 重置 tab 內 state 沒處理:使用者切回來上次 scroll 位置沒了。需要時用 keep-mounted。

相關模式

  • PE08
  • PC04

搜尋

按 ⌘K 隨時開啟