آنلاین

Toolbar

Overview

Containerای برای گروه‌بندی controlها و actionهای مرتبط همراه با keyboard navigation، که معمولاً برای text formatting، toolbarها و command panelها استفاده می‌شود.

ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  background-color: var(--septenary-contrast);
}

.group {
  gap: 0.5rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 1.25rem;
  background-color: transparent;
  color: var(--primary-contrast);
}

[ngToolbarWidget]:hover {
  background-color: color-mix(in srgb, var(--primary-contrast) 10%, transparent);
}

[ngToolbarWidget]:active {
  background-color: color-mix(in srgb, var(--primary-contrast) 15%, transparent);
}

[ngToolbarWidget]:focus {
  outline-offset: -1px;
  outline: 1px solid color-mix(in srgb, var(--hot-pink) 60%, transparent);
}

[ngToolbarWidget][aria-pressed="true"],
[ngToolbarWidget][aria-checked="true"] {
  color: color-mix(in srgb, var(--hot-pink) 80%, var(--primary-contrast));
  background-color: color-mix(in srgb, var(--hot-pink) 10%, transparent);
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar class="material-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  display: flex;
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  font-size: 1.25rem;
  border-radius: 2rem;
  color: color-mix(in srgb, var(--vivid-pink) 70%, var(--full-contrast));
  background-color: color-mix(in srgb, var(--vivid-pink) 20%, transparent);
  transition:
    width 0.2s ease-in-out,
    background-color 0.15s ease-in-out,
    color 0.15s ease-in-out;
}

[ngToolbarWidget]:focus {
  outline-offset: 2px;
  outline: 2px solid var(--vivid-pink);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  background-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--full-contrast));
  color: var(--page-background);
}

[ngToolbarWidget][aria-checked='true'] {
  width: 4.5rem;
}

.group {
  display: flex;
  gap: 0.5rem;
}

.separator {
  width: 1px;
  margin: 0 1rem;
  height: calc(100% - 2rem);
  background-color: var(--quinary-contrast);
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar class="retro-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;

  font-family: 'Press Start 2P';
  --retro-button-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--page-background));
  --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
  --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
  --retro-elevated-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast);
  --retro-flat-shadow:
    4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
    -4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
  --retro-clickable-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
  --retro-pressed-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-dark),
    inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 1rem;
}

.group {
  gap: 1rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  padding: 0.5rem;
  font-size: 1.25rem;
  color: var(--page-background);

  background-color: var(--retro-button-color);
  box-shadow: var(--retro-clickable-shadow);
  transition:
    transform 0.1s,
    box-shadow 0.1s;
}

[ngToolbarWidget]:focus,
[ngToolbarWidget]:hover {
  transform: translate(1px, 1px);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  transform: translate(4px, 4px);
  box-shadow: var(--retro-pressed-shadow);
  background-color: color-mix(in srgb, var(--retro-button-color) 60%, var(--gray-50));
}

[ngToolbarWidget]:focus {
  outline-offset: 4px;
  outline: 4px dashed var(--retro-button-color);
}

Usage

Toolbar برای گروه‌بندی controlهای مرتبطی مناسب است که کاربران زیاد به آن‌ها دسترسی دارند. استفاده از toolbar را در این موارد در نظر بگیرید:

  • چند action مرتبط - چند control دارید که functionهای مرتبط انجام می‌دهند، مثل buttonهای text formatting.
  • Keyboard efficiency مهم است - کاربران از keyboard navigation سریع با arrow keyها سود می‌برند.
  • Grouped controls - باید controlها را با separator در sectionهای منطقی سازماندهی کنید.
  • دسترسی پرتکرار - controlها در یک workflow بارها استفاده می‌شوند.

از toolbar پرهیز کنید وقتی:

  • یک button group ساده کافی است - برای فقط 2-3 action نامرتبط، buttonهای جداگانه بهتر کار می‌کنند.
  • controlها مرتبط نیستند - toolbar به یک گروه‌بندی منطقی اشاره می‌کند؛ controlهای نامرتبط کاربران را گیج می‌کنند.
  • navigation پیچیده nested دارید - hierarchyهای عمیق با menuها یا navigation componentها بهتر پشتیبانی می‌شوند.

قابلیت‌ها

Toolbar در Angular یک implementation کامل و accessible برای toolbar فراهم می‌کند با:

  • Keyboard Navigation - با arrow keyها بین widgetها navigate کنید و با Enter یا Space activate کنید.
  • Screen Reader Support - attributeهای ARIA داخلی برای assistive technologyها.
  • Widget Groups - widgetهای مرتبط مثل radio button groupها یا toggle button groupها را سازماندهی کنید.
  • Flexible Orientation - layoutهای افقی یا عمودی با keyboard navigation خودکار.
  • Signal-Based Reactivity - مدیریت state reactive با Angular signals.
  • Bidirectional Text Support - مدیریت خودکار زبان‌های راست‌به‌چپ \(RTL\).
  • Configurable Focus - بین wrapping navigation یا hard stop در edgeها انتخاب کنید.

مثال‌ها

Basic horizontal toolbar

Toolbarهای افقی controlها را از چپ به راست سازماندهی می‌کنند و با pattern رایج در text editorها و design toolها match هستند. arrow keyها بین widgetها navigate می‌کنند و focus را داخل toolbar نگه می‌دارند تا زمانی که کاربران Tab را فشار دهند و به element بعدی صفحه بروند.

ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  background-color: var(--septenary-contrast);
}

.group {
  gap: 0.5rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 1.25rem;
  background-color: transparent;
  color: var(--primary-contrast);
}

[ngToolbarWidget]:hover {
  background-color: color-mix(in srgb, var(--primary-contrast) 10%, transparent);
}

[ngToolbarWidget]:active {
  background-color: color-mix(in srgb, var(--primary-contrast) 15%, transparent);
}

[ngToolbarWidget]:focus {
  outline-offset: -1px;
  outline: 1px solid color-mix(in srgb, var(--hot-pink) 60%, transparent);
}

[ngToolbarWidget][aria-pressed="true"],
[ngToolbarWidget][aria-checked="true"] {
  color: color-mix(in srgb, var(--hot-pink) 80%, var(--primary-contrast));
  background-color: color-mix(in srgb, var(--hot-pink) 10%, transparent);
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar class="material-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  display: flex;
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  font-size: 1.25rem;
  border-radius: 2rem;
  color: color-mix(in srgb, var(--vivid-pink) 70%, var(--full-contrast));
  background-color: color-mix(in srgb, var(--vivid-pink) 20%, transparent);
  transition:
    width 0.2s ease-in-out,
    background-color 0.15s ease-in-out,
    color 0.15s ease-in-out;
}

[ngToolbarWidget]:focus {
  outline-offset: 2px;
  outline: 2px solid var(--vivid-pink);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  background-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--full-contrast));
  color: var(--page-background);
}

[ngToolbarWidget][aria-checked='true'] {
  width: 4.5rem;
}

.group {
  display: flex;
  gap: 0.5rem;
}

.separator {
  width: 1px;
  margin: 0 1rem;
  height: calc(100% - 2rem);
  background-color: var(--quinary-contrast);
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar class="retro-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;

  font-family: 'Press Start 2P';
  --retro-button-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--page-background));
  --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
  --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
  --retro-elevated-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast);
  --retro-flat-shadow:
    4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
    -4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
  --retro-clickable-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
  --retro-pressed-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-dark),
    inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 1rem;
}

.group {
  gap: 1rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  padding: 0.5rem;
  font-size: 1.25rem;
  color: var(--page-background);

  background-color: var(--retro-button-color);
  box-shadow: var(--retro-clickable-shadow);
  transition:
    transform 0.1s,
    box-shadow 0.1s;
}

[ngToolbarWidget]:focus,
[ngToolbarWidget]:hover {
  transform: translate(1px, 1px);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  transform: translate(4px, 4px);
  box-shadow: var(--retro-pressed-shadow);
  background-color: color-mix(in srgb, var(--retro-button-color) 60%, var(--gray-50));
}

[ngToolbarWidget]:focus {
  outline-offset: 4px;
  outline: 4px dashed var(--retro-button-color);
}

Vertical toolbar

Toolbarهای عمودی controlها را از بالا به پایین stack می‌کنند و برای side panelها یا command paletteهای عمودی مفیدند. arrow keyهای بالا و پایین بین widgetها navigate می‌کنند.

ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget],
})
export class App {}
html
<div ngToolbar orientation="vertical" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: flex-start;
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  flex-direction: column;
  padding: 1rem 0.5rem;
  border-radius: 0.5rem;
  background-color: var(--septenary-contrast);
}

.group {
  gap: 0.5rem;
  display: flex;
  flex-direction: column;
}

.separator {
  height: 1px;
  align-self: center;
  width: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 1.25rem;
  background-color: transparent;
  color: var(--primary-contrast);
}

[ngToolbarWidget]:hover {
  background-color: color-mix(in srgb, var(--primary-contrast) 10%, transparent);
}

[ngToolbarWidget]:active {
  background-color: color-mix(in srgb, var(--primary-contrast) 15%, transparent);
}

[ngToolbarWidget]:focus {
  outline-offset: -1px;
  outline: 1px solid color-mix(in srgb, var(--hot-pink) 60%, transparent);
}

[ngToolbarWidget][aria-pressed="true"],
[ngToolbarWidget][aria-checked="true"] {
  color: color-mix(in srgb, var(--hot-pink) 80%, var(--primary-contrast));
  background-color: color-mix(in srgb, var(--hot-pink) 10%, transparent);
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget],
})
export class App {}
html
<div
  ngToolbar
  orientation="vertical"
  class="vertical-material-toolbar"
  aria-label="Text Formatting Tools"
>
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: flex-start;
}

[ngToolbar] {
  display: flex;
  flex-direction: column;
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  font-size: 1.25rem;
  border-radius: 2rem;
  color: color-mix(in srgb, var(--vivid-pink) 70%, var(--full-contrast));
  background-color: color-mix(in srgb, var(--vivid-pink) 20%, transparent);
  transition:
    height 0.2s ease-in-out,
    background-color 0.15s ease-in-out,
    color 0.15s ease-in-out;
}

[ngToolbarWidget]:focus {
  outline-offset: 2px;
  outline: 2px solid var(--vivid-pink);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  background-color: var(--vivid-pink);
  color: var(--page-background);
}

[ngToolbarWidget][aria-checked='true'] {
  height: 4.5rem;
}

.group {
  gap: 0.5rem;
  display: flex;
  flex-direction: column;
}

.separator {
  width: 1px;
  margin: 1rem 0;
  height: calc(100% - 2rem);
  background-color: var(--quinary-contrast);
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget],
})
export class App {}
html
<div ngToolbar orientation="vertical" class="retro-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: flex-start;

  font-family: 'Press Start 2P';
  --retro-button-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--page-background));
  --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
  --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
  --retro-elevated-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast);
  --retro-flat-shadow:
    4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
    -4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
  --retro-clickable-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
  --retro-pressed-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-dark),
    inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 1rem;
  flex-direction: column;
}

.group {
  gap: 1rem;
  display: flex;
  flex-direction: column;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  padding: 0.5rem;
  font-size: 1.25rem;
  color: var(--page-background);

  background-color: var(--retro-button-color);
  box-shadow: var(--retro-clickable-shadow);
  transition:
    transform 0.1s,
    box-shadow 0.1s;
}

[ngToolbarWidget]:focus,
[ngToolbarWidget]:hover {
  transform: translate(1px, 1px);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  transform: translate(4px, 4px);
  box-shadow: var(--retro-pressed-shadow);
  background-color: color-mix(in srgb, var(--retro-button-color) 60%, var(--gray-50));
}

[ngToolbarWidget]:focus {
  outline-offset: 4px;
  outline: 4px dashed var(--retro-button-color);
}

Widget groupها

Widget groupها controlهای مرتبطی را در بر می‌گیرند که با هم کار می‌کنند، مثل optionهای text alignment یا choiceهای list formatting. Groupها state داخلی خودشان را نگه می‌دارند و در toolbar navigation هم شرکت می‌کنند.

در مثال‌های بالا، buttonهای alignment داخل ngToolbarWidgetGroup با role="radiogroup" wrap شده‌اند تا یک mutually exclusive selection group ایجاد شود.

input مربوط به multi کنترل می‌کند که چند widget داخل یک group بتوانند هم‌زمان selected شوند یا نه:

html
<!-- Single selection (radio group) -->
<div ngToolbarWidgetGroup role="radiogroup" aria-label="Alignment">
  <button ngToolbarWidget value="left">Left</button>
  <button ngToolbarWidget value="center">Center</button>
  <button ngToolbarWidget value="right">Right</button>
</div>

<!-- Multiple selection (toggle group) -->
<div ngToolbarWidgetGroup [multi]="true" aria-label="Formatting">
  <button ngToolbarWidget value="bold">Bold</button>
  <button ngToolbarWidget value="italic">Italic</button>
  <button ngToolbarWidget value="underline">Underline</button>
</div>

Widgetهای disabled

Toolbarها دو mode مربوط به disabled را پشتیبانی می‌کنند:

  1. Soft-disabled widgetها focusable می‌مانند اما از نظر visual نشان می‌دهند که unavailable هستند.
  2. Hard-disabled widgetها کامل از keyboard navigation حذف می‌شوند.

به صورت پیش‌فرض، softDisabled برابر true است و اجازه می‌دهد widgetهای disabled همچنان focus دریافت کنند. اگر می‌خواهید hard-disabled mode را فعال کنید، [softDisabled]="false" را روی toolbar تنظیم کنید.

ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      disabled
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div
    ngToolbarWidgetGroup
    role="radiogroup"
    class="group"
    aria-label="Text alignment options"
    disabled
  >
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  background-color: var(--septenary-contrast);
}

.group {
  gap: 0.5rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 1.25rem;
  background-color: transparent;
  color: var(--primary-contrast);
}

[ngToolbarWidget]:hover {
  background-color: color-mix(in srgb, var(--primary-contrast) 10%, transparent);
}

[ngToolbarWidget]:active {
  background-color: color-mix(in srgb, var(--primary-contrast) 15%, transparent);
}

[ngToolbarWidget]:focus {
  outline-offset: -1px;
  outline: 1px solid color-mix(in srgb, var(--hot-pink) 60%, transparent);
}

[ngToolbarWidget][aria-pressed="true"],
[ngToolbarWidget][aria-checked="true"] {
  color: color-mix(in srgb, var(--hot-pink) 80%, var(--primary-contrast));
  background-color: color-mix(in srgb, var(--hot-pink) 10%, transparent);
}

[ngToolbarWidget][aria-disabled="true"] {
  cursor: default;
  opacity: 0.45;
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar class="disabled-material-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      disabled
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div
    ngToolbarWidgetGroup
    role="radiogroup"
    class="group"
    aria-label="Text alignment options"
    disabled
  >
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  display: flex;
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  font-size: 1.25rem;
  border-radius: 2rem;
  color: color-mix(in srgb, var(--vivid-pink) 70%, var(--full-contrast));
  background-color: color-mix(in srgb, var(--vivid-pink) 20%, transparent);
  transition:
    width 0.2s ease-in-out,
    background-color 0.15s ease-in-out,
    color 0.15s ease-in-out;
}

[ngToolbarWidget]:focus {
  outline-offset: 2px;
  outline: 2px solid var(--vivid-pink);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  background-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--full-contrast));
  color: var(--page-background);
}

[ngToolbarWidget][aria-checked='true'] {
  width: 4.5rem;
}

.group {
  display: flex;
  gap: 0.5rem;
}

.separator {
  width: 1px;
  margin: 0 1rem;
  height: calc(100% - 2rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget][aria-disabled="true"] {
  cursor: default;
  opacity: 0.45;
}
ts
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar class="retro-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      disabled
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div
    ngToolbarWidgetGroup
    role="radiogroup"
    class="group"
    aria-label="Text alignment options"
    disabled
  >
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;

  font-family: 'Press Start 2P';
  --retro-button-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--page-background));
  --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
  --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
  --retro-elevated-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast);
  --retro-flat-shadow:
    4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
    -4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
  --retro-clickable-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
  --retro-pressed-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-dark),
    inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 1rem;
}

.group {
  gap: 1rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  padding: 0.5rem;
  font-size: 1.25rem;
  color: var(--page-background);

  background-color: var(--retro-button-color);
  box-shadow: var(--retro-clickable-shadow);
  transition:
    transform 0.1s,
    box-shadow 0.1s;
}

[ngToolbarWidget]:focus,
[ngToolbarWidget]:hover {
  transform: translate(1px, 1px);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  transform: translate(4px, 4px);
  box-shadow: var(--retro-pressed-shadow);
  background-color: color-mix(in srgb, var(--retro-button-color) 60%, var(--gray-50));
}

[ngToolbarWidget]:focus {
  outline-offset: 4px;
  outline: 4px dashed var(--retro-button-color);
}

[ngToolbarWidget][aria-disabled='true'] {
  cursor: default;
  opacity: 0.45;
}

پشتیبانی از راست‌به‌چپ \(RTL\)

Toolbarها به صورت خودکار از زبان‌های راست‌به‌چپ پشتیبانی می‌کنند. toolbar را داخل containerای با dir="rtl" wrap کنید تا layout و جهت keyboard navigation معکوس شود. navigation با arrow keyها خودکار تنظیم می‌شود: arrow چپ به widget بعدی می‌رود و arrow راست به قبلی.

ts
import {Dir} from '@angular/cdk/bidi';
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Dir, Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar dir="rtl" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  background-color: var(--septenary-contrast);
}

.group {
  gap: 0.5rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 1.25rem;
  background-color: transparent;
  color: var(--primary-contrast);
}

[ngToolbarWidget]:hover {
  background-color: color-mix(in srgb, var(--primary-contrast) 10%, transparent);
}

[ngToolbarWidget]:active {
  background-color: color-mix(in srgb, var(--primary-contrast) 15%, transparent);
}

[ngToolbarWidget]:focus {
  outline-offset: -1px;
  outline: 1px solid color-mix(in srgb, var(--hot-pink) 60%, transparent);
}

[ngToolbarWidget][aria-pressed="true"],
[ngToolbarWidget][aria-checked="true"] {
  color: color-mix(in srgb, var(--hot-pink) 80%, var(--primary-contrast));
  background-color: color-mix(in srgb, var(--hot-pink) 10%, transparent);
}
ts
import {Dir} from '@angular/cdk/bidi';
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Dir, Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar dir="rtl" class="rtl-material-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;
}

[ngToolbar] {
  display: flex;
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  font-size: 1.25rem;
  border-radius: 2rem;
  color: color-mix(in srgb, var(--vivid-pink) 70%, var(--full-contrast));
  background-color: color-mix(in srgb, var(--vivid-pink) 20%, transparent);
  transition:
    width 0.2s ease-in-out,
    background-color 0.15s ease-in-out,
    color 0.15s ease-in-out;
}

[ngToolbarWidget]:focus {
  outline-offset: 2px;
  outline: 2px solid var(--vivid-pink);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  background-color: var(--vivid-pink);
  color: var(--page-background);
}

[ngToolbarWidget][aria-checked='true'] {
  width: 4.5rem;
}

.group {
  display: flex;
  gap: 0.5rem;
}

.separator {
  width: 1px;
  margin: 0 1rem;
  height: calc(100% - 2rem);
  background-color: var(--quinary-contrast);
}
ts
import {Dir} from '@angular/cdk/bidi';
import {Component} from '@angular/core';
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';

@Component({
  selector: 'app-root',
  templateUrl: 'app.html',
  styleUrl: 'app.css',
  imports: [Dir, Toolbar, ToolbarWidget, ToolbarWidgetGroup],
})
export class App {}
html
<div ngToolbar dir="rtl" class="rtl-retro-toolbar" aria-label="Text Formatting Tools">
  <div class="group">
    <button
      ngToolbarWidget
      value="undo"
      type="button"
      aria-label="undo"
      class="material-symbols-outlined"
      translate="no"
    >
      undo
    </button>

    <button
      ngToolbarWidget
      value="redo"
      type="button"
      aria-label="redo"
      class="material-symbols-outlined"
      translate="no"
    >
      redo
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div class="group">
    <button
      ngToolbarWidget
      value="bold"
      type="button"
      aria-label="bold"
      #bold="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="bold.selected()"
      translate="no"
    >
      format_bold
    </button>

    <button
      ngToolbarWidget
      value="italic"
      type="button"
      aria-label="italic"
      #italic="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="italic.selected()"
      translate="no"
    >
      format_italic
    </button>

    <button
      ngToolbarWidget
      value="underlined"
      type="button"
      aria-label="underlined"
      #underlined="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-pressed]="underlined.selected()"
      translate="no"
    >
      format_underlined
    </button>
  </div>

  <div class="separator" role="separator"></div>

  <div ngToolbarWidgetGroup role="radiogroup" class="group" aria-label="Text alignment options">
    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align left"
      aria-label="align left"
      #leftAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="leftAlign.selected()"
      translate="no"
    >
      format_align_left
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align center"
      aria-label="align center"
      #centerAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="centerAlign.selected()"
      translate="no"
    >
      format_align_center
    </button>

    <button
      ngToolbarWidget
      role="radio"
      type="button"
      value="align right"
      aria-label="align right"
      #rightAlign="ngToolbarWidget"
      class="material-symbols-outlined"
      [aria-checked]="rightAlign.selected()"
      translate="no"
    >
      format_align_right
    </button>
  </div>
</div>
css
@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined');

:host {
  display: flex;
  justify-content: center;

  font-family: 'Press Start 2P';
  --retro-button-color: color-mix(in srgb, var(--vivid-pink) 80%, var(--page-background));
  --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff);
  --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000);
  --retro-elevated-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast);
  --retro-flat-shadow:
    4px 0px 0px 0px var(--tertiary-contrast), 0px 4px 0px 0px var(--tertiary-contrast),
    -4px 0px 0px 0px var(--tertiary-contrast), 0px -4px 0px 0px var(--tertiary-contrast);
  --retro-clickable-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-light),
    inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 8px 8px 0px 0px var(--tertiary-contrast);
  --retro-pressed-shadow:
    inset 4px 4px 0px 0px var(--retro-shadow-dark),
    inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--tertiary-contrast),
    0px 4px 0px 0px var(--tertiary-contrast), -4px 0px 0px 0px var(--tertiary-contrast),
    0px -4px 0px 0px var(--tertiary-contrast), 0px 0px 0px 0px var(--tertiary-contrast);
}

[ngToolbar] {
  gap: 1.5rem;
  display: flex;
  padding: 1rem;
}

.group {
  gap: 1rem;
  display: flex;
}

.separator {
  width: 1px;
  align-self: center;
  height: calc(100% - 1rem);
  background-color: var(--quinary-contrast);
}

[ngToolbarWidget] {
  border: none;
  outline: none;
  cursor: pointer;
  padding: 0.5rem;
  font-size: 1.25rem;
  color: var(--page-background);

  background-color: var(--retro-button-color);
  box-shadow: var(--retro-clickable-shadow);
  transition:
    transform 0.1s,
    box-shadow 0.1s;
}

[ngToolbarWidget]:focus,
[ngToolbarWidget]:hover {
  transform: translate(1px, 1px);
}

[ngToolbarWidget]:active,
[ngToolbarWidget][aria-pressed='true'],
[ngToolbarWidget][aria-checked='true'] {
  transform: translate(4px, 4px);
  box-shadow: var(--retro-pressed-shadow);
  background-color: color-mix(in srgb, var(--retro-button-color) 60%, var(--gray-50));
}

[ngToolbarWidget]:focus {
  outline-offset: 4px;
  outline: 4px dashed var(--retro-button-color);
}

Testing

Angular Aria برای testing کامپوننت‌های toolbar، component harness ارائه می‌کند. این نمونه نحوه استفاده از harnessها را در یک component test نشان می‌دهد:

ts
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 allow selection', 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 selection state
    expect(await widgets[0].isSelected()).toBe(true);
  });
});

API reference

برای مستندات دقیق API، referenceهای API زیر را بررسی کنید: