Spotlight Card
游標聚光燈卡片:邊框光暈與更淡的背景泛光同步跟隨游標,滑出時淡出,多卡並排各自獨立。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
320
<SpotlightCard />
安裝
npx shadcn@latest add https://webberui.com/r/spotlight-card.json或在 components.json 設定 registries 後,改用 @webberui/spotlight-card 安裝。
安裝依賴後,打開 spotlight-card.json,把 files[0].content 的內容複製到你的 components/ui/spotlight-card.tsx:
npm install clsx tailwind-merge使用
內容直接放進 children,尺寸與佈局寫在 className 上:
import { SpotlightCard } from "@/components/ui/spotlight-card";
<SpotlightCard className="max-w-sm">
<h3 className="text-sm font-semibold">標題</h3>
<p className="text-sm text-neutral-500">游標移入卡片,光暈會跟著走。</p>
</SpotlightCard>自訂光暈顏色與半徑:
<SpotlightCard spotlightColor="rgba(59,130,246,0.6)" radius={240}>
<h3 className="text-sm font-semibold">品牌色光暈</h3>
<p className="text-sm text-neutral-500">任何合法 CSS 色值都可以。</p>
</SpotlightCard>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
spotlightColor | string | 淺色深灰/深色白 | 光暈顏色,接受任何合法 CSS 色值 |
radius | number | 320 | 光暈半徑(px) |
children | React.ReactNode | — | 卡片內容 |
className | string | — | 附加到最外層容器的 class |
其餘 props(如 onClick、id)全部透傳到最外層 div。
細節
- 效能:mousemove 不經 React state。 座標直接以
ref.style.setProperty寫入 CSS 變數--wb-spot-x/--wb-spot-y,再由radial-gradient讀取,游標移動再快也不觸發 re-render - 邊框光暈的實作是「1px padding 容器」:外層鋪中性底色作為靜態邊框,其上疊一層跟隨游標的 radial-gradient,內層卡片蓋住中央,漸層只從 1px 環露出
- 背景泛光與邊框光暈共用同一組座標變數,半徑放大 1.75 倍、透明度減半,形成更淡的大範圍光暈
- 淡入淡出走 opacity 過渡(
--wb-duration-fasttoken,預設 200ms):mouseenter把--wb-spot-opacity設為 1、mouseleave設回 0,兩層光暈同步淡出 - 多卡並排各自獨立:所有變數都寫在各卡自己的容器上,不共享任何全域狀態
- 預設光色以 class 定義(淺色模式深灰、深色模式白色),傳入
spotlightColor時以 inline style 覆蓋兩者 - 使用者系統開啟「減少動態效果」時光暈保留——它是跟隨游標的 hover 位置提示、並非自主播放的動畫,僅有 opacity 過渡;DOM 結構前後一致,無 SSR 水合差異
- 觸控裝置沒有 hover,卡片以靜態邊框呈現,內容與互動不受影響;光暈層皆為
aria-hidden且pointer-events-none,不干擾輔助科技與點擊