樹狀檢視 (Tree View)

  • 新提案
  • 封閉測試
  • 公開測試
  • 已穩定
成熟度說明
  • 新提案:未完成開發、請勿使用。
  • 封閉測試:開發暫時性完成,可使用。可能仍有親和力或其他使用上問題待透過實測發現。
  • 公開測試:開發暫時性完成,歡迎使用。具有完整親和力報告。
  • 已穩定:開發完成、歡迎使用。應無任何親和力或使用上問題。

說明

樹狀檢視用於呈現具有階層關係的資料結構,例如檔案目錄、組織架構等。

基本範例

  • 以原生 <ul> / <li> 為語意基礎,再以 ARIA 屬性補足樹狀結構語意
  • 支援完整鍵盤操作
  • 採用 Roving tabindex 焦點管理:整個樹狀檢視只佔一個 Tab 停靠點
  • 採購招標作業程序
    • 共同投標
    • 緊急採購
  • 自我檢核表
  • 招決標方式評估
HTML
<ul
  role="tree"
  class="tree-view"
>
  <li
    role="treeitem"
    aria-expanded="true"
    aria-level="1"
    aria-selected="false"
    aria-labelledby="tvb-src"
    tabindex="0"
  >
    <span class="tree-view__label" id="tvb-src">採購招標作業程序</span>
    <ul role="group">
      <li
        role="treeitem"
        aria-expanded="false"
        aria-level="2"
        aria-selected="false"
        aria-labelledby="tvb-js"
        tabindex="-1"
      >
        <span class="tree-view__label" id="tvb-js">採購作業</span>
        <ul role="group">
          <li
            role="treeitem"
            aria-level="3"
            aria-selected="false"
            aria-labelledby="tvb-button"
            tabindex="-1"
          >
            <span class="tree-view__label" id="tvb-button">公告金額以上</span>
          </li>
          <li
            role="treeitem"
            aria-level="3"
            aria-selected="false"
            aria-labelledby="tvb-input"
            tabindex="-1"
          >
            <span class="tree-view__label" id="tvb-input">未達公告金額採購</span>
          </li>
        </ul>
      </li>
      <li
        role="treeitem"
        aria-level="2"
        aria-selected="true"
        aria-current="true"
        aria-labelledby="tvb-index"
        tabindex="-1"
      >
        <span class="tree-view__label" id="tvb-index">共同投標</span>
      </li>
      <li
        role="treeitem"
        aria-level="2"
        aria-selected="false"
        aria-labelledby="tvb-style"
        tabindex="-1"
      >
        <span class="tree-view__label" id="tvb-style">緊急採購</span>
      </li>
    </ul>
  </li>
  <li
    role="treeitem"
    aria-expanded="false"
    aria-level="1"
    aria-selected="false"
    aria-labelledby="tvb-tests"
    tabindex="-1"
  >
    <span class="tree-view__label" id="tvb-tests">使用須知</span>
    <ul role="group">
      <li
        role="treeitem"
        aria-level="2"
        aria-selected="false"
        aria-labelledby="tvb-index-test"
        tabindex="-1"
      >
        <span class="tree-view__label" id="tvb-index-test">採購標準作業程序</span>
      </li>
    </ul>
  </li>
  <li
    role="treeitem"
    aria-level="1"
    aria-selected="false"
    aria-labelledby="tvb-readme"
    tabindex="-1"
  >
    <span class="tree-view__label" id="tvb-readme">自我檢核表</span>
  </li>
  <li
    role="treeitem"
    aria-level="1"
    aria-selected="false"
    aria-labelledby="tvb-package"
    tabindex="-1"
  >
    <span class="tree-view__label" id="tvb-package">招決標方式評估</span>
  </li>
</ul>

ARIA 屬性

屬性套用於說明
role="tree"最外層 <ul>標示此為樹狀檢視元件
role="group"巢狀 <ul>標示子節點群組
role="treeitem"<li>標示每個節點
aria-expanded分支節點 <li>true 已展開 / false 已收合;葉節點加此屬性
aria-selected<li>是否為·目前選取的節點
aria-level每個 <li>明確宣告層級,修正部分報讀器無法自動計算層級的問題
aria-labelledby<li>指向內部文字的 id,解決 VoiceOver 對 <li> 內部複雜結構的相容性問題
aria-current="true"<li>深連結(deep link)到此節點時使用
tabindex<li>Roving tabindex:僅目前焦點節點為 0,其餘為 -1

JavaScript

  • 使用 tree-view.js
  • JavaScript 選擇器為 [role="tree"].tree-view,同時具備 class 與 role 才會初始化。

鍵盤操作

按鍵說明
/ 移動焦點至下一個 / 上一個可見節點
若為已收合的分支節點則展開;若為已展開的分支節點則移至第一個子節點
若為已展開的分支節點則收合;若為葉節點或已收合節點則移至父節點
Home / End移至第一個 / 最後一個可見節點
Enter / Space選取節點;若為分支節點則同時切換展開 / 收合

親和力

  • 以原生 <ul> / <li> 作為語意基礎
  • 整個元件包在一個 Tab 停靠點中,避免大型樹狀結構造成過多 Tab 停留
  • aria-level 明確宣告層級,不依賴瀏覽器自動推算
  • aria-labelledby 指向節點文字元素,確保 VoiceOver on macOS / iOS 能正確朗讀名稱
  • 鍵盤焦點有清楚的外框指示
  • 不依賴色彩傳達選取狀態

參考資料