{item.question}
-{item.answer}
+{item.answer}
diff --git a/.changeset/converge-uiux-rate-basis.md b/.changeset/converge-uiux-rate-basis.md new file mode 100644 index 000000000..c4a865ebe --- /dev/null +++ b/.changeset/converge-uiux-rate-basis.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': minor +--- + +換算結果新增計價基準標示(臺銀賣出/買入、換錢所等六種基準 pill),收藏與全幣種清單標示臺銀賣出價基準與 TWD 單位;計算機輸入時即時顯示目標幣別換算預覽;換算結果加入螢幕閱讀器 aria-live 宣告;多幣別收藏星與字級補足無障礙觸控目標與對比下限。 diff --git a/.changeset/fix-nitro-theme-ssot.md b/.changeset/fix-nitro-theme-ssot.md new file mode 100644 index 000000000..ff284e544 --- /dev/null +++ b/.changeset/fix-nitro-theme-ssot.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +對齊 nitro 主題色票 SSOT:themes.ts primary 從 #00D4FF 改為 #0096E6,與 index.css 保持一致 diff --git a/.changeset/fix-ratewise-pwa-ios-eviction.md b/.changeset/fix-ratewise-pwa-ios-eviction.md new file mode 100644 index 000000000..4322d4802 --- /dev/null +++ b/.changeset/fix-ratewise-pwa-ios-eviction.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +修復 iOS PWA precache 驅逐後 3s timeout 導致在線用戶看到 offline.html 的假離線問題,改用 precache-first 冷啟動策略 diff --git a/.changeset/quiet-breadcrumb-token-refactor.md b/.changeset/quiet-breadcrumb-token-refactor.md new file mode 100644 index 000000000..a442a70c0 --- /dev/null +++ b/.changeset/quiet-breadcrumb-token-refactor.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +收斂內容頁返回導覽、麵包屑與核心 UI shell 的 design token,改善 PWA 與小螢幕顯示穩定性。 diff --git a/.changeset/ratewise-a11y-touch-target-focus.md b/.changeset/ratewise-a11y-touch-target-focus.md new file mode 100644 index 000000000..f7c89f418 --- /dev/null +++ b/.changeset/ratewise-a11y-touch-target-focus.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +無障礙與操作體驗改善:評分視窗星星按鈕、開放資料頁複製按鈕、Email 連結與計算機關閉鈕補齊 44px 觸控目標與鍵盤焦點指示;小型標籤與代碼區塊圓角統一為設計系統規格。 diff --git a/.changeset/ratewise-artifact-ssot.md b/.changeset/ratewise-artifact-ssot.md new file mode 100644 index 000000000..c2440f801 --- /dev/null +++ b/.changeset/ratewise-artifact-ssot.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +Clarify generated artifact buckets and remove local build report files from tracked source. diff --git a/.changeset/ratewise-calculator-preview-derived-ssot.md b/.changeset/ratewise-calculator-preview-derived-ssot.md new file mode 100644 index 000000000..d1afd8d89 --- /dev/null +++ b/.changeset/ratewise-calculator-preview-derived-ssot.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +內部收斂:計算機即時預覽改以衍生值(useMemo)取代冗餘狀態與同步 effect,並將計價基準的 i18n key 集中為單一來源。對外顯示與換算行為不變,僅提升可維護性與一致性。 diff --git a/.changeset/ratewise-currency-route-registry.md b/.changeset/ratewise-currency-route-registry.md new file mode 100644 index 000000000..1ccd9aa45 --- /dev/null +++ b/.changeset/ratewise-currency-route-registry.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +Consolidate currency landing route registration behind a registry with parity checks. diff --git a/.changeset/ratewise-data-pr-governance.md b/.changeset/ratewise-data-pr-governance.md new file mode 100644 index 000000000..fad31a664 --- /dev/null +++ b/.changeset/ratewise-data-pr-governance.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +Strengthen scheduled rate data update governance by requiring generated data PRs to pass branch protection before merge. diff --git a/.changeset/ratewise-design-token-ssot.md b/.changeset/ratewise-design-token-ssot.md new file mode 100644 index 000000000..0770af7a7 --- /dev/null +++ b/.changeset/ratewise-design-token-ssot.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +收斂設計 Token 為語義化 SSOT:圓角與陰影全站統一為語義 token,恢復 Tailwind 標準預設值避免第三方整合風險 diff --git a/.changeset/ratewise-eslint-8593-redundant-assertions.md b/.changeset/ratewise-eslint-8593-redundant-assertions.md new file mode 100644 index 000000000..d58770f1a --- /dev/null +++ b/.changeset/ratewise-eslint-8593-redundant-assertions.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +移除 typescript-eslint 8.59.3 新規則標記的冗餘型別斷言(MiniTrendChart、exchangeRateService);內部 lint 清理,使用者無可見影響。 diff --git a/.changeset/ratewise-exchange-shop-ratemode-nav-header.md b/.changeset/ratewise-exchange-shop-ratemode-nav-header.md new file mode 100644 index 000000000..c0cf9153c --- /dev/null +++ b/.changeset/ratewise-exchange-shop-ratemode-nav-header.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +修正換錢所匯率模式選價:選「中間價」時正確以(買入+賣出)÷2 計算、選「賣出」時雙向採用賣出價,趨勢圖與多幣別列同步跟隨所選模式;內容頁頂部「返回+麵包屑」導覽改為不固定的圓角按鈕樣式,修復部分 iOS PWA 用戶頂部內容被遮擋的問題。 diff --git a/.changeset/ratewise-opendata-mobile-overflow.md b/.changeset/ratewise-opendata-mobile-overflow.md new file mode 100644 index 000000000..4e856b39b --- /dev/null +++ b/.changeset/ratewise-opendata-mobile-overflow.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +修正開放資料頁 API 端點路徑在小螢幕(320px 等窄視口)造成的水平溢出,長路徑現在會正確斷行。 diff --git a/.changeset/ratewise-pwa-shell-brand-sync.md b/.changeset/ratewise-pwa-shell-brand-sync.md new file mode 100644 index 000000000..2866c9e6d --- /dev/null +++ b/.changeset/ratewise-pwa-shell-brand-sync.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +PWA shell 品牌色同步至 Violet 主題,CDN 備援日誌降噪至 debug 等級 diff --git a/.changeset/ratewise-radius-ssot-guard.md b/.changeset/ratewise-radius-ssot-guard.md new file mode 100644 index 000000000..580d7c9d1 --- /dev/null +++ b/.changeset/ratewise-radius-ssot-guard.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +視覺一致性收斂:匯率卡趨勢圖底部圓角對齊卡片外框、骨架載入與小型元素圓角統一為設計系統規格,並新增圓角防回歸守門測試。 diff --git a/.changeset/ratewise-sw-bounded-nav.md b/.changeset/ratewise-sw-bounded-nav.md new file mode 100644 index 000000000..ec8b3accb --- /dev/null +++ b/.changeset/ratewise-sw-bounded-nav.md @@ -0,0 +1,5 @@ +--- +'@app/ratewise': patch +--- + +離線/弱網下載入更穩定,不再可能卡白屏。 diff --git a/.github/workflows/update-moneybox-rates.yml b/.github/workflows/update-moneybox-rates.yml index 20e61b8b5..b09d1c9dc 100644 --- a/.github/workflows/update-moneybox-rates.yml +++ b/.github/workflows/update-moneybox-rates.yml @@ -94,13 +94,26 @@ jobs: id: save-history if: steps.fetch-rates.outcome == 'success' run: | - CURRENT_DATE=$(TZ=Asia/Taipei date +%Y-%m-%d) - MONEYBOX_HISTORY_FILE="${MONEYBOX_HISTORY_DIR}/${CURRENT_DATE}.json" - mkdir -p "$MONEYBOX_HISTORY_DIR" if [[ ! -f "$MONEYBOX_FETCH_OUTPUT_FILE" ]]; then echo "❌ Current MoneyBox fetch snapshot missing: ${MONEYBOX_FETCH_OUTPUT_FILE}" exit 1 fi + # history 檔名 SSOT:直接採用資料本身宣告的首爾掛牌日(updateTime), + # 與 fetch script 的 date-rollover 判斷 (extractSeoulSnapshotDate) 同源, + # 避免 runner wall-clock 與資料日期在跨日視窗不一致。提取失敗時 fallback 首爾 wall-clock。 + CURRENT_DATE=$(node --input-type=module -e " + import { readFileSync } from 'node:fs'; + const { extractSeoulSnapshotDate } = await import('./scripts/fetch-moneybox-rates.js'); + const data = JSON.parse(readFileSync(process.env.MONEYBOX_FETCH_OUTPUT_FILE, 'utf8')); + const d = extractSeoulSnapshotDate(data); + if (d) process.stdout.write(d); + ") + if [[ ! "$CURRENT_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then + CURRENT_DATE=$(TZ=Asia/Seoul date +%Y-%m-%d) + echo "⚠️ 無法從資料提取首爾 snapshot date,fallback 至首爾 wall-clock: ${CURRENT_DATE}" + fi + MONEYBOX_HISTORY_FILE="${MONEYBOX_HISTORY_DIR}/${CURRENT_DATE}.json" + mkdir -p "$MONEYBOX_HISTORY_DIR" if [[ ! -f "$MONEYBOX_HISTORY_FILE" ]] || [[ -n "$(git status --short --untracked-files=all -- "$MONEYBOX_LATEST_FILE")" ]]; then cp "$MONEYBOX_FETCH_OUTPUT_FILE" "$MONEYBOX_HISTORY_FILE" echo "✅ MoneyBox history snapshot refreshed: ${MONEYBOX_HISTORY_FILE}" @@ -135,6 +148,9 @@ jobs: if [[ -n "$(git status --short --untracked-files=all -- "$MONEYBOX_HISTORY_DIR/")" ]]; then echo "changed=true" >> $GITHUB_OUTPUT fi + if [[ ! -f "$MONEYBOX_AGGREGATE_FILE" ]]; then + echo "changed=true" >> $GITHUB_OUTPUT + fi if [[ "$RETIRED_ALIASES_CHANGED" == "true" ]]; then echo "changed=true" >> $GITHUB_OUTPUT fi diff --git a/.gitignore b/.gitignore index a7e5f240d..10a3d9eb0 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,9 @@ squirrel.toml .agents/skills/*/references/ .agents/skills/*/AGENTS.md +# Third-party local skill bundles (tool-synced, not project source) +.agents/skills/impeccable/ + # AI tool local skill copies (synced from .agents/skills/) .claude/ .codex/ diff --git a/AGENTS.md b/AGENTS.md index e2a692f1b..a22822a8b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -823,5 +823,30 @@ Agent 在結案或提交時,應能提供下列證據(依任務適用性) --- +## Learned User Preferences + +- 偏好極簡 UI 設計:卡片與按鈕不加外框(border/outline),保持乾淨俐落 +- 多幣別轉換器中,非主幣項目使用極淺背景色 token,避免視覺突兀 +- 匯率顯示採 Google 模式:上方為原始幣、下方為目標幣,顯示買入價與其倒數,不使用「買入/賣出」術語 +- 匯率來源切換為三態(即期/現金/換錢所),無資料者灰色顯示並自動 fallback 至下一個可用來源 +- RateWise UI/UX 標竿為韓系金融 App(Toss、Wowpass),並行多面向審查追求高真度體驗 +- Kawaii 主題色票偏好較淺、較飽和粉嫩,避免暗沉色;Nitro/Ocean 等深色主題 primary 按鈕使用淺白字 +- 頁面資訊應精簡去重,避免重複雜亂堆疊;單幣別輸入應減少 Modal 閘門與多步摩擦 +- 所有修復需保持原子化,不得順便重構或加入不必要註解 +- 期望持續迭代直到完美收斂:監控 Codex review 並逐一解決、推送、驗證 + +## Learned Workspace Facts + +- `docs/prompt/UIUX.md` 為 UI/UX 變更的正式審查清單,用於審視未提交改動 +- `feat/ratewise-fintech-uiux-p0` 為最新 RateWise UI/UX 分支(含 governance 與計價基準 pill);若被 worktree 占用,開發/審查使用 `.claude/worktrees/ratewise-uiux-p0` +- 2026 UX 規格與 Phase 1 計畫見 `docs/superpowers/specs/` 與 `docs/superpowers/plans/` +- 品牌名稱 SSOT 為「HaoRate 匯率好工具」 +- RateWise 趨勢圖曾因 `TREND_CHART_DEFER_MS = 10000` 導致感知延遲,需保持 defer 時間在合理範圍 +- SEO 生產驗證三腳本組合:`verify-production-resources.mjs`(資源可達)→ `verify-all-apps.mjs`(語義)→ `verify-precache-assets.mjs`(PWA live) +- Codex review 收斂為標準工作流:使用 `pnpm review:codex:audit` 盤點 → `gh` 逐條回覆 → 標記 resolved +- 使用者會透過瀏覽器元素選取(browser_element)直接指定要修改的 UI 節點 + +--- + **最後更新**: 2026-05-02T09:00:00+0800 **版本**: v5.5(SEO 迭代 SOP 與監控治理補齊) diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 000000000..396be7d32 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,231 @@ +--- +name: RateWise +description: 台灣銀行牌告導向的安靜匯率換算工具 +colors: + background: '#F8FAFC' + surface: '#FFFFFF' + surface-elevated: '#F8FAFC' + surface-sunken: '#F1F5F9' + text: '#0F172A' + text-muted: '#64748B' + primary: '#7C3AED' + secondary: '#6366F1' + accent: '#8B5CF6' + border: '#E2E8F0' + info: '#0EA5E9' + success: '#22C55E' + warning: '#F59E0B' + destructive: '#DC2626' +typography: + display: + fontFamily: 'Inter, Noto Sans TC, system-ui, -apple-system, sans-serif' + fontSize: 'clamp(1.875rem, 4vw, 2.25rem)' + fontWeight: 700 + lineHeight: 1.2 + headline: + fontFamily: 'Inter, Noto Sans TC, system-ui, -apple-system, sans-serif' + fontSize: '1.5rem' + fontWeight: 700 + lineHeight: 1.333 + title: + fontFamily: 'Inter, Noto Sans TC, system-ui, -apple-system, sans-serif' + fontSize: '1.25rem' + fontWeight: 600 + lineHeight: 1.4 + body: + fontFamily: 'Inter, Noto Sans TC, system-ui, -apple-system, sans-serif' + fontSize: '1rem' + fontWeight: 400 + lineHeight: 1.6 + label: + fontFamily: 'Inter, Noto Sans TC, system-ui, -apple-system, sans-serif' + fontSize: '0.75rem' + fontWeight: 600 + lineHeight: 1.333 + letterSpacing: '0.16em' +rounded: + sm: '4px' + md: '6px' + lg: '8px' + card: '24px' + panel: '16px' + control: '16px' + icon: '12px' + compact: '8px' + pill: '999px' +spacing: + xs: '8px' + sm: '12px' + md: '16px' + lg: '24px' + xl: '32px' +components: + button-primary: + backgroundColor: '{colors.primary}' + textColor: '{colors.surface}' + rounded: '{rounded.lg}' + padding: '0 16px' + height: '44px' + button-secondary: + backgroundColor: '{colors.surface-elevated}' + textColor: '{colors.text}' + rounded: '{rounded.lg}' + padding: '0 16px' + height: '44px' + card-panel: + backgroundColor: '{colors.surface}' + textColor: '{colors.text}' + rounded: '{rounded.card}' + padding: '20px' + notification-surface: + backgroundColor: '{colors.surface}' + textColor: '{colors.text}' + rounded: '{rounded.lg}' + padding: '14px 24px' + list-row: + backgroundColor: '{colors.surface}' + textColor: '{colors.text}' + rounded: '{rounded.lg}' + padding: '12px 16px' +--- + +## Overview + +**Creative North Star: "The Quiet Exchange Desk"** + +RateWise 的預設視覺系統是一套安靜、克制、資訊優先的產品介面。它應該像使用者在付款前最後確認匯率的工作台,不像行情盤,也不像裝飾型 SaaS 首頁。畫面首先服務判讀速度,其次才是品牌辨識。 + +預設產品語法以 `zen` 風格為基準,其他 `nitro`、`kawaii`、`classic`、`ocean`、`forest` 僅作使用者可切換的外觀變體。所有變體都必須保留相同的資訊層級、相同的元件節奏與相同的互動語意,不能用造型改寫產品心智模型。 + +這套系統明確排斥加密交易平台式的霓虹高飽和、AI 樣板 SaaS 式的 glow 與漸層文字,以及生活風格工具式的過度情緒化語氣。它的辨識度來自安靜表面、清楚數字、穩定留白與一致詞彙,不來自特效。 + +Key Characteristics: + +- 冷靜、精準、可靠。 +- 預設使用 restrained color strategy,不做大面積裝飾性漸層。 +- 同一概念在首頁、收藏、多幣別、設定、SEO 內容頁使用同一種權重與元件語法。 +- 觸控優先,但桌面版要有足夠寬度與資訊節奏,不能像手機稿被放大。 + +## Colors + +整體色彩以 violet / indigo 品牌色搭配冷靜中性色為主,將主色集中在主要操作、狀態與導引,而不是大片情緒背景。 + +### Primary + +- **Exchange Violet** (`#7C3AED`): 主要 CTA、焦點與需要立即判讀的互動元素。預設不拿來鋪滿大面積背景。 + +### Secondary + +- **Indigo Signal** (`#6366F1`): 支援型資訊、次要狀態與品牌層次,用於輔助,不與 Primary 爭主導權。 + +### Tertiary + +- **Soft Violet Accent** (`#8B5CF6`): 僅用於小範圍高亮,例如通知裝飾、局部導引與互動後的柔性回饋。 + +### Neutral + +- **Ledger Mist** (`#F8FAFC`): 頁面背景,維持乾淨但不刺眼的工作台底色。 +- **Paper Surface** (`#FFFFFF`): 主卡片與主要容器背景。 +- **Raised Surface** (`#F8FAFC`): 次層容器、segmented controls、次要按鈕背景。 +- **Sunken Surface** (`#F1F5F9`): 按壓後或低階容器的收斂層次。 +- **Ink 900** (`#0F172A`): 主要文字、標題與高重要度數字。 +- **Slate Note** (`#64748B`): 次要說明、輔助文與低權重標籤。 +- **Rule Line** (`#E2E8F0`): 邊框、分隔與可讀但不搶戲的結構線。 + +### Named Rules + +**The Quiet Surface Rule.** 背景與容器先用中性層次解決階層,再考慮色彩。若同一畫面已經靠邊框、留白與標題完成分層,就不要再加漸層或 glow。 + +## Typography + +**Display Font:** Inter, Noto Sans TC, system-ui, -apple-system, sans-serif +**Body Font:** Inter, Noto Sans TC, system-ui, -apple-system, sans-serif +**Label/Mono Font:** ui-monospace, SFMono-Regular, Menlo, Monaco, monospace + +字體策略以高可讀性的無襯線系統為主,讓中英文與數字混排時仍保持穩定節奏。數值顯示、更新時間與版本等資料型內容,應優先使用 tabular numerals 或 monospace 輔助,而不是額外裝飾。 + +### Hierarchy + +- **Display** (700, `clamp(1.875rem, 4vw, 2.25rem)`, 1.2): 頁面主標題與少數需要建立主場景的首屏標題。 +- **Headline** (700, `1.5rem`, 1.333): 核心模組標題,例如主要卡片或內容頁區塊標題。 +- **Title** (600, `1.25rem`, 1.4): 次級區塊、卡片標題與清單模組標題。 +- **Body** (400, `1rem`, 1.6): 正文與說明文。內容型頁面的段落寬度維持在約 65 至 72 字元。 +- **Label** (600, `0.75rem`, 1.333, `0.16em`): eyebrow、區塊導引與輕量 metadata。只在需要建立節奏時使用大寫標籤,不可濫用。 + +### Named Rules + +**The Number First Rule.** 與匯率、金額、更新時間相關的資訊優先度高於裝飾型標題。若文字階層與數值判讀衝突,優先讓數值更清楚。 + +## Elevation + +RateWise 的深度語法以 tonal layering 為主,陰影為輔。絕大多數層次差異先靠 `surface`、`surface-elevated`、`surface-sunken` 解決,陰影只用來表達浮起、hover 或暫時性提示,不作常態性戲劇效果。 + +### Shadow Vocabulary + +- **Resting Card** (`shadow-card`): 預設卡片與主要內容面板,值由 `shadowTokens.values.card` 統一維護。 +- **Hover Lift** (`shadow-card-hover`): hover 後的輕微浮起,只作互動回饋。 +- **Transient Surface** (`shadow-floating`): 通知、tooltip、底部工作表與臨時浮層。 + +### Named Rules + +**The Lift Must Mean State Rule.** 若一個陰影不代表 hover、焦點、暫時提示或浮層,就不應存在。不要用大陰影補救階層不清的版面。 + +## Components + +### Buttons + +- **Shape:** 互動控制預設 `rounded-control`(16px),主要尺寸高度至少 `44px`,少數輕量操作可用膠囊型圓角。 +- **Primary:** `primary` 實底配 `surface` 文字,只用於明確主動作,例如更新、確認、開始轉換。 +- **Hover / Focus:** hover 允許極輕微上浮與陰影加深;focus 使用清楚的 `ring-primary`,不得用模糊光暈取代焦點樣式。 +- **Secondary / Ghost / Danger:** 次要按鈕用 `surface-elevated` 加邊框;ghost 只在低視覺權重工具列使用;danger 維持明確語義,但版面仍要克制。 + +### Chips + +- **Style:** 小尺寸、圓角、邊框明確,優先作為 eyebrow、狀態或輕量切換標籤,而不是厚重 badge。 +- **State:** 選中狀態主要依靠邊框、底色與文字色改變,不使用高飽和螢光效果。 + +### Cards / Containers + +- **Corner Style:** 主內容面板使用 `rounded-card`(24px),次層容器與互動列使用 `rounded-panel` / `rounded-control`(16px);只允許 pill 用於 chip、badge 或膠囊型控制。 +- **Background:** 主卡片用 `surface`,次層與安靜模組用 `surface-elevated`,不要在正式產品頁中使用玻璃卡。 +- **Shadow Strategy:** 預設使用 resting card 陰影;hover 或可拖曳狀態才升到更高層級。 +- **Border:** 絕大多數卡片都有 `border-border/70` 左右的結構線,取代彩色 accent stripe。 +- **Internal Padding:** 主要面板 `20px` 至 `24px`,輕量列項 `12px` 至 `16px`。 + +### Inputs / Fields + +- **Style:** 以乾淨背景、清楚邊界與穩定留白為主,不用擬物或發光效果。 +- **Focus:** focus 由 ring 與邊框色帶出,不改變版面尺寸。 +- **Error / Disabled:** 直接用語義色與可讀文字說明,不靠震動或炫目動畫表達。 + +### Navigation + +- **Top / Bottom Navigation:** 使用半透明背景與輕微 blur 只作可讀性補強,不是視覺主角。導覽本體要融入產品殼層。 +- **Segmented / Tabs:** 活動狀態使用 `surface-elevated`、文字加重與輕陰影,不用大片主色底。 + +### Notifications + +- **Style:** 更新通知、離線提示與評分提示統一使用安靜的 `surface` 浮層,不再使用品牌漸層底。 +- **Icon Treatment:** 狀態圖標放在小型 elevated 容器中,用 `primary` 或 `warning` 文字色表達狀態。 +- **Action Pattern:** 通知內的主要與關閉操作共用同一套 action token,避免各通知自成一格。 + +## Do's and Don'ts + +- **Do:** 先用字級、留白、邊框與表面層次建立階層,再決定是否需要色彩。 +- **Do:** 讓首頁、收藏、多幣別、設定與 SEO 內容頁共用同一套 panel、row、eyebrow 與 secondary CTA 語法。 +- **Do:** 保留 `prefers-reduced-motion`、清楚 focus ring、足夠對比與至少 44px 的觸控目標。 +- **Do:** 將 theme styles 視為外觀皮膚,不得改變資訊密度、元件語意或互動模型。 +- **Don't:** 不要使用漸層文字、彩色側邊條、裝飾性 glass、過量 glow、或沒有語義的大面積品牌漸層。 +- **Don't:** 不要把金融工具做成加密交易平台、AI 樣板 SaaS,或可愛生活風首頁。 +- **Don't:** 不要靠巢狀卡片與大陰影堆層級,也不要用 8 至 10px 當作常態正文。 +- **Don't:** 不要在不同頁面為相同概念發明第二套顏色、第二套間距或第二套按鈕語法。 + +## Engineering Decisions + +### Tailwind borderRadius Alias Override + +本專案刻意將 Tailwind 標準 `rounded-sm`/`md`/`lg`/`xl` 值上調至語義 token 對齊值(如 `lg` = 1rem 而非 Tailwind 預設 0.5rem),以確保遺漏遷移的 `rounded-lg` 不會產生舊值視覺殘留。此決策的前提是 RateWise 不引入依賴 Tailwind 預設 radius 值的第三方 UI 元件。若未來整合外部元件庫,需重新評估此 override 策略。 + +### Shadow Token 淺色模式限定 + +`shadowTokens` 的陰影基底色使用硬編碼 `rgb(15 23 42 / ...)` (slate-900),僅適用淺色模式。若未來支援深色模式,陰影值需改為 CSS variable 或主題條件值。 diff --git a/PRODUCT.md b/PRODUCT.md new file mode 100644 index 000000000..37a820fd1 --- /dev/null +++ b/PRODUCT.md @@ -0,0 +1,40 @@ +# Product + +## Register + +product + +## Users + +以台灣為主要使用情境的旅客、跨境消費者、自由工作者與小型商務使用者。 +他們通常在出國前、付款前或比價當下開啟 RateWise,希望用最短時間看懂真實換匯成本,而不是市場中間價。 + +## Product Purpose + +RateWise 提供以臺灣銀行牌告為核心的匯率換算體驗,重點是快速、可信、可重複使用。 +產品應在首頁、收藏、多幣別、歷史與 SEO 幣別頁之間維持一致心智模型,讓使用者能在手機與桌面上用最少操作完成換算、比較與回查。 + +## Brand Personality + +冷靜、精準、可靠。 +語氣應直接、節制、資訊優先,像成熟的金融工具,而不是行銷頁或加密貨幣儀表板。 + +## Anti-references + +- 不要像加密交易平台,避免霓虹、黑底高飽和、過度行情感。 +- 不要像 AI 樣板 SaaS,避免大量 glow、漸層文字、裝飾性 glass。 +- 不要像生活風格或可愛工具,避免預設介面過度玩味與情緒化。 +- 不要為了視覺新奇重做既有操作模型,標準工具行為優先。 + +## Design Principles + +- 實際換匯成本優先,任何視覺表現都不能壓過核心數字與方向。 +- 熟悉的工具型介面優先於新奇,使用者不應學習新的操作語法。 +- 資訊可密集,但層級必須清楚,次要訊息只能輔助,不能搶焦點。 +- 色彩與動效保持克制,只用於狀態、主動作與導引,不做裝飾。 +- 同一概念在所有頁面使用相同詞彙、相同權重與相同元件語言。 + +## Accessibility & Inclusion + +以 WCAG 2.2 AA 為基準,保留清楚焦點樣式、足夠對比、合理觸控尺寸與 `prefers-reduced-motion` 支援。 +繁體中文是預設語境,其他語言介面也必須維持相同資訊層級與可讀性。 diff --git a/apps/ratewise/docs/dev/014_design_token_architecture.md b/apps/ratewise/docs/dev/014_design_token_architecture.md index 581a2a30a..fdb9501d4 100644 --- a/apps/ratewise/docs/dev/014_design_token_architecture.md +++ b/apps/ratewise/docs/dev/014_design_token_architecture.md @@ -1,22 +1,24 @@ # Design Token SSOT 架構文檔 +> 狀態:實作架構說明。當前正式視覺規範請以 root `DESIGN.md` 為主,本文保留技術實作背景與歷史決策。 + > **建立時間**: 2026-01-17T00:30:00+08:00 -> **最後更新**: 2026-01-17T00:30:00+08:00 -> **版本**: 1.0.0 +> **最後更新**: 2026-05-23T00:00:00+08:00 +> **版本**: 1.1.0 > **狀態**: ✅ 已完成 --- ## 1. 概述 -RateWise 採用 **SSOT (Single Source of Truth) Design Token** 架構,透過 CSS Variables 實現動態主題切換,支援 6 種風格和淺/深/自動模式。 +RateWise 採用 **SSOT (Single Source of Truth) Design Token** 架構,透過 CSS Variables 實現風格切換,支援 6 種介面風格。正式產品視覺北極星與色票以 root `DESIGN.md` 為準;runtime 實作以 `src/config/themes.ts`、`src/config/design-tokens.ts` 與 `src/index.css` 為準。 ### 1.1 核心設計原則 1. **語義化命名**: 使用 `--color-primary`、`--color-accent` 等語義名稱,而非 `--color-blue-500` -2. **主題隔離**: 透過 `data-style` 和 `data-mode` 屬性控制主題變數 +2. **風格隔離**: 透過 `data-style` 屬性控制風格變數;現行 runtime 不使用 `data-mode` 3. **FOUC 防護**: 同步腳本在 `
` 中初始化主題,避免閃爍 -4. **向後相容**: 支援 Tailwind CSS 任意屬性語法 `bg-[rgb(var(--color-primary))]` +4. **語義 class 優先**: 正式頁優先使用 `bg-surface`、`text-text-muted`、`border-border` 等 Tailwind semantic class;任意 `rgb(var())` 僅保留於 token 定義、SVG/Canvas、內部展示頁與必要 fallback --- @@ -37,14 +39,14 @@ apps/ratewise/src/ ## 3. 支援的風格 -| 風格 ID | 名稱 | 主色調 | 說明 | -| --------- | ------- | ----------- | ---------------------- | -| `zen` | Zen | 紫/靛藍 | 極簡專業,適合金融應用 | -| `nitro` | Nitro | 青色/霓虹 | 深色科技感 | -| `kawaii` | Kawaii | 粉紅/珊瑚 | 可愛粉嫩 | -| `classic` | Classic | 琥珀/棕色 | 復古書卷 | -| `ocean` | Ocean | 青藍/海洋藍 | 海洋深邃 | -| `forest` | Forest | 翠綠/森林綠 | 自然森林 | +| 風格 ID | 名稱 | 主色調 | 說明 | +| --------- | ------- | ----------- | ------------------------ | +| `zen` | Zen | 冷靜藍系 | 極簡專業,為產品預設基準 | +| `nitro` | Nitro | 青色/霓虹 | 深色科技感 | +| `kawaii` | Kawaii | 粉紅/珊瑚 | 可愛粉嫩 | +| `classic` | Classic | 琥珀/棕色 | 復古書卷 | +| `ocean` | Ocean | 青藍/海洋藍 | 海洋深邃 | +| `forest` | Forest | 翠綠/森林綠 | 自然森林 | --- @@ -95,12 +97,7 @@ apps/ratewise/src/ [data-style="ocean"] { ... } [data-style="forest"] { ... } -/* 模式選擇器 */ -[data-mode="light"] { ... } -[data-mode="dark"] { ... } - -/* 組合選擇器 */ -[data-style="zen"][data-mode="dark"] { ... } +/* 注意:現行 runtime 已移除 data-mode / dark mode。 */ ``` --- @@ -110,15 +107,10 @@ apps/ratewise/src/ ### 5.1 在組件中使用 ```tsx -// 使用 Tailwind 任意屬性 -即時重點
+{item.answer}
+{item.answer}
{page.intro}
+專題指南
+{page.intro}
+
{paragraph}
))} @@ -67,13 +68,13 @@ export function AuthorityGuidePage({ page }: AuthorityGuidePageProps) {{item.answer}
+{item.answer}
{guide.label}
@@ -101,14 +102,14 @@ export function AuthorityGuidePage({ page }: AuthorityGuidePageProps) { )} {page.relatedCurrencies && page.relatedCurrencies.length > 0 && ( -{page.ctaDescription}