WebberUI

二十四節氣時間軸(React)

以二十四節氣為主體的橫向時間軸 React 元件:依日期定位當前節氣、距下一節氣倒數、四季色帶與物候飲食短句卡;內建 21 世紀近似公式計算交節日期,並具名匯出 getSolarTerms 與 currentSolarTerm,可用曆書值覆寫。

適合茶、農產、養生、日曆型網站的內容元件。24 個節氣依序排在一條可橫向捲動的軌道上,依季節分成春綠、夏朱、秋金、冬青四段色帶;元件依 date(預設今天,掛載後才取得)定位當前節氣——該節點放大、呼吸光暈並自動捲到可視範圍。上方摘要卡顯示今日節氣、距下一節氣還有幾天,以及一句物候/飲食短句(內建 24 條繁中文案,可逐條覆寫)。交節日期用 21 世紀通用近似公式(寿星公式)計算,偶有 ±1 日誤差,可以曆書值覆寫;getSolarTerms()currentSolarTerm() 也單獨匯出,方便在其他地方算節氣。

載入預覽⋯
npx shadcn@latest add https://webberui.com/r/solar-terms-timeline.json

Playground

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

<SolarTermsTimeline />

安裝

npx shadcn@latest add https://webberui.com/r/solar-terms-timeline.json

或在 components.json 設定 registries 後,改用 @webberui/solar-terms-timeline 安裝。

使用

import {
  SolarTermsTimeline,
  getSolarTerms,
  currentSolarTerm,
} from "@/components/ui/solar-terms-timeline";

// 最簡用法:不給 date 就在掛載後定位「今天」
<SolarTermsTimeline onSelect={(term) => console.log(term.name, term.date)} />

// 指定日期、橫排節氣名、以曆書值覆寫近似公式的 ±1 日誤差、覆寫短句
<SolarTermsTimeline
  date="2026-02-18"
  orientation="horizontal"
  terms={[{ name: "雨水", date: "2026-02-18" }]}
  descriptions={{ 雨水: "春茶預購開跑,濕冷天請多喝溫熱的茶。" }}
/>

// 計算函式可單獨使用
getSolarTerms(2026);
// [{ index: 0, name: "小寒", en: "Minor Cold", season: "winter", date: 2026-01-05 }, …共 24 筆]

const { current, next, daysUntilNext } = currentSolarTerm(new Date(2026, 7, 18));
// current.name === "立秋"、next.name === "處暑"、daysUntilNext === 5

Props

Prop型別預設值說明
dateDate | string今天(掛載後取得)定位用日期,字串格式 YYYY-MM-DD;未提供或解析失敗時於掛載後取「今天」,SSR 與首次渲染先顯示佔位狀態
yearnumberdate 的年份時間軸顯示哪一年的 24 節氣;與 date 年份不同時不點亮任何節點
termsSolarTermOverride[]以曆書值覆寫特定節氣的交節日期,修正近似公式的 ±1 日誤差
descriptionsRecord<string, string>內建 24 條繁中短句覆寫物候/飲食短句,鍵為節氣名;未覆寫的節氣沿用內建文案
orientation"vertical" | "horizontal""vertical"節點上節氣名的排版:直排或橫排
showSummarybooleantrue是否顯示上方摘要卡(今日/選中節氣、倒數、短句、回到今日)
locale"zh-TW" | "en""zh-TW"內建文案語系;en 時節點主標改為英文節氣名、中文名縮小顯示
labelsPartial<SolarTermsTimelineLabels>逐條覆寫文案,優先於 locale 的內建值
valuestring | null受控:目前選中的節氣名;null 代表跟隨今日節氣。不提供時為非受控模式
defaultValuestring非受控模式的初始選中節氣名
onSelect(term: SolarTerm) => void點選節點、鍵盤移動選取或按「回到今日」時回呼,附上該節氣資料
classNamestring透傳到最外層容器

SolarTerm

欄位型別預設值說明
indexnumber年內序,0 為小寒、23 為冬至
namestring節氣名(繁中)
enstring英文名,如 "Start of Spring"
season"spring" | "summer" | "autumn" | "winter"所屬季節:立春~穀雨為春、立夏~大暑為夏、立秋~霜降為秋、立冬~大寒為冬
dateDate交節日期(當地時間 00:00)

SolarTermOverride

欄位型別預設值說明
namestring要覆寫的節氣名,須為二十四節氣之一
datestring曆書日期,格式 YYYY-MM-DD;解析失敗時忽略該筆、沿用公式值

SolarTermStatus

currentSolarTerm(date, terms?) 的回傳值:

欄位型別預設值說明
currentSolarTerm該日所處的節氣;小寒之前(1 月初)為去年冬至
nextSolarTerm下一個節氣;冬至之後為明年小寒
daysUntilNextnumber距下一節氣的天數,交節當日為 0
daysSinceStartnumber進入目前節氣已幾天,交節當日為 0

SolarTermsTimelineLabels

labels 可覆寫的文案欄位;含 {name}{days}{n} 佔位符的欄位會在渲染時代換:

欄位型別預設值說明
timelinestring"二十四節氣時間軸"區塊(role="region")的無障礙名稱
termsstring"二十四節氣"節點群組(role="radiogroup")的無障礙名稱
currentstring"今日節氣"摘要卡標題:顯示今日節氣時
selectedstring"節氣"摘要卡標題:顯示使用者點選的其他節氣時
nextUpstring"下一節氣"倒數區標題
dayUnitstring"天"天數單位(單數)
daysUnitstring"天"天數單位(複數)
daysUntilstring"距「{name}」還有 {days} 天"選中未來節氣時的距離文案
daysAgostring"「{name}」已過 {days} 天"選中過去節氣時的距離文案
isTodaystring"今天正是「{name}」交節之日"定位日期恰為交節日時的文案
ordinalstring"第 {n} 節氣"節氣序號
backToTodaystring"回到今日"回到今日節氣的按鈕文字
pendingstring"正在取得今天的日期…"掛載前尚未取得日期時的佔位文字
currentMarkstring"目前節氣"節點 aria-label 中「目前節氣」的註記
spring / summer / autumn / winterstring"春" / "夏" / "秋" / "冬"色帶起點與摘要卡季節籤的季節名

getSolarTerms(year, overrides?)

getSolarTerms(year: number, overrides?: SolarTermOverride[]): SolarTerm[]——回傳該年 24 個節氣(小寒起、冬至止),依寿星公式計算,2001–2100 年準確度最佳。傳入 overrides 可用曆書值取代特定節氣的日期。

currentSolarTerm(date, terms?)

currentSolarTerm(date: Date, terms?: SolarTerm[]): SolarTermStatus——找出某日所處節氣、下一節氣與距離天數。terms 可傳入該年(已覆寫過的)節氣清單,未傳時依公式計算;跨年的「去年冬至」與「明年小寒」一律用公式算。

另外具名匯出常數 SOLAR_TERM_NAMES(24 個節氣名,依年內順序)與 SOLAR_TERM_DESCRIPTIONS(內建 24 條短句,鍵為節氣名),以及 SolarTermSeason 型別。

細節

  • 日期公式:日 = int(Y × 0.2422 + C) − L。Y 為西元年後兩位(2001–2100 → 1–100),C 為各節氣的 21 世紀常數(小寒 5.4055、大寒 20.12、立春 3.87、雨水 18.73、驚蟄 5.63、春分 20.646、清明 4.81、穀雨 20.1、立夏 5.52、小滿 21.04、芒種 5.678、夏至 21.37、小暑 7.108、大暑 22.83、立秋 7.5、處暑 23.13、白露 7.646、秋分 23.042、寒露 8.318、霜降 23.438、立冬 7.438、小雪 22.36、大雪 7.18、冬至 21.94)。L 為閏年修正:1、2 月的節氣(小寒、大寒、立春、雨水)用 int((Y − 1) / 4),其餘用 int(Y / 4)——1、2 月尚未經過當年 2/29,閏日累積要少算一年;若一律用同一個 L,每逢閏年就有一批節氣整批差一天
  • ±1 日誤差:近似公式偶爾與曆書差一天(已知如 2026 雨水、2016 小暑、2021 冬至等),正式產品請用 terms 以曆書值覆寫;示範與 playground 都是公式值
  • 跨年:時間軸是循環的——1 月初「目前節氣」其實是去年冬至,元件仍會點亮本年的冬至節點;冬至之後的「下一節氣」是明年小寒,倒數天數會正確跨年
  • 選取與摘要卡:未選取時摘要卡顯示今日節氣與「距下一節氣 N 天」;點選其他節點後改顯示該節氣、距今幾天前/後與「回到今日」按鈕。valuenull 代表跟隨今日節氣,受控時請在 onSelect 中同步
  • 自動捲動:只捲動時間軸自己的水平捲軸(計算 offsetLeft 後對軌道 scrollTo),不用 scrollIntoView——後者會連整頁一起捲,元件在視窗外時整頁會跳
  • SSR:未提供 date 時,伺服器端與首次渲染只列 24 個節氣名、不算日期、摘要卡顯示佔位文字;掛載後才取今天並填入日期,節點高度預留、不跳版

可及性

  • 最外層為 role="region",以視覺隱藏的標題(labels.timeline)命名;軌道為 role="radiogroup",24 個節點是 type="button"role="radio" 的原生按鈕,aria-checked 標示使用者的選取、aria-current="date" 標示今日節氣,aria-label 含節氣名、日期與「目前節氣」註記
  • 鍵盤:roving tabindex——只有目前節點可 Tab 進入;方向鍵(左右/上下)在 24 個節點間循環移動並即時選取,HomeEnd 跳到小寒/冬至,焦點移動時軌道跟著捲動
  • 摘要卡的短句置於 aria-live="polite" 區域,切換節氣時會被螢幕閱讀器朗讀;軌道以 aria-describedby 指向摘要卡
  • 季節色帶與光暈皆為 aria-hidden 裝飾;季節不只靠顏色區分——每段色帶起點標有季節名,摘要卡的季節籤也帶文字與圖示
  • 使用者系統開啟「減少動態效果」時,停用當前節點的呼吸光暈(改為靜態淡色光圈)、節點縮放與短句淡入改為即時切換,自動捲動也改用 behavior: "auto" 直接跳到位置

本頁目錄