
TUI 正在經歷一場文藝復興
終端介面(Terminal User Interface, TUI)正在重新崛起。如果你是開發者,幾乎不可能沒用過這些工具:lazygit 讓 Git 操作變得直覺、btop 把系統監控變成一幅即時儀表板、k9s 讓 Kubernetes 叢集管理從此告別冗長的 kubectl 指令、Charm 團隊打造的一系列工具證明了終端應用可以同時兼具美觀與功能性。
但問題來了——網頁 UI 有 Material Design、Apple Human Interface Guidelines、Ant Design 等成熟的設計規範,而 TUI 呢?幾乎沒有任何系統性的設計標準。
每個 TUI 工具都在「自己發明輪子」:有的用 j/k 導航,有的用方向鍵;有的用紅色表示錯誤,有的用紅色表示重要;有的按 q 退出,有的按 Ctrl+C,有的甚至需要 :q。使用者在不同工具之間切換時,必須重新學習操作方式,這大幅降低了效率。
本文嘗試提出一套 TUI 設計一致性框架(TUI Design Consistency Framework),為終端介面的色彩系統、互動模式、佈局原則與元件標準提供參考依據。這不是一份強制規格書,而是一份「如果大家都這樣做,使用者會更開心」的建議。
TUI 設計系統的分層架構
一個完整的 TUI 設計系統可以分為四個層級,由底層往上逐步構建:
graph TB subgraph Application["應用層 Application"] A1[lazygit] A2[k9s] A3[btop] A4[Claude Code] end subgraph Patterns["模式層 Patterns"] P1[導航模式 Navigation] P2[回饋模式 Feedback] P3[佈局模式 Layout] P4[錯誤處理 Error Handling] end subgraph Components["元件層 Components"] C1[文字輸入 Input] C2[列表 List] C3[表格 Table] C4[進度條 Progress] C5[對話框 Dialog] end subgraph Foundation["基礎層 Foundation"] F1[色彩系統 Colors] F2[文字排版 Typography] F3[間距系統 Spacing] F4[圖示符號 Icons/Symbols] end Foundation --> Components --> Patterns --> Application
每一層都依賴下一層的定義。基礎層決定了「我們有哪些顏色和字元可用」,元件層定義了「每個互動單元長什麼樣」,模式層描述了「元件如何組合成使用流程」,最終在應用層組裝成完整的工具。
為什麼 TUI 現在正在流行?
開發者工具回歸終端
越來越多開發者工具選擇 TUI 而非 GUI 作為介面:
| 工具 | 用途 | 取代了什麼 |
|---|---|---|
| lazygit | Git 視覺化操作 | GitKraken, SourceTree |
| lazydocker | Docker 容器管理 | Docker Desktop |
| k9s | Kubernetes 叢集管理 | Kubernetes Dashboard |
| btop / htop | 系統資源監控 | 系統監控 GUI |
| yazi | 檔案管理器 | Finder, Explorer |
AI 編碼助手以 TUI 為主要介面
這是一個重大轉折:Claude Code、GitHub Copilot CLI、aider 等 AI 編碼助手選擇了終端作為主要互動介面。當 AI 工具也選擇 TUI,代表這不只是復古潮流,而是一種有實質優勢的介面選擇。
核心優勢
- SSH 可達:透過遠端連線即可操作,不需要 GUI 環境。在伺服器上、在 Docker 容器中、在任何有 SSH 的地方都能使用
- 效能卓越:啟動時間通常在毫秒級,記憶體占用極低。相較之下,Electron 應用動輒數百 MB
- 鍵盤效率:對於熟練使用者,鍵盤操作遠比滑鼠快。不需要在鍵盤與滑鼠之間反覆切換
- 可腳本化:終端工具天然適合自動化和管道串接
- 現代框架降低門檻:Bubble Tea(Go)、Ink(JS)、Rich(Python)、Ratatui(Rust)讓打造精美 TUI 變得前所未有地簡單
TUI 設計五大原則
原則一:鍵盤優先(Keyboard-First)
每一個操作都必須能透過鍵盤完成。 滑鼠支援是加分項,但絕不是必要條件。
這與網頁設計的「行動裝置優先」(Mobile-First)類似——先確保核心互動在最受限的情境下可用,再往上擴展。
好的做法:
按 Enter 確認 | 按 Esc 取消 | 按 ? 顯示說明
不好的做法:
[請點擊確認按鈕](終端使用者可能根本沒有滑鼠)
原則二:漸進式揭露(Progressive Disclosure)
先顯示最重要的資訊,將細節藏在「按需展開」的互動中。終端空間有限,不能像網頁一樣無限捲動。
- 第一層:關鍵摘要(檔案名稱、狀態、數量)
- 第二層:按 Enter 或方向鍵展開詳細資訊
- 第三層:按特定鍵(如
d查看 diff,l查看 log)進入深層檢視
lazygit 是漸進式揭露的典範:左側面板顯示檔案列表,選取後右側顯示 diff,按 Enter 可進入逐行檢視。
原則三:情境感知(Context Awareness)
使用者在任何時刻都必須能回答三個問題:
- 我在哪裡?(目前在哪個面板/模式/頁面)
- 我能做什麼?(目前可用的操作)
- 剛才發生了什麼?(上一個操作的結果)
實作方式:
- 使用高亮/反白標示目前焦點
- 底部狀態列顯示可用的快捷鍵
- 操作後顯示簡短的回饋訊息
原則四:優雅降級(Graceful Degradation)
TUI 必須在各種終端環境中運作:
| 環境 | 寬度 | 色彩支援 | 字元支援 |
|---|---|---|---|
| 最小終端 | 80x24 | 16 色 | ASCII only |
| 標準終端 | 120x40 | 256 色 | 基本 Unicode |
| 現代終端 | 200+ | True Color | 完整 Unicode + Nerd Font |
設計時應以 80 欄寬為基準,確保核心功能在最小終端中依然可用。寬螢幕是加分項,不是必要條件。
原則五:一致的回饋(Consistent Feedback)
每個操作都應該有可見的回饋:
- 成功:綠色
✓ Done或[OK] - 失敗:紅色
✗ Error: ...或[FAIL] - 進行中:動畫旋轉器
⠋ Loading... - 警告:黃色
⚠ Warning: ... - 無操作:簡短說明為什麼什麼都沒發生
沒有回饋是最糟糕的使用者體驗。使用者按了一個鍵,什麼都沒發生——是成功了?失敗了?還是沒偵測到按鍵?
色彩系統(Color System)
ANSI 標準 16 色
終端色彩的基礎是 ANSI 16 色,這是幾乎所有終端都支援的最低公分母:
| 色彩 | 標準用途 | 語意映射 |
|---|---|---|
| 黑色 (Black) | 背景 | 背景、隱藏文字 |
| 紅色 (Red) | 錯誤 | 錯誤、刪除、危險操作 |
| 綠色 (Green) | 成功 | 成功、新增、安全操作 |
| 黃色 (Yellow) | 警告 | 警告、注意、修改中 |
| 藍色 (Blue) | 資訊 | 導航、連結、說明 |
| 洋紅 (Magenta) | 強調 | 特殊標記、關鍵字 |
| 青色 (Cyan) | 輔助資訊 | 路徑、URL、次要資訊 |
| 白色 (White) | 主要文字 | 主要內容、聚焦元素 |
| 亮色變體 | 對應色的淺色版 | 用於高亮或強調 |
語意色彩映射(Semantic Color Mapping)
不要用「紅色」思考,要用「語意」思考:
語意 色彩 符號 使用場景
──────────────────────────────────────────────────────
error Red ✗ [!] 錯誤訊息、失敗狀態
success Green ✓ [OK] 成功訊息、完成狀態
warning Yellow ⚠ [!] 警告訊息、需要注意
info Blue ℹ [i] 提示訊息、說明
primary Bold/White ▶ 主要內容、焦點
secondary Dim/Gray · 次要內容、已停用
destructive Red + Bold ✗✗ 刪除、不可逆操作
256 色與 True Color
現代終端(iTerm2, WezTerm, Windows Terminal, Kitty, Alacritty)支援 256 色甚至 24-bit True Color。但要注意:
- 永遠提供 16 色降級方案:不是每個終端都支援 True Color
- 用
$COLORTERM環境變數偵測支援度:truecolor或24bit表示支援 - 256 色用於漸層和圖表:btop 的 CPU 使用率圖表就是好例子
無障礙:不要只靠顏色
這是最容易被忽略的原則:永遠不要讓顏色成為唯一的資訊傳遞方式。
色覺障礙者(約 8% 的男性、0.5% 的女性)可能無法區分紅色和綠色。因此:
不好的做法:
紅色文字 = 失敗 | 綠色文字 = 成功
好的做法:
✗ 紅色文字 = 失敗 | ✓ 綠色文字 = 成功
[FAIL] 紅色背景 | [OK] 綠色背景
同時使用顏色 + 符號(或顏色 + 文字標籤),確保資訊在單色環境中依然可讀。
深色/淺色終端
許多開發者使用淺色背景的終端(是的,他們存在)。設計時要考慮:
- 避免使用「白色文字 + 黑色背景」的硬編碼組合
- 使用終端的「預設前景色」和「預設背景色」作為基準
- 測試時同時在深色和淺色主題下驗證可讀性
佈局模式(Layout Patterns)
全螢幕應用佈局
最常見的 TUI 應用佈局:
┌─────────────────────────────────────────────────┐
│ 標題列 (Title Bar) [模式/狀態] │
├──────────────┬──────────────────────────────────┤
│ │ │
│ 側邊欄 │ 主要內容區 │
│ (Sidebar) │ (Main Content) │
│ │ │
│ - 項目 1 │ 詳細資訊顯示在這裡 │
│ > 項目 2 │ ... │
│ - 項目 3 │ │
│ │ │
├──────────────┴──────────────────────────────────┤
│ 狀態列: ↑↓ 導航 | Enter 選取 | q 退出 | ? 說明 │
└─────────────────────────────────────────────────┘
關鍵設計點:
- 標題列:顯示應用名稱、目前模式、連線狀態等全域資訊
- 側邊欄:寬度固定(通常 20-30 欄),顯示導航或列表
- 主要內容區:佔據剩餘空間,顯示詳細內容
- 狀態列:永遠顯示在最下方,列出目前可用的快捷鍵
列表/詳情分割(List-Detail Split)
這是最實用的 TUI 模式。lazygit、k9s 都使用這個模式:
- 左側面板:項目列表,以高亮標示目前選取項
- 右側面板:選取項的詳細資訊
- 導航:
j/k或↑/↓在列表中移動,焦點切換時右側即時更新
頁籤導航(Tab Navigation)
┌──────┬──────┬──────┬──────┐
│ 檔案 │ 分支 │ 提交 │ 暫存 │
└──┬───┴──────┴──────┴──────┘
│ (目前頁籤底線標示)
使用 Tab / Shift+Tab 或數字鍵 1/2/3/4 切換頁籤。
模態對話框(Modal Dialog)
┌───────────────────────────────┐
│ │
│ ┌─── 確認刪除 ──────────┐ │
│ │ │ │
│ │ 確定要刪除 main.js? │ │
│ │ │ │
│ │ [Yes] [No] │ │
│ └───────────────────────┘ │
│ │
└───────────────────────────────┘
模態對話框應該:
- 使用方框字元(box-drawing characters)繪製邊框
- 背景使用暗色遮罩(如果終端支援)
- 預設焦點在安全選項上(通常是 “No” 或 “Cancel”)
響應式設計
根據終端寬度調整佈局:
寬度 >= 120:側邊欄 + 主內容(雙欄)
寬度 80-119:隱藏側邊欄,改用全螢幕列表 + Enter 進入詳情
寬度 < 80: 簡化顯示,截斷長文字,隱藏非必要欄位
間距與結構字元
使用 Unicode 方框繪製字元建立視覺結構:
基本邊框:─ │ ┌ ┐ └ ┘
T 型接合:┬ ┤ ┴ ├
十字交叉:┼
雙線邊框:═ ║ ╔ ╗ ╚ ╝(用於強調、模態)
圓角邊框:╭ ╮ ╰ ╯(現代風格,但部分終端不支援)
互動模式(Interaction Patterns)
導航
建立一致的導航快捷鍵:
| 操作 | 主要按鍵 | 替代按鍵 | 來源 |
|---|---|---|---|
| 上移 | k | ↑ | Vim |
| 下移 | j | ↓ | Vim |
| 左移/收合 | h | ← | Vim |
| 右移/展開 | l | → | Vim |
| 跳到頂部 | g | Home | Vim (gg) |
| 跳到底部 | G | End | Vim (G) |
| 上一頁 | Ctrl+u | PgUp | Vim |
| 下一頁 | Ctrl+d | PgDn | Vim |
| 切換面板 | Tab | Ctrl+w | 通用/Vim |
為什麼選 Vim 鍵位? 因為終端使用者群與 Vim 使用者群高度重疊。不需要強制 Vim 鍵位,但同時支援 Vim 鍵位和方向鍵是最佳實踐。
選取與確認
| 操作 | 按鍵 | 說明 |
|---|---|---|
| 切換選取 | Space | 勾選/取消勾選當前項目 |
| 確認 | Enter | 執行操作或進入下一層 |
| 取消 | Esc | 返回上一層或關閉對話框 |
| 全選 | Ctrl+a | 選取所有項目 |
搜尋與篩選
| 操作 | 按鍵 | 說明 |
|---|---|---|
| 開始搜尋 | / | 進入搜尋模式(Vim 慣例) |
| 下一個結果 | n | 跳到下一個匹配項 |
| 上一個結果 | N | 跳到上一個匹配項 |
| 清除搜尋 | Esc | 退出搜尋模式 |
系統操作
| 操作 | 按鍵 | 說明 |
|---|---|---|
| 顯示說明 | ? | 開啟快捷鍵說明頁面 |
| 退出 | q | 退出應用(如果有未儲存變更,先確認) |
| 強制退出 | Ctrl+C | 通用中斷訊號,永遠要能用 |
| 重新整理 | r | 重新載入/刷新資料 |
狀態列:動態提示可用操作
狀態列應根據目前情境顯示不同的可用操作:
在列表頁:
↑↓ 導航 | Enter 檢視 | d 刪除 | / 搜尋 | ? 說明
在編輯模式:
Esc 取消 | Ctrl+S 儲存 | Tab 下一個欄位
在確認對話框:
y 確認 | n 取消 | Enter 執行預設選項
元件標準(Component Standards)
文字輸入(Text Input)
┌─ 搜尋 ─────────────────────────────────┐
│ > 輸入關鍵字... │ ← 淺灰色佔位文字
└─────────────────────────────────────────┘
┌─ 搜尋 ─────────────────────────────────┐
│ > main█ │ ← 游標以方塊顯示
└─────────────────────────────────────────┘
┌─ Email ────────────────────────────────┐
│ > not-an-email │
│ ✗ 請輸入有效的 Email 地址 │ ← 紅色驗證錯誤
└─────────────────────────────────────────┘
設計要點:
- 使用
>作為輸入提示符號 - 佔位文字使用暗色/灰色
- 驗證錯誤即時顯示在輸入框下方
- 支援
Ctrl+A(全選)、Ctrl+K(刪除到行尾)等 Emacs 風格編輯鍵
選取列表(Select / List)
Select a branch:
develop
▶ main ← 高亮 + 箭頭標示目前選取
feature/auth
feature/ui-update
hotfix/login-bug
[3/5] ↑↓ 移動 | Enter 選取 | / 篩選
設計要點:
- 使用
▶或反白標示目前選取項 - 顯示「目前位置/總數」(如
[3/5]) - 列表超出可視範圍時顯示捲動提示(
↑ 還有更多/↓ 還有更多) - 支援增量搜尋(輸入文字即時篩選)
表格(Table)
┌──────────────┬──────────┬──────────┬───────────┐
│ Name │ Status ▼ │ CPU │ Memory │
├──────────────┼──────────┼──────────┼───────────┤
│ web-server │ Running │ 23.4% │ 512 MB │
│ api-gateway │ Running │ 11.2% │ 256 MB │
│ db-primary │ Warning │ 67.8% │ 2.1 GB │
│ worker-01 │ Stopped │ 0.0% │ 0 MB │
└──────────────┴──────────┴──────────┴───────────┘
1-4 of 12 | ▼ 表示降序排序 | Tab 切換排序欄位
設計要點:
- 標題列使用粗體或不同顏色
- 排序方向使用
▲/▼標示 - 數值靠右對齊,文字靠左對齊
- 狀態使用語意色彩(Running=綠, Warning=黃, Stopped=紅)
進度指示(Progress Indicator)
短時操作(< 2 秒)用旋轉器:
⠋ 正在載入...
⠙ 正在載入...
⠹ 正在載入...
長時操作用進度條:
下載中 ████████████░░░░░░░░ 62% | 3.1 MB/s | 剩餘 12s
多步驟操作:
[1/4] ✓ 安裝相依套件
[2/4] ✓ 編譯原始碼
[3/4] ⠋ 執行測試...
[4/4] 部署(等待中)
確認對話框(Confirmation Dialog)
一般確認:
是否繼續? [Y/n] ← 大寫字母 = 預設選項
危險操作確認:
⚠ 此操作將刪除所有資料且無法復原。
請輸入 "delete-all" 以確認:> █
(對於不可逆的危險操作,要求使用者輸入確認文字)
通知與訊息(Notifications)
成功:✓ 檔案已儲存 ← 綠色,2 秒後自動消失
錯誤:✗ 無法連線到伺服器:timeout ← 紅色,停留直到按鍵關閉
警告:⚠ 磁碟空間不足(剩餘 2%) ← 黃色,停留 5 秒
資訊:ℹ 有 3 個更新可用 ← 藍色,2 秒後自動消失
現代 TUI 框架比較
| 框架 | 語言 | 架構風格 | 最適合 | 學習曲線 |
|---|---|---|---|---|
| Bubble Tea | Go | Elm 架構(Model-Update-View) | 生產級 CLI 工具 | 中等 |
| Ink | JavaScript/TypeScript | React 元件模型 | Node.js 開發者工具 | 低(熟悉 React 的話) |
| Rich | Python | 宣告式 API | 腳本、資料展示、美化輸出 | 低 |
| Ratatui | Rust | 即時模式渲染(Immediate Mode) | 高效能、系統工具 | 高 |
| Textual | Python | CSS-like 樣式系統 | 複雜的全功能應用 | 中等 |
Bubble Tea 範例:基本計數器
Bubble Tea 使用 Elm 架構——把狀態管理和 UI 渲染完全分離。這是 Go 生態中最受歡迎的 TUI 框架。
package main
import (
"fmt"
tea "github.com/charmbracelet/bubbletea"
)
// Model:應用狀態
type model struct {
count int
quitting bool
}
// Init:初始化指令
func (m model) Init() tea.Cmd {
return nil
}
// Update:處理訊息,更新狀態
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c":
m.quitting = true
return m, tea.Quit
case "k", "up":
m.count++
case "j", "down":
if m.count > 0 {
m.count--
}
}
}
return m, nil
}
// View:根據狀態渲染 UI
func (m model) View() string {
if m.quitting {
return "Bye!\n"
}
return fmt.Sprintf(
"\n 計數器: %d\n\n ↑/k 增加 | ↓/j 減少 | q 退出\n",
m.count,
)
}
func main() {
p := tea.NewProgram(model{count: 0})
if _, err := p.Run(); err != nil {
fmt.Printf("Error: %v\n", err)
}
}設計重點:注意 View() 中的狀態列永遠顯示可用操作,同時支援 Vim 鍵位(j/k)和方向鍵。
Rich 範例:美觀的資料表格
Rich 是 Python 生態中最流行的終端美化函式庫,特別適合輸出格式化資料。
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.text import Text
from rich import box
console = Console()
# 建立表格
table = Table(
title="🖥 服務狀態監控",
box=box.ROUNDED, # 使用圓角邊框
show_lines=True, # 顯示行分隔線
header_style="bold cyan", # 標題列樣式
)
# 定義欄位
table.add_column("服務名稱", style="bold white", min_width=15)
table.add_column("狀態", justify="center", min_width=10)
table.add_column("CPU", justify="right", min_width=8)
table.add_column("記憶體", justify="right", min_width=10)
table.add_column("回應時間", justify="right", min_width=10)
# 加入資料(使用語意色彩)
table.add_row(
"web-server",
"[green]● Running[/green]",
"23.4%",
"512 MB",
"[green]45ms[/green]",
)
table.add_row(
"api-gateway",
"[green]● Running[/green]",
"11.2%",
"256 MB",
"[green]12ms[/green]",
)
table.add_row(
"db-primary",
"[yellow]● Warning[/yellow]",
"[yellow]67.8%[/yellow]",
"[yellow]2.1 GB[/yellow]",
"[yellow]230ms[/yellow]",
)
table.add_row(
"worker-01",
"[red]● Stopped[/red]",
"0.0%",
"0 MB",
"[red]N/A[/red]",
)
# 輸出表格
console.print()
console.print(table)
console.print()
# 加入摘要面板
summary = Text()
summary.append("✓ 2 ", style="green")
summary.append("正常運行 ")
summary.append("⚠ 1 ", style="yellow")
summary.append("需要關注 ")
summary.append("✗ 1 ", style="red")
summary.append("已停止")
console.print(Panel(summary, title="摘要", border_style="blue"))設計重點:使用語意色彩(綠=正常、黃=警告、紅=錯誤)+ 符號(●, ✓, ⚠, ✗)雙重傳遞狀態資訊。
Ratatui 的架構特點
Ratatui 使用即時模式渲染,每一幀都重新繪製整個畫面。這種方式特別適合需要高效能更新的應用(如系統監控):
// Ratatui 的核心渲染迴圈概念
fn ui(frame: &mut Frame, app: &App) {
// 將終端分割為多個區域
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(3), // 標題列
Constraint::Min(0), // 主內容
Constraint::Length(1), // 狀態列
])
.split(frame.area());
// 渲染標題
let title = Paragraph::new("System Monitor")
.style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD))
.block(Block::default().borders(Borders::ALL));
frame.render_widget(title, chunks[0]);
// 渲染主內容(表格、圖表等)
// ...
// 渲染狀態列
let status = Paragraph::new(" q: Quit | r: Refresh | ?: Help")
.style(Style::default().fg(Color::DarkGray));
frame.render_widget(status, chunks[2]);
}真實世界 TUI 設計分析
lazygit:把 Git 複雜性馴服在終端裡
lazygit 是 TUI 設計的標竿之作,值得仔細研究它的設計決策:
- 五面板佈局:Status、Files、Branches、Commits、Stash 分別佔據左側五個面板,右側顯示詳情
- Tab 切換:數字鍵
1-5快速切換面板焦點 - 漸進式揭露的極致:在檔案列表中按 Enter 可以看到 diff,在 diff 中可以選取特定行進行 stage
- 上下文選單:不同面板中按同一個鍵(如
d)會執行不同操作(刪除檔案 vs 刪除分支) - 即時回饋:每個操作都立即反映在 UI 上
k9s:Kubernetes 的終端儀表板
k9s 把複雜的 Kubernetes API 轉化為直覺的 TUI 介面:
- 指令列模式:按
:進入指令列,輸入資源類型(:pods,:deployments) - 快速篩選:按
/即時篩選資源 - 上下文感知的操作:選取不同資源時,可用操作會動態更新
- 色彩編碼:Pod 狀態一目瞭然(Running=綠, Pending=黃, Error=紅)
- 麵包屑導航:頂部始終顯示
Context > Namespace > Resource的路徑
btop:系統監控的藝術品
btop 展示了 TUI 可以有多美觀:
- 即時圖表:CPU、記憶體使用率以波形圖呈現,利用 Unicode 方塊字元實現像素級渲染
- 色彩漸層:從綠到黃到紅的漸層表示資源使用程度
- 自適應佈局:根據終端大小動態調整圖表和表格的比例
- 主題系統:支援多種配色方案,適應不同終端和偏好
Claude Code:AI 時代的 TUI 先驅
Claude Code 作為 AI 編碼助手,展示了 TUI 在 AI 時代的設計方向:
- 對話式互動:主要介面是文字輸入與輸出的串流,符合終端的天然強項
- 結構化輸出:程式碼區塊、diff 顯示、檔案樹都有清晰的視覺區隔
- 進度回饋:長時間操作(讀取檔案、思考中)有明確的載入指示
- 上下文保持:對話歷史在終端中清晰可追溯
建議的 TUI 設計檢查清單
在發布任何 TUI 應用之前,建議對照以下清單逐項檢查:
### 基礎
- [ ] 所有操作都可以透過鍵盤完成
- [ ] 色彩編碼遵循語意映射(紅=錯誤, 綠=成功, 黃=警告)
- [ ] 在 80 欄寬的終端中可正常使用
- [ ] 在 16 色終端中可正常使用(色彩降級)
### 導航
- [ ] 支援 j/k(Vim)和方向鍵兩種導航方式
- [ ] 按 ? 可顯示所有快捷鍵說明
- [ ] 按 q 或 Ctrl+C 可以退出
- [ ] Tab / Shift+Tab 可在面板間切換
### 回饋
- [ ] 每個操作都有可見的回饋
- [ ] 錯誤狀態有清晰的錯誤訊息
- [ ] 載入狀態有進度指示器
- [ ] 成功操作有確認訊息
### 無障礙
- [ ] 不只靠顏色傳遞資訊(有搭配符號或文字)
- [ ] Unicode 字元有 ASCII 降級方案
- [ ] 支援深色和淺色終端背景
### 健壯性
- [ ] 正確處理終端大小調整(resize)
- [ ] 異常退出時恢復終端狀態(不留下亂碼)
- [ ] 長文字有截斷或換行處理常見問題與風險
色彩在某些終端中壞掉
問題:你在 iTerm2 中精心調整的色彩,在 Linux TTY 或舊版 PuTTY 中變得面目全非。
解決方案:
- 偵測
$TERM和$COLORTERM環境變數,動態調整色彩方案 - 永遠以 ANSI 16 色為基線設計
- 提供
--no-color或遵循NO_COLOR環境變數標準(參見 no-color.org)
Unicode 字元無法渲染
問題:方框繪製字元 ┌─┐、圓角 ╭╮、或符號 ✓ ✗ 在某些終端中顯示為亂碼或問號。
解決方案:
提供 ASCII 降級:
Unicode: ╭──────────╮ ASCII: +----------+
│ Hello │ | Hello |
╰──────────╯ +----------+
Unicode: ✓ 成功 ASCII: [OK] 成功
Unicode: ✗ 失敗 ASCII: [FAIL] 失敗
Unicode: ⚠ 警告 ASCII: [WARN] 警告
終端太小
問題:使用者在 80x24 甚至更小的終端中執行你的應用。
解決方案:
- 設定最小終端大小(例如 60x20),太小時顯示友善提示
- 監聽
SIGWINCH訊號(終端大小變更),動態重排佈局 - 優先保留核心功能,次要資訊在空間不足時自動隱藏
螢幕閱讀器的困境
問題:TUI + 螢幕閱讀器(Screen Reader)基本上是一個未解決的問題。終端輸出對螢幕閱讀器來說很難解析。
目前的最佳實踐:
- 避免使用純裝飾性的 Unicode 字元(螢幕閱讀器會逐字唸出來)
- 提供純文字模式(
--accessible旗標) - 確保所有狀態訊息是完整的句子,而不只是符號
- 這是整個 TUI 生態系統需要共同改進的領域
終端狀態殘留
問題:程式異常退出後,終端留在 raw mode,游標消失、echo 關閉。
解決方案:
- 使用
defer或finally確保清理程式碼一定會執行 - 捕獲
SIGINT、SIGTERM訊號,在退出前恢復終端狀態 - 現代框架(Bubble Tea, Ratatui)通常已內建處理,但務必測試異常情境
展望:TUI 設計的未來
TUI 設計正處於一個有趣的轉折點。隨著 AI 工具越來越多地選擇終端作為主要介面,TUI 的重要性只會持續增長。我們可能會看到:
- TUI 設計系統的標準化:就像網頁有 Material Design,TUI 也需要統一的設計語言
- 更好的無障礙支援:終端模擬器和 TUI 框架需要共同改善螢幕閱讀器支援
- 跨框架的元件生態:標準化的 TUI 元件可以在不同框架間共享
- AI 驅動的自適應介面:根據使用者習慣和情境自動調整佈局和快捷鍵
延伸閱讀
- Charm.sh — Bubble Tea、Lip Gloss、Huh 等 Go TUI 工具的官方網站
- Ratatui 文件 — Rust TUI 框架的完整文件與教學
- Textual 文件 — Python TUI 框架,支援 CSS-like 樣式
- Rich 文件 — Python 終端美化函式庫
- Ink 文件 — 用 React 語法寫 TUI
- Terminal.sexy — 終端配色方案設計工具
- no-color.org —
NO_COLOR環境變數標準 - The Art of Command Line — 命令列使用的經典參考
- clig.dev — CLI Guidelines,雖然聚焦 CLI 而非 TUI,但許多原則相通