Control Center Panel
玻璃模組控制網格,長按任一方塊原地彈簧放大為精細控制卡(滑桿、分段切換),背景同步模糊下沉,放開回彈歸位。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
2
<ControlCenterPanel />
安裝
npx shadcn@latest add https://webberui.com/r/control-center-panel.json或在 components.json 設定 registries 後,改用 @webberui/control-center-panel 安裝。
安裝依賴後,從 registry JSON(/r/control-center-panel.json 的 files[0].content)複製 control-center-panel.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
import {
ControlCenterPanel,
ControlTile,
} from "@/components/ui/control-center-panel";
const [brightness, setBrightness] = React.useState(72);
const [appearance, setAppearance] = React.useState("auto");
<ControlCenterPanel columns={2}>
<ControlTile
id="brightness"
label="亮度"
icon={<Sun />}
value={brightness}
onValueChange={setBrightness}
formatValue={(v) => `${v}%`}
/>
<ControlTile
id="appearance"
label="外觀"
icon={<Palette />}
control="segmented"
value={appearance}
onValueChange={setAppearance}
options={[
{ label: "淺色", value: "light" },
{ label: "深色", value: "dark" },
{ label: "自動", value: "auto" },
]}
/>
</ControlCenterPanel>;Props
ControlCenterPanel
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
columns | number | 2 | 網格欄數(2–4) |
value | string | null | — | 受控模式:目前展開的 tile id(null 為全部收合) |
defaultValue | string | null | null | 非受控模式的初始展開 id |
onValueChange | (id: string | null) => void | — | 展開/收合變更時觸發 |
className | string | — | 覆蓋面板容器樣式 |
children | ReactNode | — | 放入 ControlTile 子元件 |
ControlTile(共用)
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | tile 唯一識別,面板以此協調「同時僅一個展開」 |
label | string | — | 標題(如「亮度」) |
icon | ReactNode | — | 左上角圖示,建議傳 lucide-react 圖示 |
control | 'slider' | 'segmented' | 'slider' | 控制型別 |
onValueChange | (value) => void | — | 數值/選擇變更時觸發 |
className | string | — | 覆蓋 tile 樣式 |
ControlTile — control="slider"
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | number | — | 目前數值(受控) |
min | number | 0 | 最小值 |
max | number | 100 | 最大值 |
step | number | 1 | 級距 |
formatValue | (v: number) => string | (v) => `${v}` | compact 讀數與展開卡的顯示格式化 |
ControlTile — control="segmented"
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | string | — | 目前選中的 value(受控) |
options | { label: ReactNode; value: string }[] | — | 分段選項,等寬排列 |
細節
- 長按展開:pointer 按住方塊超過約 380ms 才展開;按住期間方塊微幅縮下蓄勢,提前放開會以 spring 回彈歸位(不觸發展開)
- 原地形變:方塊與展開卡共用
layoutId,以減速回彈 spring 從原格位無縫放大為精細控制卡;一次僅一個 tile 展開 - 背景下沉:展開時整面網格被半透明遮罩覆蓋並
backdrop-blur模糊,營造背景後退聚焦的層次 - 精細滑桿:展開卡內的滑桿支援 pointer 拖曳與鍵盤(方向鍵 ±
step、PageUp/Down±10%、Home/End到端點),填充與滑鈕以 spring 追隨 - 分段切換:等寬選項,高亮以索引推算位置滑動切換(避開巢狀 layout 動畫),方向鍵可循環切換
- 收合:點背景遮罩或按
Esc收合,展開卡以相同 spring 形變回原格位
可及性
- 方塊為
role="button"、aria-haspopup="dialog"、aria-expanded;Enter/Space可直接展開(鍵盤操作不需長按) - 展開卡為
role="dialog"aria-modal,開啟時焦點移入卡片、網格加上inert移出 tab 序,收合後焦點還給原方塊 - 滑桿為
role="slider"具aria-valuemin/max/now與aria-valuetext;分段為role="radiogroup"/role="radio"並以aria-checked標記 - 使用者系統開啟「減少動態效果」時:長按展開與所有控制功能完全保留,僅移除形變位移與蓄勢縮放,改為短暫淡入淡出