iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
Vibe Coding

看得懂、叫得出、驗得過:30 天 VibeCoding UI 元件實戰系列 第 17

Day 17|資料有層級時,別只用縮排:Tree View、Nested List、Treegrid 與 Expandable Row

  • 分享至 

  • xImage
  •  

安安~我是ChiYu~

昨天把資料值和命令分開後,我從 Command Palette 執行「檢視專案結構」。AI 很快交出一張有箭頭、有縮排,點下去也會展開的畫面。

乍看就是一棵樹。

再看仔細一點,子專案、附件、檢核紀錄和備註全部都住在下一層。只要往右縮排兩格,任何資料突然都能變成孩子。

下面是依照第一版問題重建的畫面,不含真實資料:

專案結構的錯誤第一版:子專案、備註與附件都被縮排成相同的孩子節點

圖 1:元件盤點計畫、專案備註與附件共用相同箭頭和縮排,全被算成設計系統組的孩子。

原始需求確實留了很大的發揮空間:

請把部門、專案和任務做成樹狀,點開後可以看細節。

部門底下有專案,這是父子關係;任務底下顯示一段備註,卻只是同一筆資料的補充。兩者都能使用箭頭展開,操作意義完全不同。

Vibe Coding 若只說「做成樹狀」,AI 多半會先完成箭頭和縮排。至於展開後出現的是下一層資料,還是目前這列的更多明細,就看畫面怎麼塞得下。

今天要把 Tree View、Nested List、Treegrid 與 Expandable Row 分開。選型依據不是箭頭長什麼樣,而是資料之間到底有沒有父子關係,以及使用者需不需要比較多欄資料。

我把四種做法放進 Vibe UI Atlas 的階層資料比較頁

階層資料元件比較頁:先判斷展開的是子節點、內容層次、多欄資料或同列明細

圖 2:箭頭只說「這裡可以展開」,沒有回答展開的是孩子資料,還是目前這列的補充。

展開項目有自己的身分,還是只在解釋目前這列?

我先拿 LumenDesk 的「產品與設計中心」做測試。它底下有產品策略組、設計系統組,每個組別再包含各自的專案。展開設計系統組後,才看得到「元件盤點計畫」。這些資料有自己的身分、狀態與生命週期,適合 Tree View。

另一邊,專案任務表裡有一筆「活動頁無障礙檢查」。按下「檢核明細」後出現完成項目、備註與附件。那些內容無法離開這筆任務獨立存在,只是在解釋同一列,Expandable Row 會更直白。

判斷時,我不只問「刪掉目前這列後,展開內容還在不在」。有些系統會連孩子一起刪除,光靠刪除結果,很容易把真正的父子資料誤判成明細。

我會改問三件事:

  1. 展開項目有沒有自己的識別、狀態與生命週期?
  2. 它能不能在其他流程中被搜尋、選取、移動或單獨授權?
  3. 使用者是否需要沿著父子關係繼續往下操作?

若答案是可以,而且資料確實隸屬於目前節點,通常是父子資料。若內容只用來解釋目前任務,離開這列就沒有獨立意義,多半是明細。

再加上「需不需要比較多欄資料」,四種元件就能排回自己的位置:

資料關係 使用者真正要做的事 適合的元件
部門底下有小組,小組底下有專案 逐層走進真正的孩子資料 Tree View
文件有章節、子章節與條列內容 順著閱讀順序理解內容層次 Nested List
專案有子任務,也要比較負責人、狀態與截止日 展開階層,同時對齊多欄資料 Treegrid
任務列下面顯示附件、備註與檢核紀錄 暫時查看同一筆資料的補充 Expandable Row

依資料關係與欄位需求選擇階層資料元件

圖 3:先判斷是不是父子資料,再問要不要對齊多欄;沒有互動需求時,Nested List 已經夠用。

箭頭放左邊還是右邊可以晚點決定。資料關係一開始寫錯,後面每次展開都會繼續錯下去。

互動式父子資料:Tree View 與 Treegrid

Tree View 的焦點、選取與展開是三種狀態

Tree View 元件頁示範部門、群組與專案的父子關係。父節點可以展開,葉節點則沒有下一層。

Vibe UI Atlas 的 Tree View 實際 Demo:已選取節點、鍵盤焦點與展開狀態分開呈現

圖 4:焦點表示鍵盤目前會操作哪裡,選取表示已保存的節點,展開則控制孩子是否可見。

Tree View 真正麻煩的地方不是縮排,而是焦點、選取與展開很容易被 AI 合成同一個藍色底。

  • 焦點: 鍵盤下一步會作用的位置。
  • 選取: 使用者已經選定或系統正在保存的資料。
  • 展開: 孩子目前看不看得到。

W3C 的 Tree View Pattern 將焦點與選取視為不同概念,也允許部分單選 Tree 採「焦點跟著選取」;多選 Tree 則更需要清楚分開。W3C WAI-ARIA APG:Tree View Pattern

LumenDesk 刻意採分離模式。管理員可以先用方向鍵查看其他節點,再決定是否改變目前專案:

  • Up/Down 只在可見節點間移動焦點。
  • Right 展開父節點,或進入第一個孩子。
  • Left 收合父節點,或回到父節點。
  • Enter 執行目前節點的預設動作;在這個 Demo 中,葉節點的動作是選取。

這是本案例的互動合約,不是所有 Tree View 都必須照抄。真正重要的是規格先選一套,不要讓方向鍵有時移焦點、有時順便改資料。

第一輪實測:方向鍵通過,摘要卻只剩一個菱形

2026 年 7 月 24 日,網站初始選取「LumenCore 平台」。我把焦點放到這個節點,再按 Arrow Down,焦點移到下一筆「行動應用程式」,aria-selected 仍留在 LumenCore。

這一段符合預期:焦點只是準備操作的位置,選取才是已保存的結果。

但頁面下方的摘要從「目前選取:LumenCore 平台」變成「目前選取:◇」。它抓到的是圖示文字,不是節點名稱;瀏覽器 Console 同時出現三筆 SVG viewBox 格式錯誤。

檢查項目 2026 年 7 月 24 日結果 當時判斷
Arrow Down 移動焦點 焦點移到下一個可見節點。 通過。
選取是否跟著焦點改變 LumenCore 仍維持選取。 通過。
選取摘要 顯示成「◇」。 未通過,節點名稱取值錯誤。
Console 出現三筆 SVG viewBox 錯誤。 未通過,圖示輸出需要修正。

如果只看箭頭有沒有開合,這兩個 bug 都會被放過。寫 Prompt 時除了鍵盤規則,還要交代選取資料從哪個欄位取得、摘要顯示哪個名稱,最後再打開 Console 看一眼。畫面會動,只代表它真的會動。

修正後複測:摘要與 SVG 錯誤已排除

後續修正把摘要改成讀取真正的節點名稱,也替五個展開圖示補上 viewBox="0 0 24 24"

2026 年 7 月 27 日重新載入後:

  • 選取摘要會顯示節點名稱。
  • Console 不再出現 SVG 格式錯誤。
  • 方向鍵移動焦點時,原本的選取狀態仍會保留。

目前已通過節點名稱、焦點/選取分離與 Console 複測。正式螢幕閱讀器實聽仍未完成,因此不能把「鍵盤操作正常」直接寫成所有輔助科技都通過。摘要顯示「◇」和三筆 Console 錯誤是歷史上曾失敗的結果,不是目前仍存在的問題。

真實資料不一定一次載完:展開、載入與失敗要分開

正式系統的孩子資料常常要等使用者展開後才載入。這時「有沒有孩子」「正在載入」「載入失敗」不能全部用同一顆旋轉箭頭表示。

父節點在尚未取得孩子前,至少要決定:

  • 展開後是否先保留節點位置並顯示 Loading。
  • 載入失敗時能否重試,父節點是否仍維持展開意圖。
  • 重新收合再展開時,使用快取還是重新查詢。
  • 搜尋結果展開祖先節點後,焦點要落在哪一筆。
  • 權限不足的孩子是隱藏、停用,還是顯示原因。

這些是資料生命週期,不是 Tree View 的外觀選項。若 AI 只收到「點箭頭呼叫 API」,很容易在失敗時把整棵樹收回去,使用者連剛才展開哪一層都得重新尋找。

層級如果深到一直展開、展開、再展開,也別急著繼續美化 Tree View。那可能代表資訊架構需要搜尋、篩選、Breadcrumb 或獨立詳細頁,不是再多縮排兩格就能救回來。

Treegrid 在階層之外,還要比較多欄資料

如果使用者除了專案名稱,還要比較負責人、狀態與截止日,單純 Tree View 就不夠用了。Treegrid 元件頁把階層放在第一欄,其餘欄位維持對齊。

Vibe UI Atlas 的 Treegrid 操作區:第一欄管理階層,其他欄用來比較資料

圖 5:第一欄展開專案與子任務,負責人、狀態和截止日仍能沿欄位比較。

Treegrid 的功能完整,維護成本也最高。它同時處理表格、焦點移動、列選取、展開收合與手機欄位策略。W3C 將 Treegrid 定義為具有階層關係的資料格狀介面,鍵盤焦點可能停在列或儲存格上,互動規則必須先決定。W3C WAI-ARIA APG:Treegrid Pattern

若需求只是找到某個資料夾,我不會因為 Treegrid 看起來像企業系統就選它。反過來,真的需要比較多欄時,也不要把負責人、狀態與日期全塞進 Tree View 的節點名稱。

窄螢幕時,表格可以在自己的容器內橫向閱讀,整張頁面不能跟著左右漂移。若欄位多到必須一直滑,摘要卡或獨立詳細頁往往比把字壓碎更實用。

閱讀層次與同列明細:Nested List、Expandable Row

Nested List 有層次,不代表一定要操作一棵樹

文件目錄、條款清單與靜態分類說明也有層次,但讀者通常只想順著內容往下讀。Nested List 元件頁保留標題與縮排,不另外加入展開控制。

Vibe UI Atlas 的 Nested List 實際 Demo:保留內容層次,不額外加入展開控制

圖 6:整個內容結構一次呈現,沒有目前選取、展開狀態與方向鍵走訪。

原生巢狀 <ul> 已經能表達未排序內容的階層關係。沒有「逐層操作資料」的需求時,清單語意與視覺縮排就足夠。MDN:<ul> HTML element

它幾乎沒有什麼好操作,反而是優點:少一個展開按鈕,就少一組狀態、焦點與例外狀況。

當 AI 自動替每個章節加上箭頭時,先問使用者是否真的需要收合。若目的只是讓段落看得出層級,Nested List 已經完成工作,不用強迫一份靜態目錄學會走路。

Expandable Row 展開的是這一列,不是下一代

平面資料表裡,使用者有時只想多看一點目前任務的資訊。Expandable Row 元件頁用「活動頁無障礙檢查」示範檢核進度、備註和下一步。

Vibe UI Atlas 的 Expandable Row 實際 Demo:展開同一筆任務的檢核明細與下一步

圖 7:展開後仍是「活動頁無障礙檢查」這筆任務的內容,沒有憑空長出三個子任務。

Tree View 的箭頭表示往下一層走;Expandable Row 的按鈕則把目前資料說得更完整。按鈕名稱、aria-expanded 與被控制的明細區塊要能對得起來,不能只放一顆沒有對象的箭頭。

資料表本身仍要保留表格語意。HTML <table> 用於有列與欄的資料,<caption> 也能幫助使用者理解用途。MDN:<table> HTML element

收合明細時,任務狀態、列選取與使用者剛完成的篩選不能一起被重設。Expandable Row 在整理閱讀空間,不是在替資料表執行 Reset。

改寫 Prompt:先交代資料關係,再決定箭頭怎麼動

請為 LumenDesk 製作「產品與設計中心」的階層資料畫面。

資料關係:部門底下有專案,專案是部門的孩子,不是同一列的補充明細。
元件:使用 Tree View。父節點顯示可展開箭頭,沒有孩子的葉節點不要顯示假箭頭。
狀態:展開/收合、鍵盤焦點、已選取節點必須分開呈現;不要只靠顏色區分。
鍵盤:這個單選 Demo 採焦點與選取分離。Up/Down 只在可見節點間移動焦點;Right 展開或進入第一個孩子;Left 收合或回到父節點;Enter 執行目前節點的預設動作,葉節點的預設動作是選取。不要讓方向鍵經過每一筆時就改寫目前選取。
資料:設計系統組可展開,底下有「元件盤點計畫」;所有人名、日期、專案皆為虛構資料。

若孩子資料延後載入,展開後顯示 Loading;失敗時保留父節點與展開意圖,提供重試,不要讓整棵樹跳回初始狀態。

如果使用者還要比較負責人、狀態、截止日,改用 Treegrid:只有第一欄縮排,其他欄保持對齊;手機版可讓表格容器局部橫向捲動,但整頁不可水平溢出。

如果只是展開同一筆任務的備註和檢核項目,改用 Expandable Row,不要把明細偽裝成子節點。

Prompt 裡先寫「專案是部門的孩子」,比寫「箭頭使用 16px 灰色圖示」更能決定畫面會不會走偏。視覺可以再調,資料關係一旦錯了,後面每一次展開都會繼續錯下去。

驗收階層元件,先別被箭頭會轉騙過去

交付前,我會沿著資料關係、焦點與載入狀態逐一檢查:

  • 展開後出現的是孩子,還是目前這列的補充?
  • 父節點有展開狀態嗎?沒有孩子的葉節點是否拿掉假箭頭?
  • 鍵盤焦點、選取節點與展開狀態能否分辨?
  • 方向鍵移動時,選取值有沒有被偷偷改掉?
  • 收合父節點後,焦點是否仍停在看得見的位置?
  • 延後載入失敗時,使用者能否重試,原本展開位置是否保留?
  • Nested List 是否只呈現內容結構,沒有多做一組用不到的互動?
  • Treegrid 是否真的需要多欄比較?窄螢幕該局部捲動、顯示摘要,還是前往詳細頁?
  • Expandable Row 收合後,表格條件與列狀態是否仍保留?

這份清單沒有檢查箭頭轉得夠不夠滑順。關係、狀態與焦點正確後,動畫才輪得到上場。

專案結構分清楚後,「漂亮彈窗」卻先替我按了確定

現在,真正的部門、專案與任務父子關係進入 Tree View;需要同時比較多欄時才升級 Treegrid;同一筆任務的備註與檢核紀錄則回到 Expandable Row。Nested List 也不用為了看起來有功能,硬背一整套方向鍵操作。

下一步,我按下成員列上的「停用帳號」,只留下另一句很熟悉的需求:

按停用時跳出一個漂亮的彈窗。

下面是依照第一版問題重建的錯誤現場,不含真實帳號與個人資料:

停用帳號的錯誤第一版:白色卡片與灰色遮罩已完成,但停用對象不明、危險動作先取得焦點,背景仍可操作

圖 8:彈窗只問「確定要停用嗎」,沒有說停用誰;初始焦點落在危險操作,背景卻仍然能點。外觀完成了,安全退出的規則還沒進場。

白色卡片、灰色遮罩和紅色提示全都到齊,看起來的確像完成品。問題是,使用者不知道要停用誰、會失去什麼;按 Escape 會不會取消、關閉後焦點回到哪裡,也沒有答案。

明天,我們就從這個彈窗開始,拆開 Dialog、Modal Dialog、Alert Dialog 與危險確認,也看看紅色按鈕出現以前,取消路徑到底有沒有先準備好。

延伸閱讀

資料查閱:2026-08-07。


上一篇
Day 16|選一個值,還是執行命令?Select、Menu、Overflow Menu 與 Command Palette
下一篇
Day 18|彈窗要不要鎖住背景?Modal、Non-modal、Alert Dialog 與危險確認
系列文
看得懂、叫得出、驗得過:30 天 VibeCoding UI 元件實戰23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言