頁面區塊 Sections

墨色山脊主視覺

層疊的墨色山脊曲線由程式產生並逐層描繪,標題文字先描邊再填色,捲動時山脊分層視差。

首頁主視覺區塊:上半部是小標、標題、說明與兩顆 CTA,下半部是一整幅由程式產生的墨色山脊。山脊由遠到近逐層描出,遠層淺、近層深,最近一層帶一條強調色細線;每層描完後下方淡淡填上同色。標題先以描邊字出現,第一條山脊描完時由下往上填滿實色。捲動頁面時,近層上移較多、遠層較少,形成分層視差。換一個 seed 就是另一座山。

把這個效果裝進你的專案

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

npx webberui@latest add ink-ridgeline-hero

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

Playground

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

7
5
1400
編輯中的呼叫預設屬性
<InkRidgelineHero/>

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

安裝

npx webberui@latest add https://webberui.com/r/ink-ridgeline-hero.json

或在 components.json 設定 registries 後,改用 @webberui/ink-ridgeline-hero 安裝。

使用

import { InkRidgelineHero } from "@/components/ui/ink-ridgeline-hero";

<InkRidgelineHero
  eyebrow="嵐線戶外 · 秋季步道指南"
  title="把週末留給山的稜線"
  subtitle="一百二十條步道的海拔、坡度與補水點整理成一張路線卡。"
  seed={7}
  layers={5}
  primaryAction={{ label: "找附近的步道", href: "/trails" }}
  secondaryAction={{ label: "看路線卡範例", href: "#routes" }}
/>

放在巢狀捲動容器內

預設追蹤的是視窗的捲動。若元件放在固定高度的 overflow-y-auto 容器內,請把該容器的 ref 傳給 container。山脊的視差位移跟著主視覺在容器內的捲動進度走。

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

<div ref={scrollerRef} className="h-[400px] overflow-y-auto">
  <InkRidgelineHero container={scrollerRef} />
</div>

以整個視窗為捲動容器時可省略 container,行為與原本相同。

Props

Prop型別預設值說明
titleReactNode—主標題(必填);描邊效果只是視覺,文字始終是可朗讀的真文字
eyebrowReactNode—標題上方的小標
subtitleReactNode—標題下方的副標
primaryActionInkRidgelineHeroAction—主要 CTA(背景為強調色)
secondaryActionInkRidgelineHeroAction—次要 CTA(外框樣式)
as"h1" | "h2""h1"標題層級
minHeightnumber560區塊最小高度(px)
seednumber7山脊形狀的決定性種子;同一個 seed 永遠畫出同一組山
layersnumber5山脊層數,由遠到近,限制在 3–7
align"left" | "center""left"文字對齊
strokeTitlebooleantrue標題先以描邊出現、第一條山脊描完時由下往上填滿實色
drawnumber—每層山脊的描繪時長(ms),寫入 --wb-ink-ridgeline-hero-draw;未提供時沿用 CSS 變數(預設 1400ms)
durationnumber—文字進場時長(ms),寫入 --wb-ink-ridgeline-hero-duration;未提供時沿用 CSS 變數(預設 600ms)
containerRefObject<HTMLElement>—巢狀捲動容器的 ref;省略則以視窗為捲動容器
classNamestring—併入根 section 的 class

InkRidgelineHeroAction

欄位型別預設值說明
labelstring—按鈕文字
hrefstring—提供時渲染為連結 a,否則為 button
onClick(event: React.MouseEvent<HTMLElement>) => void—點擊回呼

細節

  • 山脊形狀:每層以 seed 產生的 1D value noise(四個八度疊加)取 52 個點,再以 Catmull-Rom 轉成平滑的 cubic Bézier。整個過程是決定性的,伺服器與瀏覽器畫出同一座山,不會有 hydration 落差。
  • 描繪:每條線以 pathLength 正規化後用 stroke-dashoffset 從 1 走到 0,曲線 cubic-bezier(0.65,0,0.35,1),層間錯開 180ms;描完後填色在 500ms 內淡入。
  • 標題填色:用 -webkit-text-stroke 畫出描邊,字面透明,再以 background-clip: text 搭配 background-size 由下往上填滿,時間點對齊第一條山脊描完。
  • 捲動視差:以 useScroll 追蹤區塊本身,近層上移到 -60px、遠層 -15px;填色往下延伸,上移時底部不會露出空隙。
  • 可覆寫的 CSS 變數:--wb-ink-ridgeline-hero-draw(描繪時長)、--wb-ink-ridgeline-hero-duration(文字進場時長)、--wb-ink-ridgeline-hero-accent(強調色,預設 #0d9488,暗色 #2dd4bf)。
  • 高度由內容與 minHeight 決定,元件本身不使用視窗高度單位;窄螢幕時山脊裁切左右而不壓扁線條。

可及性

  • 根元素是 section,以 aria-labelledby 指向標題;標題層級由 as 決定。
  • 山脊 SVG 標記 aria-hidden,螢幕閱讀器不會讀到裝飾。
  • 標題的描邊與填色只是視覺樣式,文字始終是真文字,朗讀與選取都不受影響。
  • CTA 是 a 或 type="button",有清楚的 focus-visible 外框。
  • 系統開啟「減少動態效果」時,山脊直接以完整構圖呈現、不逐層描繪,標題直接是實色,文字進場改為 150ms 淡入,捲動視差固定在終態;此設定在首次繪製即以 CSS 媒體查詢生效。