WebberUI

Pricing Section

完整定價區塊——標頭、月繳/年繳切換、spring 補間價格與主打方案,內建可展開的常見問題手風琴,一次進場 stagger 浮現。

載入預覽⋯

Playground

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

<PricingSection />

安裝

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

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

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

npm install motion clsx tailwind-merge lucide-react

使用

import {
  PricingSection,
  type PricingSectionPlan,
  type PricingFaqItem,
} from "@/components/ui/pricing-section";

const plans: PricingSectionPlan[] = [
  {
    name: "入門",
    description: "適合個人 side project",
    monthly: 0,
    yearly: 0,
    features: ["3 個專案", "社群支援", "1GB 儲存空間"],
    cta: "免費開始",
  },
  {
    name: "專業",
    description: "適合成長中的團隊",
    monthly: 24,
    yearly: 230,
    features: ["無限專案", "優先支援", "50GB 儲存空間", "進階分析"],
    highlighted: true,
  },
  {
    name: "企業",
    monthly: 60,
    yearly: 600,
    features: ["專屬客戶經理", "SSO / SAML", "無限儲存空間"],
    cta: "聯絡我們",
  },
];

const faqs: PricingFaqItem[] = [
  { question: "可以隨時更換方案嗎?", answer: "當然,升級立即生效。" },
  { question: "年繳有折扣嗎?", answer: "切換到年繳最高可省下約 20%。" },
];

<PricingSection
  eyebrow="定價"
  title="簡單透明的定價"
  description="隨團隊成長彈性升級,隨時可取消。"
  plans={plans}
  faqs={faqs}
  currency="$"
  onSelectPlan={(plan) => console.log(plan.name)}
/>;

計費週期切換由元件內部管理——monthlyyearly 各填「該週期的實際金額」即可,折扣標籤自動以年繳相對「月繳 ×12」的節省比例計算。faqs 為選填,提供時於方案下方顯示手風琴;未提供則整個 FAQ 區塊不渲染。

Props

PricingSection

Prop型別預設值說明
plansPricingSectionPlan[]方案清單,並排顯示
eyebrowReactNode標頭上方的小標籤
titleReactNode"選擇適合你的方案"區塊主標題
descriptionReactNode區塊副標描述
faqsPricingFaqItem[]常見問題清單,提供時顯示手風琴
faqTitleReactNode"常見問題"常見問題區塊標題
currencystring"$"幣別符號,接在價格數字前
defaultCycle"monthly" | "yearly""monthly"初始計費週期
faqAllowMultiplebooleanfalse是否允許 FAQ 同時展開多項
oncebooleantrue只在第一次進入視口時播放進場動畫
onSelectPlan(plan) => void點擊方案 CTA 時觸發,回傳該方案
classNamestring附加到最外層 <section> 的 class

PricingSectionPlan

欄位型別說明
namestring方案名稱
descriptionstring方案簡短說明(可選)
monthlynumber月繳價格(每月金額)
yearlynumber年繳價格(每年金額),用來計算折扣
featuresstring[]特色列表,每列前綴一個 Check 圖示
highlightedboolean標記為主打方案:卡片放大、高亮並顯示徽章(可選)
badgestring主打徽章文字,預設「最受歡迎」(可選)
ctastringCTA 按鈕文字,未指定時為「開始使用」(可選)

PricingFaqItem

欄位型別說明
questionstring問題
answerReactNode答案,可為純文字或任意節點

細節

  • 進場 stagger:方案卡片與 FAQ 區塊以 whileInView 觸發,卡片依序淡入上浮,只在進入視口時播放
  • 週期切換器:月繳/年繳為 segmented control,選中底塊以 Motion layoutId 共享佈局在兩檔之間 spring 滑動
  • 價格 spring 補間:切換週期時,價格以 MotionValue 直接寫入 DOM(不觸發 React re-render)spring 過渡到新值,千分位、捨入到整數
  • 折扣標籤:年繳模式下若年繳價低於「月繳 ×12」,於價格下方以 AnimatePresence 淡入「年繳省 N%」,置於固定高度插槽不推擠版面
  • FAQ 手風琴:以 AnimatePresenceheight: auto 補間展開/收合,箭頭同步旋轉;預設單開(展開新項自動收合前一項),faqAllowMultiple 可切為多開

可及性

  • 使用者系統開啟「減少動態效果」時,進場動畫、底塊 layoutId 滑動、價格補間、折扣淡入與 FAQ 展開全部停用並直接呈現最終狀態(首渲染與 SSR 一致,掛載後才切換靜態)
  • 整個區塊以 <section aria-labelledby> 綁定主標題;切換器為 role="group"aria-label,選項以 aria-pressed 標示目前週期
  • 價格區塊帶 aria-label(含幣別、金額與週期),補間中的滾動數字 aria-hidden,螢幕閱讀器只朗讀最終值
  • FAQ 每項為 aria-expanded / aria-controls 按鈕,展開內容為 role="region" 並以 aria-labelledby 綁回問題;特色與箭頭圖示皆 aria-hidden

On this page