AI 應用元件
錯誤堆疊檢視器
錯誤堆疊檢視器:逐幀列出呼叫位置,高亮使用者程式碼、摺疊第三方框架幀,可展開單幀看原始碼片段並一鍵複製。
給 AI 程式助理、除錯面板與錯誤回報頁使用的堆疊檢視器。傳入結構化的 frames,或直接丟一段原始堆疊字串給 raw——內建的 parseStack 會解析 at fn (file:line:col) 與 fn@file:line:col 兩種常見格式,解析不了的行保留為純文字。使用者程式碼以左側色帶與「你的程式碼」小籤標出,連續的第三方框架幀摺成一列「⋯ 3 個框架內部呼叫」;展開單幀可看原始碼片段,出錯行整行上色並在欄位處畫出 ^ 指示。右上角一鍵複製整段堆疊,支援原始格式與 Markdown。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add stack-trace-viewerPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
180
編輯中的呼叫預設屬性
<StackTraceViewer/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/stack-trace-viewer.json或在 components.json 設定 registries 後,改用 @webberui/stack-trace-viewer 安裝。
使用
import { StackTraceViewer } from "@/components/ui/stack-trace-viewer";
// 直接傳原始堆疊字串
<StackTraceViewer
error={{ name: err.name, message: err.message }}
raw={err.stack}
onFrameClick={(frame) => openInEditor(frame.file, frame.line)}
/>
// 或傳結構化 frames(可附原始碼片段)
<StackTraceViewer
error={{ name: "TypeError", message: "Cannot read properties of undefined (reading 'amount')" }}
frames={[
{
fn: "formatPrice",
file: "src/lib/price.ts",
line: 42,
column: 29,
snippet: { startLine: 41, lines: [" const rate = item.taxRate ?? 0.05;", " const off = item.discount.amount;"] },
},
{ fn: "beginWork", file: "node_modules/ui-runtime/dist/render.js", line: 2210, column: 14 },
]}
copyFormat="markdown"
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
error | StackTraceError | — | 錯誤標頭:類型與訊息 |
frames | StackFrame[] | — | 結構化的堆疊幀;提供時優先於 raw |
raw | string | — | 原始堆疊文字,以內建 parseStack 解析 |
isUserFrame | (frame: StackFrame) => boolean | 見說明 | 判斷是否為使用者程式碼;預設為 file 不含 node_modules、不以 node: 開頭、不含 internal/ |
defaultExpanded | "first-user" | "none" | "all" | "first-user" | 非受控模式的初始展開策略:展開第一個使用者幀/全收合/全展開 |
expanded | string[] | — | 受控的展開幀 id 清單;未提供時由元件內部管理 |
onExpandedChange | (ids: string[]) => void | — | 展開清單變動時回呼 |
collapseLibrary | boolean | true | 是否把連續的第三方框架幀(兩幀以上)摺成一列 |
onFrameClick | (frame: StackFrame) => void | — | 點擊(或以 Enter/Space 啟動)幀列時回呼,例如在編輯器開啟 |
copyFormat | "raw" | "markdown" | "raw" | 複製鈕輸出的格式 |
maxHeight | number | string | 420 | 幀列表最大高度,超出時內部捲動;數字視為 px |
duration | number | 180 | 展開動畫時長(毫秒),同時寫入 --wb-stack-trace-viewer-duration |
className | string | — | 透傳到最外層容器 |
StackFrame
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | 穩定識別碼;未提供時以索引產生(frame-0、frame-1…),expanded 用的就是這個值 |
fn | string | — | 函式名稱;沒有時顯示「(匿名)」 |
file | string | — | 檔案路徑 |
line | number | — | 行號(從 1 起算) |
column | number | — | 欄位(從 1 起算),用來在出錯行畫 ^ 指示 |
isUser | boolean | — | 明確標記是否為使用者程式碼;未提供時交給 isUserFrame |
snippet | StackFrameSnippet | — | 原始碼片段;沒有時展開區顯示「沒有可用的原始碼」 |
text | string | — | 解析不了的原始行(此時 file 為空字串、line 為 0),以純文字列呈現 |
StackFrameSnippet
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
startLine | number | — | 片段第一行在原始檔中的行號 |
lines | string[] | — | 片段內容,一個元素一行 |
StackTraceError
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
name | string | — | 錯誤類型,例如 TypeError |
message | string | — | 錯誤訊息,可換行 |
另外具名匯出 parseStack(raw)、formatStackTrace(error, frames, format)、formatFrameLocation(frame) 與 defaultIsUserFrame(frame),方便在伺服器端或錯誤回報流程重複使用同一套解析與輸出邏輯。
細節
- 解析:第一個非空行若不是幀(通常是
TypeError: …標頭)會被略過;其餘解析不了的行保留為純文字幀,不會默默消失。 - 摺疊:只有連續兩幀以上的第三方幀會摺成一列——單獨一幀摺起來並不省空間。點開後各幀以 20ms 間隔依序淡入,焦點移到群組第一幀。
- 路徑截斷:路徑太長時截斷的是目錄段,檔名與行列號永遠保留,效果等同中間截斷;完整路徑在
title提示中。 - 原始碼片段不做語法高亮,只用 neutral 色階,裝進任何站都不會和既有的程式碼主題打架。
- 複製:成功時圖示交叉淡接為勾勾 1.5 秒;瀏覽器不允許存取剪貼簿時,改為展開一個已選取文字的唯讀欄位,提示使用者手動按 Ctrl+C/⌘C。
- 節奏變數:
--wb-stack-trace-viewer-duration(箭頭旋轉,預設 180ms,由duration寫入);使用者幀色帶可用--wb-stack-trace-viewer-accent覆寫。
可及性
- 整體為
role="region"、aria-label="錯誤堆疊",幀列表使用有序清單ol語意 - 每幀是原生
button,帶aria-expanded與aria-controls,aria-label完整描述幀,例如「第 3 幀:CartSummary,位於 src/components/cart-summary.tsx 第 27 行,你的程式碼」 - 鍵盤:列表採 roving tabindex,只佔一個 Tab 停駐點;↑/↓ 在幀列之間移動、Home/End 跳到首尾、Enter/Space 展開收合、→ 展開、← 收合、C 複製聚焦幀的位置(Ctrl/⌘+C 保留給瀏覽器)
- 摺疊列與複製鈕皆為原生
button;複製結果透過aria-live="polite"宣告「已複製」 - 出錯行對螢幕閱讀器額外朗讀「出錯行」,裝飾性的行號欄與 ^ 指示對輔助科技隱藏
- 使用者系統開啟「減少動態效果」時,展開直接出現、摺疊列不做依序淡入、複製鈕圖示直接替換