卡片與網格

Spotlight Card

游標聚光燈卡片:邊框光暈與更淡的背景泛光同步跟隨游標,滑出時淡出,多卡並排各自獨立。

把這個效果裝進你的專案

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

npx webberui@latest add spotlight-card

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

Spotlight Card 是用 React 與 Tailwind CSS 做的滑鼠跟隨光暈卡片(spotlight card/cursor glow card),光暈是 CSS radial-gradient 搭配 CSS 變數,不需要任何動畫函式庫。

Playground

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

320
編輯中的呼叫預設屬性
<SpotlightCard/>

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

適用情境

  • SaaS 首頁的功能介紹網格,每張卡片各自跟著游標亮起。
  • 部落格、作品集或模板列表的可點擊卡片,用光暈提示目前指到哪一張。
  • 深色主題的 Dashboard 統計卡或整合服務列表。
  • 不適合:想要卡片跟著游標做 3D 傾斜,改用 Tilt Card。

安裝

npx webberui@latest add https://webberui.com/r/spotlight-card.json

或在 components.json 設定 registries 後,改用 @webberui/spotlight-card 安裝。

使用

內容直接放進 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>

範例

功能介紹網格

多張卡片並排時各自獨立,不需要額外的共用狀態。

import { SpotlightCard } from "@/components/ui/spotlight-card";

const features = [
  { title: "即時同步", body: "多人同時編輯,變更在幾秒內出現在所有裝置。" },
  { title: "權限管理", body: "依專案設定檢視、編輯與管理員角色。" },
  { title: "稽核紀錄", body: "每一次修改都留下時間與操作者。" },
];

export function FeatureGrid() {
  return (
    <div className="grid gap-4 sm:grid-cols-3">
      {features.map((f) => (
        <SpotlightCard key={f.title}>
          <h3 className="text-sm font-semibold">{f.title}</h3>
          <p className="mt-2 text-sm text-neutral-500">{f.body}</p>
        </SpotlightCard>
      ))}
    </div>
  );
}

整張卡片可點擊

SpotlightCard 本身是 div,外層包一個 Next.js Link 就能讓整張卡片成為連結,鍵盤也能聚焦。

import Link from "next/link";
import { SpotlightCard } from "@/components/ui/spotlight-card";

<Link href="/templates/dashboard" className="block rounded-xl focus-visible:outline-2 focus-visible:outline-offset-2">
  <SpotlightCard className="h-full">
    <h3 className="text-sm font-semibold">後台模板</h3>
    <p className="mt-2 text-sm text-neutral-500">側欄導覽、資料表格與圖表頁。</p>
  </SpotlightCard>
</Link>

依主題切換光暈顏色

spotlightColor 接受任何 CSS 色值,也可以傳 CSS 變數,讓光暈跟著你的設計 token 走。

<SpotlightCard spotlightColor="var(--primary)" radius={200} className="max-w-sm">
  <h3 className="text-sm font-semibold">品牌色光暈</h3>
  <p className="mt-2 text-sm text-neutral-500">光暈顏色來自主題變數。</p>
</SpotlightCard>

Props

Prop型別預設值說明
spotlightColorstring淺色深灰/深色白光暈顏色,接受任何合法 CSS 色值
radiusnumber320光暈半徑(px)
childrenReact.ReactNode—卡片內容
classNamestring—附加到最外層容器的 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-fast token,預設 200ms):mouseenter 把 --wb-spot-opacity 設為 1、mouseleave 設回 0,兩層光暈同步淡出
  • 多卡並排各自獨立:所有變數都寫在各卡自己的容器上,不共享任何全域狀態
  • 預設光色以 class 定義(淺色模式深灰、深色模式白色),傳入 spotlightColor 時以 inline style 覆蓋兩者
  • 使用者系統開啟「減少動態效果」時光暈保留——它是跟隨游標的 hover 位置提示、並非自主播放的動畫,僅有 opacity 過渡;DOM 結構前後一致,無 SSR 水合差異
  • 觸控裝置沒有 hover,卡片以靜態邊框呈現,內容與互動不受影響;光暈層皆為 aria-hidden 且 pointer-events-none,不干擾輔助科技與點擊

常見問題

可以在 Next.js App Router 使用嗎?

可以。原始碼已有 "use client",在 Server Component 頁面直接 import 即可;伺服器與客戶端輸出的 DOM 結構相同,沒有 hydration 差異。

需要安裝 Motion 嗎?

不需要。這個元件只依賴 clsx 與 tailwind-merge(給 cn 用),光暈與淡入淡出都是 CSS。

游標移動很快時會不會造成大量 re-render?

不會。mousemove 直接用 style.setProperty 寫入 --wb-spot-x、--wb-spot-y 兩個 CSS 變數,不經過 React state。

怎麼改卡片的背景、內距或圓角?

className 加在最外層容器上,可以控制寬高與排版;內層卡片的 bg-white p-6 dark:bg-neutral-900 與圓角寫在原始碼裡,複製下來後直接修改即可。

手機上會怎樣?

觸控裝置沒有 hover,卡片會以靜態的 1px 邊框顯示,內容與點擊行為不受影響。