UX Spec

Design Pattern: Tree View

Amy TangSep 10 2026
Open Spec Changes
add-tree-view-component
tree-view-navigation (archived 2026-04-15)
site-management-for-portal (archived 2026-09-02)
Prototype
TreeViewList-demo.html(VORTEX-1.0 demo)

Visual basis: vortex-1.0 — verify behavior / copy / structure, not pixel style.

Context

Why we're building this

Many parts of the platform — Sites, Floorplans, View's camera list, Access Control — show hierarchical data as a tree, but each built its own version, so expanding, collapsing, and selecting behave differently from screen to screen. The trigger: Site Management grew from three levels to five (a Site with up to four Area levels), and the old fixed-depth trees can't handle that.

This pattern defines one reusable tree that works at any depth and behaves the same everywhere.

Section 01

節點結構與狀態

一個通用樹狀列表元件,顯示巢狀階層資料。元件本身不認得「Site / Area / Camera」,只認得「節點」與「種類(kind)」——icon、空狀態文案、業務語意都由使用端透過資料與設定傳入。

下圖為 Tree View 的預設狀態(以 Sites 為例):

tv-01-anatomy
Tree View — 預設狀態(280px sidebar)

節點類型 Node types

類型 外觀
有箭頭(無 icon) chevron(16×16) + label
有箭頭(有 icon) chevron(16×16) + icon(20×20) + label
無箭頭(無 icon) 無箭頭,label 左側 12px padding 對齊
無箭頭(有 icon) 無箭頭,icon(20×20) + label,左側 12px padding
空提示行 Empty Hint Row Regular 400 文字,無 icon / chevron,disabled 不可點;文字由使用端依 kind 傳入(如「No cameras」)

箭頭由「節點種類」決定,不由當下有無子項決定 Chevron is per kind

依據 add-tree-view-component 的 Node-Kind-Driven Behavior:節點行為由它的種類決定(可展開 / 可容納哪些子種類 / 終端),不由它在樹中的深度、也不由當下有幾個子項決定;同一份 spec 的 mixed-kind 情境明確寫著終端種類不顯示 chevron。

種類 箭頭 理由
容器種類(Site、Area、Floor plan) 一律顯示,即使當下沒有任何子項 箭頭代表「這是可以往下展開的層級」,不代表「現在裡面有東西」;否則同一個 Area 會因為別人新增 / 刪除子項而在使用者眼前改變外觀
終端種類(Device,如 View / Floorplans sidemenu 裡的 Camera) 不顯示 裝置底下不可能再有子層,箭頭會是一個永遠點不出東西的控制項

與已上線 spec 的落差。 已 deploy 的 tree-view-navigation 寫的是「chevron 用於有子項的節點」,add-tree-view-component 已用 MODIFIED 覆寫為依 kind 判斷。各頁現行實作只在有子項時畫箭頭是預期落差,不是本規則的例外。

「無箭頭」代表「這個種類不會有子層」,不是「目前沒有子項」。真正空的容器節點會轉為空容器 Empty Container 狀態(文字與 icon 變淡,見下方節點狀態表),但箭頭仍在、仍可展開;「空」的判斷依據見下一小節,展開後是否出現一列空提示行則依 profile 而定(見下方邊界表)。

「空容器」看的是有沒有直屬資源,不是樹上有沒有子節點 Empty means holds nothing

變淡與空提示行是兩件事,判準不同:

樣式 判準
變淡(空容器 Empty Container) 該節點沒有子節點,且沒有任何直屬資源(floor plan / device)—— 也就是裡面真的什麼都沒有
空提示行 Empty Hint Row 展開時樹上沒有子節點,且該場域有提供對應文案(見下方邊界表)

差別只在資源不是樹上節點的場域才會顯現:

  • View / Floorplans sidemenu:camera、floor plan 本身就是節點,「沒有子節點」與「什麼都沒有」是同一件事,兩個判準結果相同。
  • site tree(Site Management 主樹、Manage Device Access sidemenu):樹上只有 Site / Area,指派到節點上的 device 不以節點呈現。所以一個有 10 台 camera、但沒有 Area 的 Site 不會變淡;變淡在此承載的是樹本身看不出來的資訊:這個節點是真的空的。

因此同一個節點可以「不變淡、但展開後也沒有任何列」:不變淡是因為它有直屬 device,沒有列是因為它沒有子節點(site tree 又不提供空提示行文案)。

資源只算直屬:有子孫的節點本來就有子節點,不會落入空容器的判斷。

原型現況。 VORTEX-1.0 demo(TreeViewList-demo.html)符合本判準:變淡同時看子節點與直屬資源,並以一個「有 device、沒有子 Area」的節點示範不變淡。Manage Device Access 的原型目前沒有變淡樣式 —— 以本節為準。

以上依 Figma key screen 確認(2026-08-08):Floorplans sidemenu 中 Floor 1–Floor 6、Parking lot B1 / B2 等 Floor plan 節點皆有箭頭,其中沒有 camera 的 Floor 4 展開後顯示 No cameras;沒有 floor plan 的 Area Outdoor areas 展開後顯示 No floor plans。View sidemenu 中 Camera 001–Camera 006 皆無箭頭,只有 icon + label。

名稱過長 Long names

節點名稱單行顯示、不換行;放不下時以 ellipsis 截斷(white-space:nowrap + text-overflow:ellipsis)。名稱區域佔滿該列扣掉 chevron / checkbox / icon 之後的全部剩餘寬度,所以可見字數隨縮排深度遞減 —— 越深的節點看得到的名稱越短。

hover 名稱區域顯示完整名稱。 由於名稱區域已涵蓋該列右側的所有留白,實務上只有左側的 chevron / checkbox / icon 不觸發。

只在真的被截斷時顯示。 名稱完整顯示得下時 hover 不出 tooltip。這與 Sites Breadcrumbs Section 01 的 tooltip 原則一致。

用平台的共用 tooltip 元件,不是瀏覽器原生 title。 樣式與定位由該共用元件定義,權威在 Sites Breadcrumbs Section 01。

節點狀態 Node states

狀態 外觀(VORTEX 1.0 token)
預設 文字 @color-text01、icon @color-icon03、透明背景
Hover 文字 @color-text01、背景 @color-surface02(內層容器圓角 8px)
選取 Active 文字 @color-text01、背景 @color-surface04(內層容器圓角 8px),無邊框
空容器 Empty Container 文字 @color-text20 / icon @color-icon29(變淡);可展開、可選取;hover / selected 時恢復一般色。條件是沒有子節點且沒有直屬資源(見上方「空容器」小節)
停用 Disabled 文字 @color-text06 / icon @color-icon01,整列完全不可互動(不可點擊、不可展開、不回應 hover)。見下方註記

停用是繼承來的通用狀態,本 deck 的四個 profile 都沒有會停用的 Site / Area 節點。 在這個 pattern 裡「disabled」實際活著的用途只有一個:空提示行沿用它的文字色(@color-text06)與 不可互動性。節點層級的停用規則以 OpenSpec add-tree-view-component 為準,本節不擴充;目前 沒有對應的 key screen。

別和空容器混淆:空容器只是變淡,仍可選取、仍可展開。

輔助線 Indent guides

狀態 外觀
預設 不顯示
Hover 該節點所屬最頂層群組底下所有展開層級出現微弱垂直線(@color-outline19)
Active 選取節點展開後,直接子層出現較明顯垂直線(@color-outline04);收合、或沒有子項可展開時,改由上一層顯示
Active + Hover 較明顯的線優先

線畫在「展開出來的那一層」上,不是畫在節點上。 所以要判斷線出現在哪,看的是選取節點底下有沒有 展開層可承載它:

選取的節點 線的位置
已展開且有子項 它自己的子層 —— 線與它的子節點並排
已收合,且位於某個節點底下 上一層 —— 線與該節點及其兄弟並排
沒有子項可展開,且位於某個節點底下 上一層,同上
本身是最頂層 見下方「最頂層沒有上一層」
tv-guide-own
Active 線的第一種 — 選取「Building A」(已展開且有子項),較明顯的線畫在**它自己的子層**,與 Basement 等子節點並排(prototype)
tv-guide-parent
Active 線落到上一層 — 選取「Basement」(此 profile 下沒有子項可展開),線改由**上一層**顯示,與 Basement 及其兄弟節點並排。本圖示範的是「沒有子項」那一格;recipe 會先展開全部,所以 Basement 是展開狀態,**「已收合」那一格沒有對應圖**(prototype)

判準是「有沒有子項」,不是「第幾層」。 依層數寫死(例如 level === 4)會漏掉「層級不深但也沒有 子項」的節點 —— 一個還沒有 Area 的 Site 就是這種。樹的最深一層無法再展開,底下沒有可承載線的層級, 因此走的是「上一層」那一格;這不是另一條規則,是同一條規則在「無可展開層」時的結果。

Site Management 的最深節點層是 Area,不是裝置。 該情境的樹只有 Site 與 Area 兩種節點,裝置不是 樹節點(見 Section 06 的 profile 定義)。談「最深一層」時不要把裝置算進來。

最頂層沒有上一層 Top-level nodes

最頂層節點不在任何縮排層裡,所以當規則要求「線落到上一層」時,它沒有上一層可落 —— 選取這種節點時看不到線。這涵蓋兩種情形,不是只有一種:

  • 最頂層節點已收合(不論有沒有子項)
  • 最頂層節點沒有子項

這是預設狀態,不是罕例:Site Management 的樹初始為全部收合,所以剛進頁面選任何一個 Site 都屬此格。

唯一的例外是「空提示行」。 沒有子項的節點展開後,若該使用端有提供空提示行的文案,那一列會把子層 容器撐開,線就會出現在提示行旁邊。Site Management 與 Manage Device Access 不提供這段文案(子層為空 時不顯示任何列),因此在這兩個情境看不到線;View 與 Floorplans 有提供(No cameras / No floor plans),因此在那兩個情境線是看得見的。空提示行的規則見 Section 06。

這一格與「上一層」兩格的來源不同。 上游 add-tree-view-component · Indent Guides 只定義了預設、 hover、以及「選取節點的直接子層」與優先序;「落到上一層」與「最頂層看不到線」都只在原型中成立, OpenSpec 沒有對應要求。要把它們變成正式要求,需補一份 delta。

尺寸 Dimensions

項目 值
Node height 40px
Node horizontal padding 8px
Node internal gap 4px
Chevron 16×16px
Node icon 20×20px
Indent per level 16px
Leaf 左側 padding 12px
選取內層容器圓角 8px
Level-1 群組間距 8px
Container padding 8px
輔助線寬度 1px

字體:節點文字 Segoe UI 16px Semibold(600) line-height 1;空提示行 Segoe UI 16px Regular(400) line-height 1(不用 italic)。

邊界 Boundaries

情境 行為
沒有任何資料 不顯示樹,由使用端處理 empty state
展開的節點沒有子項目 是否顯示一列 disabled 的空提示行(Empty Hint Row)由 profile 決定(見 Section 06):site tree 不顯示任何列;View / Floorplans sidemenu 顯示一列,文字由使用端依 kind 提供(如「No cameras」/「No floor plans」)。兩種 profile 下節點本身都保留 chevron、仍可選取;文字與 icon 是否變淡另看它有沒有直屬資源(見上方「空容器」小節)

空提示行屬 profile 層級的差異。

  • site tree(site management 主樹、Manage Device Access sidemenu —— 以站點階層本身為主體的場域):展開沒有子項的 Site / Area 不顯示任何列,直接接續下一個同層節點。
  • View / Floorplans sidemenu(樹的葉層是某一類具體內容):顯示一列空提示行。Figma key screen 可見 No cameras(沒有 camera 的 Floor plan)與 No floor plans(沒有 floor plan 的 Area)。

差別的依據是「說不說得出少了什麼」:View / Floorplans 的容器底下裝的是一種明確的內容,講得出 No cameras;site tree 的 Area 底下是尚未建立的下層站點結構,沒有具體的東西可以說「沒有」。

OpenSpec 依據:add-tree-view-component 的空提示行是「當且僅當使用端提供該 kind 的文案才顯示」,並明寫 site tree 不提供文案、不顯示提示行;Manage Device Access 的「no placeholder or hint row is shown」是同一條規則的下游結果。

Token gap:@color-icon29(空容器 icon 變淡)尚未加入 theme-color/index.less,以 OpenSpec add-tree-view-component 為準。

TODO / 未解問題

  • @color-icon29 token 尚未落地,需與前端確認補上。
Section 02

選取

規則 Behaviour

  • 點擊節點 label(或 icon)= 選取;一次只能選一個(single-select)。
  • 點擊選取不改動任何展開 / 收合狀態——使用者能點到的節點必然已經可見(其祖先本來就是展開的),無需再展開。
  • 選取後,元件會通知使用端「使用者選了哪個節點」,由頁面接手做後續(例如右側面板顯示該節點對應的內容)。元件本身不決定選取後的行為。
  • 點擊 chevron 只切換展開 / 收合、不影響選取(見 Section 03)。

選取的規格本身含「展開被選節點的收合祖先」;但對使用者點擊而言這一步是 no-op(能點到,代表其祖先本來就已展開)。真正會「看到祖先被展開」的情境是程式化定位選取(Section 05,定位藏在收合祖先下的目標)與搜尋命中(Section 04,展開命中節點的祖先)。

下面兩張圖分別為「選取態」與「選取 + hover 同時」(hover 為微暗背景、選取為微亮背景):

tv-selected
選取態 Selected
tv-selected-hover
選取 + Hover 同時

選取「不會」做的事 釐清邊界

點擊選取只做「標記為選取」,完全不碰展開 / 收合狀態:

  • 不改變被選取節點本身的展開 / 收合狀態(原本收合就維持收合)。
  • 不展開被選取節點的子節點。
  • 不收合其他已展開的節點。

驗收條件 QA · Given-When-Then

  • Given 點擊某節點 label,Then 該節點成為唯一選取(前一個取消),且展開 / 收合狀態不變。
  • Given 點擊 chevron,Then 只切換展開 / 收合、選取不變。

「選取藏在收合祖先下的節點會展開祖先」屬程式化定位選取,驗收條件見 Section 05。

元件與 Token 決策

  • 選取態:文字 @color-text01、背景 @color-surface04(內層容器圓角 8px)。
Section 03

展開與收合

點擊分離 Click separation

[chevron] [icon] [label] [counter]
 ↑ 展開 / 收合         ↑ 選取
  • chevron 區:只切換展開 / 收合,不影響選取。
  • label / icon / counter 區:只選取,不影響展開 / 收合。
  • 整列 hover:整列背景變化。

counter 只出現在上圖的列結構裡,本 deck 沒有定義它計什麼。 它在點擊分離上與 label 同區 (點下去是選取),但「顯示哪個數字、什麼時候出現」目前沒有規則,也沒有任何 profile 在用; 要用之前需先定義。

tv-item
單一 treeview item — 點 chevron=展開 / 收合,點其餘(icon / label / 計數)=選取

全部展開 / 全部收合

頂部節點計數列(「N Sites」)右側的單顆按鈕,即為「全部展開 / 全部收合」切換:

tv-expand-all-btn
節點計數列右側的全部展開 / 全部收合按鈕

這是兩態切換,判定基準是「樹是否已全部展開」,不是「是否有任何節點展開」:

控制 行為
展開按鈕 icon 尚未全部展開時(含全收合與部分展開)顯示 chevrons-down,tooltip Expand all
收合按鈕 icon 已全部展開時才顯示 chevrons-up,tooltip Collapse all
全部展開的停點 可設定「全部展開」停在某一種類(如展開到 Floor plan,Camera 維持收合)
初始展開 可設定初次載入時展開到哪一種類;未設定時所有 root 節點皆收合。各 profile 的實際設定值見 Section 06

因此部分展開的樹按下按鈕是繼續展開剩下的,不是收合;沒有「一鍵回到全收合」的捷徑,須先全部展開。

停點與判定基準必須成對設定。 判定「已全部展開」時列入的節點範圍,必須與「全部展開」實際會展開的範圍一致。若 profile 設了停點卻仍以全樹判定,按鈕將永遠停在 Expand all、無法收合。

驗收條件 QA · Given-When-Then

  • Given 點擊 chevron,Then 切換該節點展開 / 收合、選取不變。
  • Given 點「全部展開」,Then 展開到設定的停點種類為止。
  • Given 樹為全收合或部分展開,Then 按鈕顯示為 Expand all(chevrons-down),且點擊後展開至停點。
  • Given 樹已全部展開,Then 按鈕顯示為 Collapse all(chevrons-up),且點擊後全部收合。
Section 04

搜尋

搜尋的過濾、命中 highlight、自動展開祖先、展開狀態快照 / 還原、以及 No Matches Found 空狀態,都是元件內建的行為;使用端只提供搜尋輸入框。

搜尋流程 Flow

  1. 使用者輸入 → 首次輸入時快照當前展開狀態。
  2. 即時過濾(不分大小寫)。
  3. 自動展開命中節點的所有祖先。
  4. 命中文字以 highlight 顯示;無關分支隱藏。
tv-search
搜尋命中 — 命中文字 highlight、祖先一併顯示提供 context(擷取自本 deck 的 VORTEX-1.0 demo,Site Management profile)

過濾規則 Filter rules

節點 行為
命中 名稱含關鍵字(不分大小寫),正常可選
命中的祖先 顯示且可選(正常樣式、不灰化),提供階層 context
命中的子節點 預設不展開;父層也命中才展開
完全無關分支 隱藏

清除搜尋 Clear

操作 行為
點清除(X) 清除搜尋文字
展開狀態 恢復搜尋前的快照
選取狀態 搜尋前有選取則恢復;搜尋中有新選取則保留新選取
highlight 全部移除

無命中 No Matches Found

搜尋不到任何節點時,整個樹區換成空狀態:240 寬的區塊在列表區垂直置中,由上而下是 64×64 插圖、標題、說明文字,三者間距 8px、皆置中對齊。

tv-no-matches
無命中 — 240 寬的空狀態區塊在列表區垂直置中:64×64 插圖 + `No Matches Found` + 說明文字,間距 8px;計數列一併收掉(版面依 Figma key screen `sidemenu treeview (No Matches Found)`)
元素 規格
插圖 64×64,@color-icon02
標題 No Matches Found,Segoe UI 16px Bold(700) line-height 1,@color-text02
說明 Please try adjusting filters or use different keywords.,Segoe UI 14px Regular(400) line-height 1.3,@color-text03
區塊寬度 240(280 的列表區左右各留 20)
垂直位置 在列表區垂直置中
計數列 不顯示。無命中時「N Sites」計數列連同其全部展開按鈕一併收掉,列表區從搜尋框下方直接開始(依 key screen:其他狀態的 frame 都有 36px 的計數列,本 frame 沒有)

標題與說明的文字由使用端傳入(見下方邊界表),版面與樣式則屬本元件。

本節的版面規格只覆蓋 Tree View 元件,不是平台權威。 家族中有四處引用本節取得空狀態版面 —— Filter Combo §05、 Device Picker §04、 Manage Device Access §02 與 §05 —— 其中只有 MDA §02 是樹,另外三處不是。平台層級的空狀態版面權威由 Reskin / Design system 專案訂,屆時這四處與本節一律以該專案為準。

Filter Combo §05 那一處要看清楚是哪個空狀態:該 deck 的 Sites / Event types 選單確實是樹狀, 但引用本節的是頁面清單的空狀態;選單內的空狀態是另一套規格(單行置中短句,見該 deck §03), 與本節無關。

02 Sites Related Pages §09 的 site picker 不在此列:它有自己的 key screen,版面權威在它自己那一節,只有文案與本節同源 (同一份 OpenSpec 的要求本文)。

狀態與邊界

情境 行為
無命中 No Matches Found 於 tree 區顯示「No Matches Found」空狀態,隱藏所有節點;說明文字為「Please try adjusting filters or use different keywords.」。該文字由使用端提供(OpenSpec add-tree-view-component),但字串不可各自發明:同一份 OpenSpec 已把這兩句寫進要求本文,平台上各 surface 一律用同一句。版面見上方「無命中」小節
disabled 節點被命中 顯示但維持 disabled、不可選
選取節點仍在結果中 維持該節點的選取態
選取節點被過濾掉 選取在邏輯上保留、但不可見;清除搜尋後恢復顯示
搜尋中選了新節點 清除後保留新選取
搜尋中外部觸發定位選取 先清除搜尋、恢復展開,再執行定位選取(見 Section 05)

驗收條件 QA · Given-When-Then

  • Given 輸入關鍵字,Then 只顯示命中節點及其祖先,其餘隱藏。
  • Given 命中節點,Then 自動展開其祖先,且命中文字 highlight。
  • Given 清除搜尋,Then 展開狀態恢復成搜尋前的快照。
  • Given disabled 節點被命中,Then 顯示但維持不可選。
  • Given 搜尋無任何命中,Then 顯示「No Matches Found」空狀態並隱藏所有節點。
  • Given 選取的節點被搜尋過濾掉,Then 選取邏輯上保留,清除搜尋後恢復可見。
Section 05

外部觸發選取

外部事件(例如點擊地圖上的 camera marker)可觸發 tree 選取特定節點。

流程 Flow

  1. 外部觸發「定位並選取」某個目標節點。
  2. 若在搜尋中,先清除搜尋、恢復展開狀態。
  3. 找到目標節點 → 展開所有祖先 → 選取 → 平滑捲動到可見區。
tv-reveal-result
外部觸發定位選取的結果 — 祖先已展開、目標節點呈選取態(prototype)
  1. 找不到目標節點時什麼都不做——不改變畫面、也不提示使用者(規格為 nothing changes)。

狀態與邊界

情境 行為
目標已可見且已選取 不做任何事
目標已可見但未選取 選取,必要時捲動
目標不存在 畫面完全不變:不顯示錯誤或提示、展開狀態不動、原本已選取的節點保持選取、不捲動
搜尋中觸發 先清除搜尋、恢復展開,再執行定位選取

原型待修: TreeViewList-demo 目前無條件呼叫捲動,已在畫面內的節點也會被捲到置中,與上表前兩列不符。以本表與 OpenSpec Selection Visibility and Auto-Scroll · No scroll when already visible 為準。

驗收條件 QA · Given-When-Then

  • Given 外部觸發定位一個收合的深層節點,Then 展開其祖先、選取、捲動到可見。
  • Given 目標節點不存在,Then 畫面完全不變——沒有錯誤提示、展開狀態與原有選取都不變、不捲動。
  • Given 搜尋中觸發定位選取,Then 先清除搜尋並恢復展開,再執行定位選取。

TODO / 未解問題

  • 鍵盤導航(方向鍵 / Enter / 空白鍵)目前不實作,設計上預留未來擴充空間。
  • 「目標不存在」沒有定義任何使用者回饋:規格只寫 nothing changes,指向已刪除節點的外部連結 按下後不會給使用者任何訊息。是否需要提示待設計確認(ADAT-823)。
Section 06

使用場景

同一個元件、不同資料與設定,撐起平台上數種樹狀情境。元件不綁定業務語意——icon 由使用端**依節點種類(kind)**傳入。

Icon 規則:Site / Area 節點一律無 icon;icon 只用來區分不同「種類」的節點。因此:Site Management 只有 site / area → 完全無 icon;View 多了 Camera 種類 → Camera 有 icon;Floorplans 有 Floor plan + Camera 兩種 → 兩者各有 icon。

Site Management Sidebar 五層、無 icon

Site > Area × 4,純文字節點(無 icon)。採單選、fill 選取樣式。

tv-sitemgmt
Site Management sidebar — 五層、純文字節點(無 icon),單選 fill 樣式

View Sidebar 最多六層、Camera 有 icon

Site > Area × 4 > Camera——Camera 直接掛在最深的 Area 底下(無 Floor plan 層);Camera 由使用端依節點種類傳入 icon。

tv-view
View — 最多六層、Camera 有 icon

Floorplans Sidebar 最多七層、Floor plan / Camera 有 icon

Site > Area × 4 > Floor plan > Camera——比 View 多一層 Floor plan;Floor plan 與 Camera 由使用端依節點種類傳入對應 icon。

tv-floorplans
Floorplans — 最多七層、Floor plan / Camera 有 icon

以上是「側邊欄」情境;同一個元件也用在對話框內的挑選器:

Manage Device Access by Site 多選兩態

以 Site / Area 為單位授權的權限設定也用 Tree View,採多選模式:每列 chevron 後有 20×20 兩態勾選(未勾 / 勾選,站點節點無半選)。勾選的連動語意(對稱 cascade、祖先永不自動連動)以 Design Pattern: Filter Combo §03 為權威。checkbox 的存取語意(該節點「自己的直屬裝置」是否保有存取、隨裝置狀態即時推導)與 All sites 列保留三態的例外,規則以 Manage Device Access by Site spec 為權威,本節不重列。

此場域只有 Site / Area 兩種容器節點,因此樹上每一列都顯示 chevron(Section 01 的 kind 規則直接套用)。(樹以外的 All sites 列不是節點,沒有 chevron,見 Manage Device Access by Site。)

兩態與 OpenSpec 不一致,spec 待更新。 add-tree-view-component 的 Multi-Select Mode 仍寫「20x20 three-state checkbox」。站點節點的兩態以 Manage Device Access 那份 deck 為準(原型亦為兩態)。

空提示行:不顯示。 此場域屬 site tree,展開沒有子項的 Site / Area 之後不出現任何列,直接接續下一個同層節點(同 Site Management 主樹,見 Section 01 邊界表的 site tree profile)。

tv-multi
多選模式(Manage Device Access by Site 的 sidemenu)— 搜尋、選取計數、All sites 列,以及每列 chevron 後 20×20 兩態勾選(Figma key screen)

初次載入的展開與選取 Initial state per profile

初始展開層級與初始選取是各 profile 自己的設定,不是元件的預設行為。元件本身未設定初始 展開時,所有 root 節點皆收合(見 Section 03)。

場域 初次載入的展開 初次載入的選取
Site Management sidebar 全收合 未選取(右側顯示 No Site Selected,見 Site Management US3)
View sidemenu 全收合 選取第一個 Site
Floorplans sidemenu 展開到 Floor plan 那層(Floor plan 列可見、其 Camera 維持收合) 未選取
Manage Device Access sidemenu 全展開 未選取

兩者是獨立的設定:View 全收合卻仍選取第一個 Site —— 那個 Site 是 root,本來就看得到, 不需要展開任何節點(點擊選取不改動展開狀態的規則見 Section 02)。

本 deck 是這四組值的唯一記錄處。 OpenSpec 只規範機制(可設定初始展開到哪一種節點, 以及未設定時全部 root 收合),沒有規範任何 surface 的實際值;初始選取連機制都還沒有 —— 元件目前沒有「載入時選取某個節點」的設定,View 的「選取第一個 Site」在實作上落在使用端。 這一點需要補進 OpenSpec,見下方 TODO。

狀態與邊界

情境 說明
層數不固定 節點行為由 kind 決定,不由深度決定;同一 kind 可出現在不同深度
未來取代 之後取代 Floor Plan 專案現有寫死層數的 tree 實作

Move to 目標挑選器不是 Tree View 的使用場景。 Site Management 的「Move to」目的地挑選器改用單選 Site picker,規格見 Sites Related Pages 的 Section 09;使用情境與 key screen 見 Site Management spec US4。

TODO / 未解問題

  • 初始選取需要一條 OpenSpec 規範。 上表的四個展開值對應「初始展開到哪一種節點」這個 設定,但「View 載入時選取第一個 Site」目前沒有對應的元件能力。要決定它是元件的設定 還是使用端的責任(頁面載入後自行呼叫選取)—— 這會影響 RD 怎麼實作。

驗收條件 QA · Given-When-Then

  • Given Site Management 資料(最多五層、無 icon),Then 正確渲染且無 icon。
  • Given View 資料(最多六層,Camera 有 icon),Then 依節點種類顯示 Camera icon。
  • Given Floorplans 資料(最多七層,Floor plan / Camera 有 icon),Then 依節點種類顯示對應 icon。
  • Given 一個沒有任何子項的 Area(Site Management 或 Manage Device Access),Then 該列仍顯示 chevron 且可點擊展開。
  • Given View / Floorplans sidemenu 的 Camera 節點,Then 不顯示 chevron。
  • Given Floorplans sidemenu 中沒有 camera 的 Floor plan,Then 仍顯示 chevron;展開後顯示 No cameras 空提示行。
  • Given Floorplans sidemenu 中沒有 floor plan 的 Area,Then 仍顯示 chevron;展開後顯示 No floor plans 空提示行。
  • Given 在 site tree(Site Management 主樹或 Manage Device Access sidemenu)展開一個沒有子項的容器節點,Then 不顯示任何列,直接接續下一個同層節點。
  • Given site tree 中一個沒有 Area、但有直屬 device 的 Site,Then 該列不以空容器樣式變淡(箭頭仍在、仍可選取),展開後也不顯示任何列。
  • Given site tree 中一個沒有 Area、也沒有任何直屬 device 的 Site / Area,Then 該列以空容器樣式變淡,箭頭仍在、仍可選取。
  • Given Floorplans sidemenu 中一個沒有 floor plan 的 Area(資源本身即節點),Then 兩個判準結果相同:該列變淡,展開後顯示 No floor plans。
  • Given 初次載入 Site Management sidebar,Then 樹全收合且沒有任何節點被選取。
  • Given 初次載入 View sidemenu,Then 樹全收合,但第一個 Site 為選取態。
  • Given 初次載入 Floorplans sidemenu,Then 展開到 Floor plan 那層(Floor plan 列可見、Camera 收合),且沒有任何節點被選取。
  • Given 初次載入 Manage Device Access sidemenu,Then 樹全展開且沒有任何節點被選取。
  • Given 在 View / Floorplans sidemenu 展開一個沒有子項的容器節點,Then 顯示一列 disabled 的空提示行,文字由使用端依 kind 提供。
  • Given 節點名稱長度超過可用寬度(任一場域),Then 以 ellipsis 截斷,且 hover 名稱區域顯示完整名稱(規則見 Section 01)。
  • Given 節點名稱完整顯示得下,Then hover 不顯示 tooltip。