資料表標準
問題
表格是後台系統的主體,也是最容易長歪的地方。
手刻三張表之後,你會得到三種搜尋框位置、三種排序箭頭、三種「查無資料」文案。 更糟的是三種合計邏輯——其中一種只加總當頁,而且沒有人發現。
做法:一份欄位設定驅動全部
{
key: "amount",
header: "金額",
numeric: true, // 右對齊 + 等寬
cell: (r) => formatMoney(r.amount),
sortValue: (r) => r.amount, // 有才可排序
filterText: (r) => String(r.amount), // 參與關鍵字搜尋
filter: "range", // 單欄篩選型態
total: (rows) => formatMoney(sum(rows)),
freeze: true, // 凍結首欄
}
上面那份設定產出的,就是下面這張表——九條標準全部由欄位設定驅動,沒有一條是另外寫的:
試試搜尋、點欄頭排序、點漏斗篩選、拖曳欄邊界
| R-2406 | 戊單位 | 戊案 整併 | 12 | $268,800 | 已確認 |
| R-2403 | 丙單位 | 丙案 初版 | 6 | $213,000 | 已確認 |
| R-2402 | 乙單位 | 乙案 追加規格 這一筆刻意加長,用來示範欄位截斷與可調欄寬 | 40 | $156,400 | 已確認 |
| R-2407 | 乙單位 | 乙案 附屬項目 | 300 | $91,200 | 已作廢 |
| R-2401 | 甲單位 | 甲案 第一階段 | 120 | $84,000 | 已完成 |
| 合計 | 5,558 | $893,700 |
第 1–5 / 共 7 筆
1 / 2
這是真元件
文件站直接編譯 packages/react 的原始碼,不是截圖。
逐條 API 說明在 DataTable 元件頁。
九條標準
| # | 標準 | 為什麼 |
|---|---|---|
| 1 | 關鍵字搜尋橫跨所有文字欄 | 使用者第一個動作永遠是「找那筆」 |
| 2 | 單欄篩選:文字包含/數值範圍/多選 | 「找」和「篩」是不同任務 |
| 3 | 同欄多條件 OR、跨欄 AND | 符合直覺:同一欄想看多個值,不同欄要同時滿足 |
| 4 | 排序三態:無 → 大到小 → 小到大 | 第一下的意圖幾乎都是「誰最多」;要能回到原始順序 |
| 5 | 門檻式分頁:沒超過一頁就不顯示分頁器 | 「第 1 頁 / 共 1 頁」是噪音 |
| 6 | 合計算篩選後全部,不是當頁 | 只算當頁是對帳災難 |
| 7 | 凍結首欄 | 20 欄的表水平捲動後,不知道這列是誰 |
| 8 | 匯出跟著畫面(篩選+排序後) | 「我明明篩好了,匯出卻是全部」 |
| 9 | 空狀態分辨「沒資料」與「篩不到」 | 兩者的下一步完全不同 |
三種列狀態要真的分得開
資料表是這套系統最吃重的畫面,而「我指在哪一列」「我選了哪幾列」是它最基本的兩個問題。 改版前這兩件事實測是看不出來的:
| 改版前(淺色 ΔE00) | 現在 | |
|---|---|---|
| 一般 → hover | 1.6 | 3.0 |
| hover → 已選 | 1.6 | 7.8 |
原因不是顏色選得不好,是機制:舊做法 hover 用 --accent、已選用 --muted,
而這兩個 token 的值相同——斑馬列本來就是那個顏色。現在三種狀態都疊一層
currentColor(6% / 14% / 20%),所以「深了一階」在一般列與斑馬列上一樣成立。
兩條連帶規則:
- 已選的列,次要文字改用正文色。 20% 疊加之後
--muted-foreground掉到 2.77:1。TableRow在data-state="selected"時直接把--muted-foreground重新定義成--foreground,列裡所有吃這個變數的東西一次跟上。 - 多選時 checkbox 才是主要線索,底色是輔助。一次選 20 列時, 底色若獨自扛完整訊息就會變成整片彩色——顏色永遠不是唯一線索。
門檻與量測方法見互動狀態的顏色邏輯。
加分項:十字對準與可調欄寬
- 十字對準:指到哪一格就 highlight 整行整列。20 欄的表靠這個才不會看錯行。
- 可調欄寬:拖曳邊界、雙擊自適應。中文品名長度差異極大,固定欄寬一定有人不滿意。
取捨
代價:欄位設定比手刻 <td> 抽象。 第一張表確實比較慢。
回本點大約在第二張表。而且真正的收益不是省時間,是「所有表格行為一致」—— 使用者學會一張,就會用全部。
反例
✅ 這樣做
凡是「使用者要在裡面找某一筆」的清單,一律用標準資料表。
🚫 不要這樣
不要因為「這張表只有 5 筆」就手刻。三個月後它會有 500 筆, 而那時候補搜尋排序的成本比一開始就用高得多。
✅ 這樣做
合計列傳入的是篩選後的全部列。
🚫 不要這樣
不要傳當頁的列。這個錯誤不會拋例外、不會有紅字, 只會讓某個人在某個月的對帳中崩潰。
實作見 DataTable。