Design SystemPatternsAssetAnalysisCard

AnalysisCard

Adopted在本 repo 設計、production 已採用。站上是設計端的版本,production 實作可能已再調整。

Production:src/components/AssetPrediction/source/AnalysisCard/AnalysisCard.tsx

Installation

import { AnalysisCard } from "@/components/product/analysis-card/analysis-card";

Overview

資產 dashboard 上每個分析模組共用的外殼 —— Prediction-market consensus、Volume profile、 Market structure signals。每一張都是「一個標題、一個問『這在說什麼』的入口、一個時間控制、 一句結論、然後才是證據」。

為什麼要成為組件:spike 把這個骨架手刻了四次,四次就漂了 —— 標題與控制之間的間距各不相同、兩張留著已經砍掉的卡底來源列、一張掉了卡身上方的分隔線。 會變的是裡面那張圖,不該變的正是這個殼。

headline 講的是這張卡的結論,不是複述模組名: 「Market-implied BTC / 118,400」而不是「Consensus / 118,400」。

Interactive Demo

完整組合 — AnalysisCard + HowToRead + MetricReadout + 時間切換

Volume profile

Most-traded price · POC

$118,900

volume profile 柱列(N7,未建)· 24H

Volume below spot

62%

70% value area

$115k–121k

HVN resistance

$121,400

HVN support

$114,800

切換 24H / 7D / 30D —— headline、readout、How to read 的文案都跟著窗口走。 虛線框是還沒建的圖表(N7),殼本身是真的。

Static State Matrix

組成 — 有無 headline / howTo / controls

只有標題與卡身

chart

標題 + How to read

chart

標題 + controls

Settles Jul 31 · 7 markets

chart

全部都有

Settles Jul 31 · 7 markets

Market-implied BTC

$118,400

+0.4% vs spot

chart

headline delta — 中性 / up / down

中性 delta

Most-traded price · POC

$118,900

24H window

up

Market-implied BTC

$118,400

+0.4% vs spot

down

Market-implied BTC

$116,050

−1.6% vs spot

卡身空 — unavailable 訊息(合規路線,不是死碼)

Prediction-market consensus

No mutually exclusive range family settles with a full curve today — market-implied consensus unavailable. Individual market quotes live in the Bitcoin markets cards above.

窄容器 — 卡頭換行、controls 掉到下一行

Market structure signals

Jul 25 · Jul 31 · Aug 29

Expected move · ±1σ

±$4,180

3.5%

price axis(N8,未建)

並排 — 兩張卡等高(dashboard 的 consensus + volume profile 佈局)

Prediction-market consensus

Settles Jul 31 · 7 markets

Market-implied BTC

$118,400

+0.4% vs spot

機率分佈柱狀圖(N5,未建)

Highest-probability range

$118k–120k

50% probability range

$116k–122k

80% probability range

$112k–127k

Center vs 09:00

+0.4%

Volume profile

24H · 7D · 30D

Most-traded price · POC

$118,900

volume profile 柱列(N7,未建)

Volume below spot

62%

70% value area

$115k–121k

HVN resistance

$121,400

HVN support

$114,800

殼本身沒有 hover / pressed / focus —— 它是容器。互動全部發生在插進來的 HowToRead 與時間切換上, 各自的 state 見它們自己的 preview 頁。

Implementation Notes

來源:../opinion-labs-archive/prototypes/assets-forecasting/btc-dashboard-spike-v1.html 的 .card / .evcard / .card-h / .card-t / .ev-head / .ev-data。

組成 — 全部走 production 真組件

  • 外殼 = Card(@olab)。rounded-2xl / border-card-border / bg-card-bg / p-5 全盤照收。
  • 標題 = H3(@olab);eyebrow / delta / 說明 = SmallText;版面 = Stack / Inline。
  • 時間切換 = Button(@olab,skin=secondary、size=sm、active 表選中)—— 即 production DurationSwitch 的做法,不是 Tabs、不是手刻 pill。

production 沒有對應、只好手寫的三處

  • 卡身上方的分隔線(border-t)。
  • headline 的數值 —— production Typography 最大只到 Text(16px),沒有 24px 的;而且這是數字不是標題, 用 H1 語意也不對。退回 span + text-h1 token。
  • 虛線佔位框(本頁專用,不是組件的一部分)。

跟稿子的差異

  • 卡片內距 20px,不是稿子的 16px。Card 的 p-5 是 production 契約,照收。 (順帶一提,這個值無法用 className 覆蓋 —— Card 內部用 cn() 純字串串接,p-5 與 p-4 同權重, 由 stylesheet 順序決定勝負,結果是 p-5 贏。寫了 override 會看起來有效但其實沒作用。)
  • 卡片標題渲染成 <h3> 而非稿子的 <h2>。production Typography 把元素與字級綁死 (H2 = 20px、H3 = 16px),要 16px 就只能是 h3。標題階層在 dashboard 上會跳級, 這是 production 的限制,不在這裡發明繞法。
  • headline 數值:稿子 24/30,text-h1 是 24/32。

⚠ Button 目前長得跟 /live/button 不一樣

時間切換的 selected 底色實測是 rgba(237,100,50,.2)(舊的 α 疊色 bg-brand-2), 不是 Proposal B 拍板的 brand-tint-2 #742f16 實色。 原因是 packages/components/dist 過期 —— Proposal B 的 Button 改動只在 src,dist 沒 rebuild(本 repo 無法乾淨 rebuild,見 project memory)。 這是用真組件必然繼承的現況,不是本頁的 bug; Ethan 那側 rebuild 後會自動對上。

未建的內容物(本頁以虛線框佔位)

  • N5 機率分佈柱狀圖 · N7 volume profile 柱列 · N8 水平價格軸
  • 三者都等 data visualization token 組拍板(見 untitledui-nextjs-starter-kit/docs/asset-forecasting/asset-prediction-handoff-component-map.md)。N8 另有「一次性 SVG 還是進組件庫」未裁決。

本頁的時間切換是佔位

真正的實作走 production DurationSwitch 模式 (src/app/market/components/TopicChart/DurationSwitch.tsx)—— 一排 Button size=sm,不是 Tabs。 這裡只是為了讓 controls slot 有東西可 demo。