深入指南
Angular Aria

工具列

概觀

工具列是將相關控制項與動作分組在一起的容器,並支援鍵盤導覽,常用於文字格式化、工具列與命令面板。

使用方式

當需要將使用者經常存取的相關控制項分組時,工具列最能發揮效果。符合下列情況時,可以考慮使用工具列:

  • 多個相關動作:你有數個執行相關功能的控制項(例如文字格式化按鈕)
  • 鍵盤效率很重要:使用者能受惠於以方向鍵快速進行鍵盤導覽
  • 控制項需要分組:你需要用分隔線將控制項組織成邏輯區段
  • 頻繁存取:控制項在工作流程中會被反覆使用

下列情況應避免使用工具列:

  • 簡單的按鈕群組就足夠:若只有 2 至 3 個不相關的動作,個別按鈕的效果更好
  • 控制項彼此不相關:工具列隱含邏輯上的分組,不相關的控制項會讓使用者困惑
  • 複雜的巢狀導覽:深層階層更適合用選單或導覽元件

功能特色

Angular 的工具列提供完整無障礙的工具列實作,包含:

  • 鍵盤導覽:使用 roving tabindex,透過方向鍵、Home 與 End 在控制項之間導覽,同時控制項保留原生的啟用行為
  • 螢幕閱讀器支援:內建 ARIA 屬性,支援輔助技術
  • 控制項群組:將相關控制項組織在一起,例如單選按鈕群組或切換按鈕群組
  • 彈性的方向:水平或垂直版面,鍵盤導覽會自動配合
  • 以訊號為基礎的反應式狀態:使用 Angular 訊號管理反應式狀態
  • 雙向文字支援:自動處理由右至左(RTL)的語言
  • 可設定的焦點行為:可選擇導覽循環繞回,或在邊緣硬性停止

範例

基本水平工具列

水平工具列將控制項由左至右排列,符合文字編輯器與設計工具的常見模式。方向鍵可在控制項之間導覽,焦點會停留在工具列內,直到使用者按下 Tab 移到下一個頁面元素。

垂直工具列

垂直工具列將控制項由上至下堆疊,適合用於側邊面板或垂直命令面板。上下方向鍵可在控制項之間導覽。

控制項群組

控制項群組將協同運作的相關控制項組織在一起,例如文字對齊選項或格式化切換。群組會維持 roving tabindex 導覽,同時向輔助技術呈現適當的語意結構。

在上面的範例中,對齊按鈕被包在 ngToolbarWidgetGroup 中,並設定 role="radiogroup"。選取狀態與工具列容器彼此獨立,讓你可以使用 Angular 訊號或自訂指令來管理狀態:

<!-- Mutually exclusive radio group -->
<div ngToolbarWidgetGroup role="radiogroup" aria-label="Alignment">
  <button
    ngToolbarWidget
    role="radio"
    type="button"
    [attr.aria-checked]="alignment() === 'left'"
    (click)="alignment.set('left')"
  >
    Left
  </button>
  <button
    ngToolbarWidget
    role="radio"
    type="button"
    [attr.aria-checked]="alignment() === 'center'"
    (click)="alignment.set('center')"
  >
    Center
  </button>
  <button
    ngToolbarWidget
    role="radio"
    type="button"
    [attr.aria-checked]="alignment() === 'right'"
    (click)="alignment.set('right')"
  >
    Right
  </button>
</div>

<!-- Toggle button group -->
<div class="group" role="group" aria-label="Text styling">
  <button ngToolbarWidget type="button" [attr.aria-pressed]="bold()" (click)="bold.set(!bold())">
    Bold
  </button>
  <button
    ngToolbarWidget
    type="button"
    [attr.aria-pressed]="italic()"
    (click)="italic.set(!italic())"
  >
    Italic
  </button>
</div>

停用的控制項

工具列支援兩種停用模式:

  1. 軟停用的控制項仍可取得焦點,但會以視覺方式表明無法使用
  2. 硬停用的控制項會完全從鍵盤導覽中移除。

softDisabled 預設為 true,讓停用的控制項仍能接收焦點。若要啟用硬停用模式,請在工具列上設定 [softDisabled]="false"。

由右至左(RTL)支援

工具列會自動支援由右至左的語言。將工具列包在設定了 dir="rtl" 的容器中,即可反轉版面與鍵盤導覽方向。方向鍵導覽會自動調整:左方向鍵移到下一個控制項,右方向鍵移到上一個。

測試

Angular Aria 提供元件測試工具(component harness)來測試工具列元件。以下是在元件測試中使用這些測試工具的範例:

import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {ToolbarHarness} from '@angular/aria/toolbar/testing';
import {MyToolbarComponent} from './my-toolbar'; // Your component

describe('MyToolbarComponent', () => {
  let fixture: ComponentFixture<MyToolbarComponent>;
  let loader: HarnessLoader;

  beforeEach(async () => {
    TestBed.configureTestingModule({
      imports: [MyToolbarComponent],
    });

    fixture = TestBed.createComponent(MyToolbarComponent);
    await fixture.whenStable();
    loader = TestbedHarnessEnvironment.loader(fixture);
  });

  it('should have widgets and update toggle state on click', async () => {
    // Load the toolbar harness
    const toolbar = await loader.getHarness(ToolbarHarness);

    // Get all widgets
    const widgets = await toolbar.getWidgets();
    expect(widgets.length).toBe(3);

    // Click the first widget
    await widgets[0].click();

    // Verify pressed state updated via click handler
    expect(await widgets[0].isSelected()).toBe(true);
  });
});

API 參考

如需詳細的 API 文件,請查看下列 API 參考: