程式碼區塊 UI 系統
目的
程式碼區塊 UI 系統提供了一個標準化、可訪問且高可讀性的佈局框架,用於顯示原始程式碼片段、API 請求/回應 payload、多檔案程式碼範例、終端機命令列和程式碼差異比較。程式碼區塊是技術文件、開發者工具行銷網站、API 入口網站、工程部落格和 SaaS 平台中的關鍵互動元件。
設計有效的程式碼介面需要在等寬字體可讀性、淺色和深色主題下的高對比語法標記高亮度、標頭操作工具列(語言徽章、分頁檔案導航、複製到剪貼簿觸發器)、行號、行級高亮/聚焦、換行與水平捲動行為,以及無障礙螢幕閱讀器體驗之間取得平衡。此技能為程式碼 UI 呈現建立了空間規則、標記顏色對比標準、互動機制和 WCAG AA 合規指南。
使用案例
- 開發者文件與 API 參考入口網站: 呈現多語言 SDK 範例(例如 cURL、Node.js、Python、Go、Rust)和 API 回應。
- 開發者工具著陸頁: 展示重點程式碼片段、CLI 安裝命令和互動式產品展示區塊。
- 工程部落格與教學: 渲染內聯和區塊程式碼範例,包含特定行標註、逐步程式碼高亮和內聯註釋。
- 版本控制與程式碼審查介面: 顯示程式碼差異(
+新增、-刪除)、內聯評論和提交片段。 - 程式碼遊樂場與片段分享工具: 結構化多分頁檔案編輯器、預覽窗格和可嵌入的片段卡片。
何時不該使用
- 完整的瀏覽器內程式碼編輯器(IDE): 對於需要畫布渲染、虛擬化 AST 樹、多游標編輯和語言伺服器協定(LSP)整合的複雜互動式 Web IDE(例如 Monaco Editor、CodeMirror),請使用專用的編輯器實作。
- 一般表單文字輸入: 對於沒有語法高亮或行號的多行純文字欄位,請使用
form-design-system。 - 內聯文字程式碼徽章: 對於散文段落中簡短的單字程式碼參考(例如
npm install),請使用article-layout-system中的內聯<code>樣式。 - 結構化資料表格: 對於格式化為行和列的表格鍵值資料或資料庫查詢,請使用
data-table-ui-system或property-and-attribute-system。
輸入
- 程式碼內容與語法類型: 語言分類(例如 TypeScript、JSON、Bash、YAML、GraphQL、SQL)和結構特性(單一檔案、多檔案分頁、差異)。
- 主題上下文: 淺色模式和深色模式中,表面背景、邊框和語法標記的有效色調色板代碼(來自
accessible-color-system和dark-theme-design-system)。 - 等寬字體排版代碼: 首選字體堆疊(例如
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace)、字體大小和行高(來自fluid-typography-system)。 - 動作觸發器: 每個區塊所需的特定互動能力(例如一鍵複製按鈕、行號切換、自動換行切換、全螢幕展開、外部沙箱連結)。
輸出
- 程式碼容器與標頭工具列規範: 程式碼區塊容器、固定標頭列、語言指示器、檔案路徑分頁和動作按鈕群組的空間佈局。
- 無障礙語法標記調色板: 在淺色和深色主題下,針對關鍵字、字串、函式、變數、註解、運算子和型別的 WCAG AA(最低 4.5:1 對比度)標記顏色對應。
- 行級層次結構與註釋系統: 行號、行高亮/焦點疊加層、差異指示器(
+/-)和行級錨點連結的藍圖。 - 無障礙螢幕閱讀器與鍵盤導航模型: ARIA 角色屬性、鍵盤焦點路徑、行號遮罩(
aria-hidden="true")和aria-live複製狀態宣告。 - 響應式溢位與捲動策略: 水平捲動條、固定動作工具列、自動換行切換和行動裝置視口適應的規則。
工作流程
1. 結構化程式碼區塊外殼與標頭列
將容器和標頭動作列設計為一個統一的、內聚的單元:
- 容器架構: 設定一個圓角容器(
border-radius: 8px; border: 1px solid var(--border-subtle); overflow: hidden; background: var(--surface-code);)。使用獨特的表面背景(通常預設為深色模式或匹配主題表面)。 - 標頭工具列佈局: 渲染一個固定的頂部標頭列(
display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; background: var(--surface-code-header); border-bottom: 1px solid var(--border-subtle);)。 - 標頭左側區塊(分頁與元資料):
- 單一檔案: 顯示檔案路徑/名稱(例如
src/auth/jwt.ts)並帶有微妙的檔案類型圖示,或是一個大寫的語言徽章(例如TYPESCRIPT)。 - 多檔案 / 多語言: 渲染分頁按鈕(
role="tablist")。活動分頁具有高對比度文字和底部邊框/指示器(border-bottom: 2px solid var(--brand-primary))。
- 單一檔案: 顯示檔案路徑/名稱(例如
- 標頭右側區塊(動作): 群組實用動作觸發器:
- 複製按鈕: 32x32px 圖示按鈕(
aria-label="複製程式碼到剪貼簿"),在較寬的視口上具有清晰的複製圖示和標籤。 - 換行 / 捲動切換(可選): 圖示按鈕,用於切換軟換行(
white-space: pre-wrap)與水平捲動(white-space: pre)。 - 展開 / 沙箱連結(可選): 觸發器,用於在 StackBlitz、CodeSandbox 或全螢幕中開啟片段。
- 複製按鈕: 32x32px 圖示按鈕(
2. 建立等寬字體排版與佈局網格
確保技術閱讀和程式碼掃描的最佳可讀性:
- 字體堆疊: 定義一個清晰、高可讀性的等寬字體堆疊:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace。確保字體功能設定能夠清晰區分0(零)和O(大寫 O),以及1(一)、l(小寫 L)和I(大寫 I)。 - 字體大小與行高: 設定
font-size: 0.875rem(14px)搭配寬鬆的行高(line-height: 1.6/ 22.4px)。避免狹窄的行高導致程式碼括號和運算子重疊。 - 程式碼主體容器: 使用
<pre class="code-block"><code class="language-typescript">,搭配display: block; overflow-x: auto; padding: 16px 0; margin: 0; font-family: var(--font-mono);。
3. 設計行號、行高亮與差異
在不降低複製貼上或螢幕閱讀器行為的情況下,對行級元素進行結構化:
- 行結構: 將每一行格式化為一個獨立的區塊容器(
display: table-row;或display: flex; width: 100%;)。 - 行號: 在左側邊距中渲染行號(
display: table-cell; text-align: right; width: 40px; padding-right: 16px; user-select: none; color: var(--text-code-muted);)。- 無障礙規則: 將行號包裹在
<span aria-hidden="true">中,或使用 CSS 計數器內容(content: counter(line)),以便在選取文字時不會複製行號,並且在螢幕閱讀器朗讀程式碼語句時不會被朗讀出來。
- 無障礙規則: 將行號包裹在
- 高亮 / 聚焦行: 為了在教學或差異中突出關鍵行:
- 套用明確的行高亮背景(
background: var(--surface-code-highlight); border-left: 3px solid var(--brand-primary);)。 - 確保高亮疊加層跨越程式碼容器的整個可捲動寬度(
min-width: 100%)。
- 套用明確的行高亮背景(
- 差異檢視行(
+新增 /-刪除):- 新增行: 微妙的綠色背景(
background: rgba(34, 197, 94, 0.15); border-left: 3px solid var(--color-success);)。在邊距中顯示一個+符號,並包裹在<span class="sr-only">已新增:</span>中以供螢幕閱讀器使用。 - 刪除行: 微妙的紅色背景(
background: rgba(239, 68, 68, 0.15); border-left: 3px solid var(--color-danger);)。在邊距中顯示一個-符號,並包裹在<span class="sr-only">已移除:</span>中以供螢幕閱讀器使用。
- 新增行: 微妙的綠色背景(
4. 建立無障礙語法標記調色板
語法標記必須滿足針對程式碼區塊背景(var(--surface-code))的 WCAG AA 對比度(最低 4.5:1):
- 基本文字 / 變數: 中性淺色(例如
#E2E8F0在#0F172A背景上;對比度約 12.5:1)。 - 關鍵字(
const、import、return、async): 鮮豔的紫色/洋紅色(例如#C084FC;對比度約 7.2:1)。 - 函式與方法(
fetchData、useState): 明亮的藍色/青色(例如#38BDF8;對比度約 8.5:1)。 - 字串(
"https://api.example.com"): 柔和的綠色/翡翠色(例如#4ADE80;對比度約 9.1:1)。 - 數字與布林值(
404、true): 溫暖的橘色/琥珀色(例如#FB923C;對比度約 7.8:1)。 - 註解(
// Handle token response): 柔和冷灰色,符合 WCAG AA 合規(例如#94A3B8;對比度約 5.1:1)。切勿對註解使用低對比度的灰色(例如 2:1)。 - 運算子與標點符號(
=>、{、}、;): 中等中性色(例如#CBD5E1;對比度約 10.2:1)。
5. 建置複製到剪貼簿與動作回饋狀態
為複製動作提供即時回饋可以防止重複點擊和用戶沮喪:
- 預設狀態: 顯示帶有複製圖示(兩個重疊的矩形)和可選標籤(「複製」)的圖示按鈕。
- 懸停 / 聚焦狀態: 提升的表面背景或邊框高亮(
background: var(--surface-hover); outline: 2px solid var(--focus-ring))。 - 活動 / 成功狀態: 點擊時,將圖示變更為勾選圖示,將按鈕標籤更新為「已複製!」,並套用成功顏色色調(
color: var(--color-success))。 - 螢幕閱讀器通知: 透過一個不可見的
aria-live="polite"區域動態宣告複製狀態:「程式碼已複製到剪貼簿」。 - 超時重置: 在 2000 毫秒後將按鈕重置為預設狀態。
6. 行動裝置與響應式適應
確保長程式碼片段在小視口上仍能正常運作:
- 水平捲動容器: 在行動裝置上允許水平捲動(
overflow-x: auto)長行,而不會觸發頁面級別的水平捲動條溢位。 - 固定標頭工具列: 保持標頭工具列固定(
position: sticky; top: 0; z-index: 10;),以便在捲動 100 多行程式碼時,複製按鈕和活動檔案分頁仍然可存取。 - 行動裝置觸控目標: 確保複製按鈕、換行切換和多檔案分頁在觸控裝置上滿足 44x44px 的最低觸控目標。
決策規則
語法標記對比度與主題模式
| 語法類別 | 建議的標記角色 | 淺色主題顏色(在 #F8FAFC 上) | 深色主題顏色(在 #0F172A 上) | 最低對比度 |
|---|---|---|---|---|
| 關鍵字 | --token-keyword | 深紫羅蘭色 (#6B21A8) | 亮紫羅蘭色 (#C084FC) | ≥ 4.5:1 |
| 函式 | --token-function | 深青色 (#0369A1) | 天藍色 (#38BDF8) | ≥ 4.5:1 |
| 字串 | --token-string | 森林綠 (#15803D) | 亮翡翠色 (#4ADE80) | ≥ 4.5:1 |
| 數字/布林值 | --token-number | 深琥珀色 (#C2410C) | 亮琥珀色 (#FB923C) | ≥ 4.5:1 |
| 註解 | --token-comment | 柔和灰藍色 (#475569) | 柔和灰藍色 (#94A3B8) | ≥ 4.5:1 |
| 基本/變數 | --token-base | 木炭色 (#0F172A) | 清晰淺色 (#F8FAFC) | ≥ 7.0:1 |
換行與水平捲動策略
- 水平捲動(
white-space: pre)(預設推薦): 保持程式碼佈局完整性、縮排對齊和多行格式。對於縮排具有語義結構的 Python、YAML 和程式碼差異至關重要。 - 軟換行(
white-space: pre-wrap)(可選模式): 推薦用於長終端機輸出字串、命令列範例或窄側邊欄小工具,在這些情況下水平捲動會中斷閱讀流程。
限制條件
- 無障礙(WCAG 2.1 AA):
- SC 1.4.3 對比度(最低): 所有語法高亮標記顏色和註解必須達到針對程式碼背景的最低對比度 4.5:1。
- SC 2.1.1 鍵盤: 用戶必須能夠使用
Tab和Space/Enter導航到並啟動程式碼區塊標頭按鈕(分頁、複製按鈕)。 - SC 4.1.3 狀態訊息: 複製按鈕回饋必須透過
aria-live="polite"區域向輔助技術宣告。 - SC 1.3.1 資訊與關係: 行號必須對螢幕閱讀器隱藏(
aria-hidden="true"或 CSS 計數器),以避免在閱讀時插入數字。
- 文字選取與複製: 在程式碼區塊內選取文字絕不能將行號或差異標記(
+/-)選入剪貼簿緩衝區。 - 佈局偏移預防: 展開多檔案分頁或切換換行時,必須指定固定的行高或容器邊界,以防止累積佈局偏移(CLS)。
常見失敗模式
- 不可讀的低對比度註解: 使用微弱的灰色文字(例如
#4A5568在#1A202C上,對比度 2.8:1)作為註解,假設註解不重要,違反了 WCAG AA 指南。 - 複製行號: 將行號渲染為
<pre>內的純文字,導致複製貼上產生前綴為1 2 3 4的無效程式碼片段。 - 未宣告的複製動作: 更改複製按鈕的視覺圖示,但未更新
aria-label或發送aria-live宣告,使螢幕閱讀器用戶不確定動作是否成功。 - 頁面級別溢位擴散: 未在
<pre>上設定max-width: 100%和overflow-x: auto,導致 120 個字元的程式碼行在行動裝置螢幕上破壞頁面佈局。 - 水平捲動中的無障礙焦點陷阱: 在可捲動的程式碼區塊上放置
tabindex="0",但沒有清晰的鍵盤視覺輪廓指示器,導致鍵盤用戶被困在長程式碼區塊內部。
驗證標準
- 程式碼區塊具有一個結構化的容器,帶有固定的標頭工具列,顯示語言、檔案名稱和動作按鈕(複製、換行切換、全螢幕/沙箱)。
- 所有語法標記顏色(關鍵字、字串、函式、數字、註解)在淺色和深色主題模式中均滿足 WCAG AA 4.5:1 對比度。
- 行號和差異標記(+/-)對螢幕閱讀器隱藏,並且在選取/複製文字時不會被複製。
- 複製到剪貼簿按鈕會傳達狀態變化,透過 aria-live 區域向螢幕閱讀器提供回饋。
- 所有按鈕(分頁、複製、切換)都可以透過鍵盤使用 Tab 鍵導航並透過 Enter/Space 啟動。
- 水平捲動在程式碼區塊內運作,不會導致頁面級別的溢出或水平捲動。
- 在長程式碼區域中,標頭工具列保持固定(position: sticky),確保在捲動時始終可以存取操作。
- 所有可點擊元素在行動裝置觸控視口中滿足 44x44px 的最小觸控目標。