導航

玻璃底欄

手機底部的玻璃質感分頁列 React 元件:圖示掛載時依序彈出、選取底塊在分頁間滑動、選中項標籤展開,可選中央凸起主按鈕與未讀徽章數字。

手機 App 底部的玻璃質感分頁列。掛載時每個圖示依序以帶點回彈的彈簧彈出;切換分頁時,白色選取底塊從上一項滑到新的一項,選中項同時由「僅圖示」展開成「圖示 + 標籤」。項目數為奇數時可開啟 raisedCenter,把中間那項改成凸起的圓形主按鈕(例如「新增」);徽章支援未讀數字(超過 99 顯示 99+)與小紅點,數字變化時會縮放提醒一次。選中值支援受控/非受控雙模式。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add glass-tab-bar

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

18
60
編輯中的呼叫預設屬性
<GlassTabBar/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/glass-tab-bar.json

或在 components.json 設定 registries 後,改用 @webberui/glass-tab-bar 安裝。

使用

import { Compass, House, MessageCircle, Plus, User } from "lucide-react";
import { GlassTabBar } from "@/components/ui/glass-tab-bar";

const [tab, setTab] = React.useState("home");

<GlassTabBar
  position="fixed"
  raisedCenter
  value={tab}
  onValueChange={setTab}
  onCenterPress={() => openComposer()}
  items={[
    { id: "home", icon: <House />, label: "首頁" },
    { id: "explore", icon: <Compass />, label: "探索" },
    { id: "create", icon: <Plus />, label: "新增" },
    { id: "messages", icon: <MessageCircle />, label: "訊息", badge: 3 },
    { id: "me", icon: <User />, label: "我的" },
  ]}
/>

Props

Prop型別預設值說明
itemsGlassTabBarItem[]—分頁項目清單
valuestring—受控的選中項目 id;未提供時由元件內部管理(非受控)
defaultValuestring第一項的 id非受控模式的初始選中 id
onValueChange(value: string) => void—選中項目改變時回呼,參數為新的 id
raisedCenterbooleanfalse項目數為奇數(至少 3 項)時,把中間那項改成凸起的圓形主按鈕
onCenterPress() => void—點擊中央主按鈕時回呼
centerSelectablebooleanfalse中央主按鈕是否也會改變 value;預設只觸發 onCenterPress
blurnumber18玻璃背景模糊程度(px);未提供時使用 --wb-gtb-blur
staggernumber60掛載時圖示依序彈出的間隔(ms);未提供時讀取 --wb-gtb-stagger
position"fixed" | "static""static"fixed 固定在視窗底部並留 safe-area;static 依文件流排版
ariaLabelstring"主要導覽"nav 的無障礙名稱
classNamestring—透傳到最外層 nav

GlassTabBarItem

欄位型別預設值說明
idstring—唯一識別碼,也是 value 的值
iconReact.ReactNode—分頁圖示,建議 20px 的 lucide 圖示
labelstring—分頁名稱;選中時顯示在圖示旁,未選中時作為無障礙名稱
badgenumber | boolean—數字顯示未讀數(超過 99 顯示 99+),true 顯示小紅點

CSS 變數

欄位型別預設值說明
--wb-gtb-blurlength18px玻璃背景模糊程度
--wb-gtb-staggertime60ms圖示依序彈出的間隔(stagger prop 優先)
--wb-gtb-highlightcolorrgba(255,255,255,0.6)頂緣 1px 內高光
--wb-gtb-accentcolor#171717(dark:#f5f5f5)中央主按鈕底色
--wb-gtb-badgecolor#ef4444徽章底色

細節

  • 玻璃材質:半透明白底(dark 為 neutral-900/55)加 backdrop-blur 與 backdrop-saturate-150,頂緣一道 1px 內高光、外框 1px 淡邊與柔和外陰影,整體為圓角膠囊。
  • 選取底塊用 motion 的 layoutId 在分頁間滑動;layoutId 以 useId 加前綴,同一頁放多個底欄也不會互相干擾。
  • 選中項的寬度以 layout 動畫展開,標籤延遲 60ms 淡入並從左側滑入 4px;首次渲染直接顯示,不播放展開動畫。
  • 中央主按鈕直徑 56px、上浮 18px,不參與底塊滑動;它不是 tab,點擊只呼叫 onCenterPress,除非開啟 centerSelectable。
  • 掛載彈出等元件掛載後才開始,這時已確定使用者的動態偏好與 CSS 變數值,SSR 首次渲染與 client 一致。

可及性

  • 外層為 nav(預設 aria-label「主要導覽」),內部為 role="tablist",每個分頁是 role="tab" 並設定 aria-selected
  • 分頁的 aria-label 為其標籤,有徽章時附上「,3 則未讀」或「,有新通知」;視覺上的徽章與展開標籤對輔助科技隱藏,避免重複朗讀
  • 採 roving tabindex:只有選中的分頁在 Tab 順序中,←/→ 循環移動、Home/End 跳到首尾,移動同時選取(自動啟用)
  • 中央主按鈕是一般 button(不屬於 tablist),以項目標籤作為 aria-label;開啟 centerSelectable 且選中時設定 aria-current="page"
  • 所有按鈕皆為 type="button" 並有 focus-visible 外框
  • 使用者系統開啟「減少動態效果」時,圖示不彈出、底塊直接跳到位、徽章不縮放、標籤直接顯示