command

Command palette layout

Build a searchable command menu with one ng-command root and semantic child elements identified by command part classes. AngularTS owns query filtering and command execution. Command follows the rendered result DOM and supplies listbox relationships, active-descendant navigation, disabled skipping, and scroll-to-active behavior.

<section ng-command variant="surface" aria-label="Command menu">
  <header>
    <label>
      <span aria-hidden="true"><!-- search icon --></span>
      <input
        aria-label="Search commands"
        ng-model="query"
        placeholder="Type a command or search..."
      />
    </label>
  </header>
  <div>
    <p>No results found.</p>
    <section>
      <h2>Suggestions</h2>
      <button
        type="button"
        ng-repeat="command in commands | filter:query"
        ng-click="selected=command.label"
      >
        <span ng-bind="command.label"></span>
        <kbd ng-bind="command.shortcut"></kbd>
      </button>
    </section>
  </div>
</section>

Use aria-disabled="true" or native disabled state for unavailable options. Arrow keys wrap through enabled rendered options; Home and End move to the boundaries; Enter activates the current option through its ordinary click handler. Pointer movement updates the same active state.

For a modal palette, place the ng-command root inside a native dialog within a .dialog wrapper. Use native invoker and close commands to open and close it. The browser handles modal focus, Escape, configured light dismissal, and focus restoration. Application shortcuts such as Ctrl J remain AngularTS ng-keydown expressions.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Command</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="commandState={query:'',selected:''}; suggestions=[{label:'Calendar',icon:'calendar',disabled:false},{label:'Search Emoji',icon:'smile',disabled:false},{label:'Calculator',icon:'calculator',disabled:true}]; settings=[{label:'Profile',shortcut:'⌘P',icon:'user'},{label:'Billing',shortcut:'⌘B',icon:'credit-card'},{label:'Settings',shortcut:'⌘S',icon:'settings'}]"
    data-example="command-demo"
  >
    <main class="visual-example">
      <section
        id="command-demo"
        ng-command
        variant="surface"
        aria-label="Command menu"
      >
        <header>
          <label>
            <span aria-hidden="true">
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              >
                <circle cx="11" cy="11" r="8"></circle>
                <path d="m21 21-4.3-4.3"></path>
              </svg>
            </span>
            <input
              aria-label="Search commands"
              placeholder="Type a command or search..."
              ng-model="commandState.query"
            />
          </label>
        </header>
        <div>
          <p>No results found.</p>
          <section>
            <h2>Suggestions</h2>
            <button
              type="button"
              ng-repeat="item in suggestions | filter:commandState.query"
              ng-attr-aria-disabled="{{ item.disabled }}"
              ng-click="commandState.selected=item.label"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
                aria-hidden="true"
              >
                <circle cx="12" cy="12" r="8"></circle>
                <path d="M8 12h8"></path>
              </svg>
              <span ng-bind="item.label"></span>
            </button>
          </section>
          <hr />
          <section>
            <h2>Settings</h2>
            <button
              type="button"
              ng-repeat="item in settings | filter:commandState.query"
              ng-click="commandState.selected=item.label"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
                aria-hidden="true"
              >
                <circle cx="12" cy="8" r="4"></circle>
                <path d="M4 21a8 8 0 0 1 16 0"></path>
              </svg>
              <span ng-bind="item.label"></span>
              <kbd ng-bind="item.shortcut"></kbd>
            </button>
          </section>
        </div>
      </section>
      <output class="visually-hidden" aria-live="polite">
        Selected:
        <span ng-bind="commandState.selected || 'None'"></span>
      </output>
    </main>
  </body>
</html>

Dialog Workflows

Basic, grouped, shortcut-label, and application-owned Ctrl J dialog references are functional packaged examples.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Command Dialog Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
    <script src="../../js/command-demo.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="basic={query:'',selected:''}; grouped={query:'',selected:''}; shortcuts={query:'',selected:''}; shortcutDialog={query:'',selected:''}; suggestions=['Calendar','Search Emoji','Calculator']; settings=[{label:'Profile',shortcut:'⌘P'},{label:'Billing',shortcut:'⌘B'},{label:'Settings',shortcut:'⌘S'}]"
    data-example="command-basic command-dialog command-groups command-shortcuts"
  >
    <main class="command-dialog-workflows visual-example">
      <section class="command-dialog-workflow">
        <button
          type="button"
          variant="outline"
          aria-controls="basic-command-dialog-content"
          commandfor="basic-command-dialog-content"
          command="show-modal"
        >
          Open Menu
        </button>
        <section id="basic-command-dialog" class="command-dialog-shell dialog">
          <dialog
            id="basic-command-dialog-content"
            closedby="any"
            aria-labelledby="basic-command-dialog-title"
            aria-describedby="basic-command-dialog-description"
          >
            <header class="visually-hidden">
              <h2 id="basic-command-dialog-title">Command Palette</h2>
              <p id="basic-command-dialog-description">
                Search for a command to run.
              </p>
            </header>
            <section ng-command aria-label="Basic command menu">
              <header>
                <label>
                  <span aria-hidden="true">
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                    >
                      <circle cx="11" cy="11" r="8"></circle>
                      <path d="m21 21-4.3-4.3"></path>
                    </svg>
                  </span>
                  <input
                    aria-label="Search basic commands"
                    ng-model="basic.query"
                    placeholder="Type a command or search..."
                  />
                </label>
              </header>
              <div>
                <p>No results found.</p>
                <section>
                  <h3>Suggestions</h3>
                  <button
                    ng-repeat="item in suggestions | filter:basic.query"
                    type="button"
                    ng-click="basic.selected=item"
                    commandfor="basic-command-dialog-content"
                    command="close"
                  >
                    <span ng-bind="item"></span>
                  </button>
                </section>
              </div>
            </section>
          </dialog>
        </section>
        <output class="command-workflow-output" aria-live="polite">
          Basic: <span ng-bind="basic.selected || 'None'"></span>
        </output>
      </section>

      <section class="command-dialog-workflow">
        <button
          type="button"
          variant="outline"
          aria-controls="groups-command-dialog-content"
          commandfor="groups-command-dialog-content"
          command="show-modal"
        >
          Open Grouped Menu
        </button>
        <section id="groups-command-dialog" class="command-dialog-shell dialog">
          <dialog
            id="groups-command-dialog-content"
            closedby="any"
            aria-labelledby="groups-command-dialog-title"
            aria-describedby="groups-command-dialog-description"
          >
            <header class="visually-hidden">
              <h2 id="groups-command-dialog-title">Grouped Command Palette</h2>
              <p id="groups-command-dialog-description">
                Search grouped application commands.
              </p>
            </header>
            <section ng-command aria-label="Grouped command menu">
              <header>
                <label>
                  <span aria-hidden="true">
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                    >
                      <circle cx="11" cy="11" r="8"></circle>
                      <path d="m21 21-4.3-4.3"></path>
                    </svg>
                  </span>
                  <input
                    aria-label="Search grouped commands"
                    ng-model="grouped.query"
                    placeholder="Type a command or search..."
                  />
                </label>
              </header>
              <div>
                <p>No results found.</p>
                <section>
                  <h3>Suggestions</h3>
                  <button
                    ng-repeat="item in suggestions | filter:grouped.query"
                    type="button"
                    ng-click="grouped.selected=item"
                    commandfor="groups-command-dialog-content"
                    command="close"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <circle cx="12" cy="12" r="8"></circle>
                    </svg>
                    <span ng-bind="item"></span>
                  </button>
                </section>
                <hr />
                <section>
                  <h3>Settings</h3>
                  <button
                    ng-repeat="item in settings | filter:grouped.query"
                    type="button"
                    ng-click="grouped.selected=item.label"
                    commandfor="groups-command-dialog-content"
                    command="close"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <circle cx="12" cy="8" r="4"></circle>
                      <path d="M4 21a8 8 0 0 1 16 0"></path>
                    </svg>
                    <span ng-bind="item.label"></span>
                    <kbd ng-bind="item.shortcut"></kbd>
                  </button>
                </section>
              </div>
            </section>
          </dialog>
        </section>
        <output class="command-workflow-output" aria-live="polite">
          Grouped: <span ng-bind="grouped.selected || 'None'"></span>
        </output>
      </section>

      <section class="command-dialog-workflow">
        <button
          type="button"
          variant="outline"
          aria-controls="shortcuts-command-dialog-content"
          commandfor="shortcuts-command-dialog-content"
          command="show-modal"
        >
          Open Shortcuts
        </button>
        <section
          id="shortcuts-command-dialog"
          class="command-dialog-shell dialog"
        >
          <dialog
            id="shortcuts-command-dialog-content"
            closedby="any"
            aria-labelledby="shortcuts-command-dialog-title"
            aria-describedby="shortcuts-command-dialog-description"
          >
            <header class="visually-hidden">
              <h2 id="shortcuts-command-dialog-title">Command Shortcuts</h2>
              <p id="shortcuts-command-dialog-description">
                Search settings commands.
              </p>
            </header>
            <section ng-command aria-label="Shortcut command menu">
              <header>
                <label>
                  <span aria-hidden="true">
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                    >
                      <circle cx="11" cy="11" r="8"></circle>
                      <path d="m21 21-4.3-4.3"></path>
                    </svg>
                  </span>
                  <input
                    aria-label="Search shortcut commands"
                    ng-model="shortcuts.query"
                    placeholder="Type a command or search..."
                  />
                </label>
              </header>
              <div>
                <p>No results found.</p>
                <section>
                  <h3>Settings</h3>
                  <button
                    ng-repeat="item in settings | filter:shortcuts.query"
                    type="button"
                    ng-click="shortcuts.selected=item.label"
                    commandfor="shortcuts-command-dialog-content"
                    command="close"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <circle cx="12" cy="8" r="4"></circle>
                      <path d="M4 21a8 8 0 0 1 16 0"></path>
                    </svg>
                    <span ng-bind="item.label"></span>
                    <kbd ng-bind="item.shortcut"></kbd>
                  </button>
                </section>
              </div>
            </section>
          </dialog>
        </section>
        <output class="command-workflow-output" aria-live="polite">
          Shortcut: <span ng-bind="shortcuts.selected || 'None'"></span>
        </output>
      </section>

      <section class="command-dialog-workflow command-shortcut-workflow">
        <p>Press <kbd>Ctrl J</kbd></p>
        <section
          id="keyboard-command-dialog"
          class="command-dialog-shell dialog"
        >
          <dialog
            id="keyboard-command-dialog-content"
            closedby="any"
            aria-labelledby="keyboard-command-dialog-title"
            aria-describedby="keyboard-command-dialog-description"
          >
            <header class="visually-hidden">
              <h2 id="keyboard-command-dialog-title">
                Keyboard Command Palette
              </h2>
              <p id="keyboard-command-dialog-description">
                Search for a command to run.
              </p>
            </header>
            <section ng-command aria-label="Keyboard command menu">
              <header>
                <label>
                  <span aria-hidden="true">
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                    >
                      <circle cx="11" cy="11" r="8"></circle>
                      <path d="m21 21-4.3-4.3"></path>
                    </svg>
                  </span>
                  <input
                    aria-label="Search keyboard commands"
                    ng-model="shortcutDialog.query"
                    placeholder="Type a command or search..."
                  />
                </label>
              </header>
              <div>
                <p>No results found.</p>
                <section>
                  <h3>Suggestions</h3>
                  <button
                    ng-repeat="item in suggestions | filter:shortcutDialog.query"
                    type="button"
                    ng-click="shortcutDialog.selected=item"
                    commandfor="keyboard-command-dialog-content"
                    command="close"
                  >
                    <span ng-bind="item"></span>
                  </button>
                </section>
                <hr />
                <section>
                  <h3>Settings</h3>
                  <button
                    ng-repeat="item in settings | filter:shortcutDialog.query"
                    type="button"
                    ng-click="shortcutDialog.selected=item.label"
                    commandfor="keyboard-command-dialog-content"
                    command="close"
                  >
                    <span ng-bind="item.label"></span>
                    <kbd ng-bind="item.shortcut"></kbd>
                  </button>
                </section>
              </div>
            </section>
          </dialog>
        </section>
        <output class="command-workflow-output" aria-live="polite">
          Keyboard:
          <span ng-bind="shortcutDialog.selected || 'None'"></span>
        </output>
      </section>
    </main>
  </body>
</html>

Scrollable

The full 23-item reference inventory demonstrates the 288px list constraint, keyboard scroll-to-active behavior, filtering, and selection.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Command Scrollable</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="scroll={query:'',selected:''}; commandGroups=[{label:'Navigation',items:[{label:'Home',shortcut:'⌘H'},{label:'Inbox',shortcut:'⌘I'},{label:'Documents',shortcut:'⌘D'},{label:'Folders',shortcut:'⌘F'}]},{label:'Actions',items:[{label:'New File',shortcut:'⌘N'},{label:'New Folder',shortcut:'⇧⌘N'},{label:'Copy',shortcut:'⌘C'},{label:'Cut',shortcut:'⌘X'},{label:'Paste',shortcut:'⌘V'},{label:'Delete',shortcut:'⌫'}]},{label:'View',items:[{label:'Grid View',shortcut:''},{label:'List View',shortcut:''},{label:'Zoom In',shortcut:'⌘+'},{label:'Zoom Out',shortcut:'⌘-'}]},{label:'Account',items:[{label:'Profile',shortcut:'⌘P'},{label:'Billing',shortcut:'⌘B'},{label:'Settings',shortcut:'⌘S'},{label:'Notifications',shortcut:''},{label:'Help & Support',shortcut:''}]},{label:'Tools',items:[{label:'Calculator',shortcut:''},{label:'Calendar',shortcut:''},{label:'Image Editor',shortcut:''},{label:'Code Editor',shortcut:''}]}]"
    data-example="command-scrollable"
  >
    <main class="command-scrollable-demo visual-example">
      <button
        type="button"
        variant="outline"
        aria-controls="scrollable-command-dialog-content"
        commandfor="scrollable-command-dialog-content"
        command="show-modal"
      >
        Open Menu
      </button>
      <section
        id="scrollable-command-dialog"
        class="command-dialog-shell dialog"
      >
        <dialog
          id="scrollable-command-dialog-content"
          closedby="any"
          aria-labelledby="scrollable-command-dialog-title"
          aria-describedby="scrollable-command-dialog-description"
        >
          <header class="visually-hidden">
            <h2 id="scrollable-command-dialog-title">
              Scrollable Command Palette
            </h2>
            <p id="scrollable-command-dialog-description">
              Search all application commands.
            </p>
          </header>
          <section ng-command aria-label="Scrollable command menu">
            <header>
              <label>
                <span aria-hidden="true">
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                  >
                    <circle cx="11" cy="11" r="8"></circle>
                    <path d="m21 21-4.3-4.3"></path>
                  </svg>
                </span>
                <input
                  aria-label="Search all commands"
                  ng-model="scroll.query"
                  placeholder="Type a command or search..."
                />
              </label>
            </header>
            <div>
              <p>No results found.</p>
              <section ng-repeat="group in commandGroups">
                <h3 ng-bind="group.label"></h3>
                <button
                  ng-repeat="item in group.items | filter:scroll.query"
                  type="button"
                  ng-click="scroll.selected=item.label"
                  commandfor="scrollable-command-dialog-content"
                  command="close"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    aria-hidden="true"
                  >
                    <path d="M6 2h9l3 3v17H6z"></path>
                    <path d="M14 2v4h4"></path>
                  </svg>
                  <span ng-bind="item.label"></span>
                  <kbd ng-if="item.shortcut" ng-bind="item.shortcut"></kbd>
                </button>
                <hr />
              </section>
            </div>
          </section>
        </dialog>
      </section>
      <output class="command-workflow-output" aria-live="polite">
        Selected: <span ng-bind="scroll.selected || 'None'"></span>
      </output>
    </main>
  </body>
</html>

RTL

Logical icon, text, shortcut, active-item, and keyboard order are preserved in an Arabic command surface.

View source
<!doctype html>
<html lang="ar" dir="rtl">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Command Rtl</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="rtlCommand={query:'',selected:''}; rtlSuggestions=[{label:'التقويم',disabled:false},{label:'البحث عن الرموز التعبيرية',disabled:false},{label:'الآلة الحاسبة',disabled:true}]; rtlSettings=[{label:'الملف الشخصي',shortcut:'⌘P'},{label:'الفوترة',shortcut:'⌘B'},{label:'الإعدادات',shortcut:'⌘S'}]"
    data-example="command-rtl"
  >
    <main class="visual-example">
      <section
        id="rtl-command"
        ng-command
        variant="surface"
        aria-label="قائمة الأوامر"
      >
        <header>
          <label>
            <span aria-hidden="true">
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <circle cx="11" cy="11" r="8"></circle>
                <path d="m21 21-4.3-4.3"></path>
              </svg>
            </span>
            <input
              dir="rtl"
              aria-label="البحث في الأوامر"
              ng-model="rtlCommand.query"
              placeholder="اكتب أمرًا أو ابحث..."
            />
          </label>
        </header>
        <div>
          <p>لم يتم العثور على نتائج.</p>
          <section>
            <h2>اقتراحات</h2>
            <button
              type="button"
              ng-repeat="item in rtlSuggestions | filter:rtlCommand.query"
              ng-attr-aria-disabled="{{ item.disabled }}"
              ng-click="rtlCommand.selected=item.label"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <circle cx="12" cy="12" r="8"></circle>
              </svg>
              <span ng-bind="item.label"></span>
            </button>
          </section>
          <hr />
          <section>
            <h2>الإعدادات</h2>
            <button
              type="button"
              ng-repeat="item in rtlSettings | filter:rtlCommand.query"
              ng-click="rtlCommand.selected=item.label"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <circle cx="12" cy="8" r="4"></circle>
                <path d="M4 21a8 8 0 0 1 16 0"></path>
              </svg>
              <span ng-bind="item.label"></span>
              <kbd ng-bind="item.shortcut"></kbd>
            </button>
          </section>
        </div>
      </section>
      <output class="visually-hidden" aria-live="polite">
        المحدد: <span ng-bind="rtlCommand.selected || 'لا شيء'"></span>
      </output>
    </main>
  </body>
</html>

Installation

Install AngularCSS, load its stylesheet, and include the angular.css module in your AngularTS application. See Installation for the complete setup.

This component’s root directive is [ng-command]. Importing the package registers it with the AngularCSS angular.css module; there is no per-component JavaScript registration step.

Anatomy

Directive selectors

  • ng-command

Semantic structure

A command root requires one input and a result container. The root directive inspects semantic headers, sections, headings, buttons, separators, and keyboard hints; no child directives or anatomy classes are required. Compose modal palettes from Dialog.

API

Attributes and state

AttributeAccessPurpose
aria-activedescendantOutputID of the active option while focus remains on the composite control.
aria-autocompleteInput/outputHow a text control presents completion suggestions.
aria-controlsOutputID of the element controlled by a trigger.
aria-disabledInput/outputSemantic disabled state.
aria-expandedOutputOpen or expanded state exposed to assistive technology.
aria-hiddenInput/outputWhether generated or collapsed content is hidden from assistive technology.
aria-labelledbyOutputID of the element that supplies the accessible name.
aria-orientationOutputInteraction axis exposed to assistive technology.
aria-selectedInput/outputSelected item state.
dirInputText and interaction direction: ltr or rtl.
disabledInputDisables native or component interaction.
hiddenInputNative visibility state observed when finding available items.
roleOutputExplicit semantic role when native HTML does not provide one.
tabindexOutputKeyboard focus order for composite descendants.

Input attributes are read from authored HTML. Output attributes are maintained by AngularCSS for CSS and testing. Input/output attributes may be authored for a controlled initial state and are then synchronized by the directive.

CSS custom properties

This directive does not write component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

The directive follows the application-rendered result DOM and owns active-descendant navigation, enabled-option wrapping and boundaries, pointer synchronization, Enter activation through the authored click handler, semantic group and empty state, and scroll-to-active behavior. AngularTS remains responsible for query filtering, command execution, result data, structural bindings, and application keyboard shortcuts. Dialog remains responsible for modal disclosure, focus trapping, Escape, outside dismissal, and focus restoration.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Give the search input and command surface useful accessible names. The input is connected to a listbox through aria-controls and aria-activedescendant; rendered options expose selected and disabled state, labeled groups retain group relationships, separators are decorative structure, and shortcut labels are hidden from repeated announcement. A modal composition must include an accessible Dialog title and description.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target [ng-command], semantic descendants, component classes, and generated state with ordinary CSS. Keep behavior and accessible state in the TypeScript directive; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.