WebberUI

Feature Section Set

一份特色資料、三種落地版面——不對稱格狀、吸附對照捲動與等寬卡片列,切換 variant 即可套用。

載入預覽⋯

Playground

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

3
0.08
<FeatureSectionSet />

安裝

npx shadcn@latest add https://webberui.com/r/feature-section-set.json

或在 components.json 設定 registries 後,改用 @webberui/feature-section-set 安裝。

安裝依賴後,從 registry JSON(/r/feature-section-set.jsonfiles[0].content)複製 feature-section-set.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion clsx tailwind-merge

圖示為選用,示範中的 ZapLayers 等來自 lucide-react

使用

三種版面共用同一份 features 陣列,切換 variant 即可切換樣式:

import { Zap, Layers, Sparkles } from "lucide-react";
import { FeatureSection, type Feature } from "@/components/ui/feature-section-set";

const features: Feature[] = [
  { title: "即開即用", description: "一行指令落地。", icon: <Zap /> },
  { title: "語意化 token", description: "整站語氣一致。", icon: <Layers /> },
  { title: "動畫優先", description: "講究的過場。", icon: <Sparkles /> },
];

<FeatureSection
  variant="bento"
  eyebrow="為什麼選我們"
  title="專為動畫打造"
  features={features}
/>

三種版面

  • bento:不對稱格狀。用 colSpan / rowSpan(1–4)讓部分特色橫跨或縱跨多格,進場時逐張 stagger 浮現,hover 微微抬起。
  • scroll:吸附對照捲動(Pro)。左側視覺面板吸附(sticky),右側特色隨捲動逐段高亮;面板依進度交叉淡入對應的 media,並累積進度指示。每個特色可點擊捲回定位。
  • cards:等寬卡片列。最單純的一列特色卡,同樣具備 stagger 進場與 hover 抬升。

對照捲動與捲動容器

scroll 版面以 useScroll 換算作用中的特色索引。若捲動發生在巢狀 overflow-y: auto 容器(如上方示範)內,傳入該容器的 container ref;預設以視窗為捲動容器:

const scrollerRef = React.useRef<HTMLDivElement>(null);

<div ref={scrollerRef} className="h-[400px] overflow-y-auto">
  <FeatureSection
    variant="scroll"
    features={features}   // 每個特色帶 media 供面板顯示
    container={scrollerRef}
    stickyTop={16}
  />
</div>

版面欄數以容器查詢(@container)決定,寬度取自元件自身而非視窗,因此在窄容器或手機上會自動退回單欄堆疊。

Props

FeatureSection

Prop型別預設值說明
featuresFeature[]特色資料陣列,三種樣式共用
variant"bento" | "scroll" | "cards""bento"版面樣式
eyebrowReact.ReactNode標題上方的小標
titleReact.ReactNode區塊主標題
descriptionReact.ReactNode區塊描述
columnsnumber3bento / cards 在寬版面時的欄數(1–4)
stickyTopnumber96scroll 吸附面板距容器頂端的距離(px)
containerReact.RefObject<HTMLElement | null>scroll 巢狀捲動容器 ref;預設以視窗為捲動容器
staggernumber0.08卡片進場的逐項間隔(秒)
oncebooleantrue只在第一次進入視口時播放進場動畫
classNamestring附加到最外層 <section> 的 class

Feature

Prop型別預設值說明
titleReact.ReactNode特色標題
descriptionReact.ReactNode特色描述文字
iconReact.ReactNode標題前的圖示(會自動縮放為 20px)
mediaReact.ReactNodescroll 樣式作用中時,吸附面板顯示的視覺內容
colSpannumber1bento 橫向跨欄數(1–4,僅寬版面生效)
rowSpannumber1bento 縱向跨列數(1–4,僅寬版面生效)
idstring錨點 id,套用在該特色外層容器
classNamestring附加到該特色卡片/區塊的 class

細節

  • 三種版面共用同一份資料,切換 variant 就換版面——特色文案不必為不同區塊重寫
  • scroll 沿用 card-stack-scrolluseScroll(container / target) 慣例,並以 useMotionValueEvent 換算作用中索引,僅在索引改變時觸發重繪
  • 吸附面板以 position: sticky 完成(版面而非 scroll 事件驅動),對應 mediaAnimatePresence 交叉淡入
  • 欄數與跨格皆走容器查詢(@container + @lg: 變體),響應以元件寬度為準而非視窗寬度

可及性

  • 使用者系統開啟「減少動態效果」時,進場、hover、交叉淡入與平滑捲動皆停用,scroll 的吸附版面與作用中對照仍保留(屬版面而非動效)
  • scroll 每個特色是原生 <button>:鍵盤可聚焦、Enter 觸發捲回定位,作用中項目標記 aria-current
  • 純裝飾的圖示與吸附視覺面板標記 aria-hidden,標題以語意化 <h2> / <h3> 呈現

On this page