Command

A search box with a filtered list of actions.

import { … } from '@inlaylab/ivorie/command'
CalendarSearch EmojiCalculatorProfile⌘PBilling⌘BSettings⌘S
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_COMMAND_IMPORTS } from '@inlaylab/ivorie/command';

@Component({
  selector: 'demo-command',
  imports: [IV_COMMAND_IMPORTS],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <iv-command class="max-w-sm rounded-lg border shadow-md">
      <iv-command-input placeholder="Type a command or search..." />
      <iv-command-list>
        <iv-command-empty>No results found.</iv-command-empty>
        <iv-command-group heading="Suggestions">
          <iv-command-item>Calendar</iv-command-item>
          <iv-command-item>Search Emoji</iv-command-item>
          <iv-command-item [disabled]="true">Calculator</iv-command-item>
        </iv-command-group>
        <iv-command-separator />
        <iv-command-group heading="Settings">
          <iv-command-item>Profile<iv-command-shortcut>⌘P</iv-command-shortcut></iv-command-item>
          <iv-command-item>Billing<iv-command-shortcut>⌘B</iv-command-shortcut></iv-command-item>
          <iv-command-item>Settings<iv-command-shortcut>⌘S</iv-command-shortcut></iv-command-item>
        </iv-command-group>
      </iv-command-list>
    </iv-command>
  `,
})
export default class CommandDemo {}

Installation

CLInpm
npx ivorie add command

Type to filter. Arrow keys move the highlight, Enter picks. Like shadcn's Command (cmdk).

Usage

import { IV_COMMAND_IMPORTS } from '@inlaylab/ivorie/command';
<iv-command>
  <iv-command-input placeholder="Search..." />
  <iv-command-list>
    <iv-command-empty>No results.</iv-command-empty>
    <iv-command-group heading="Suggestions">
      <iv-command-item (select)="run($event)">Calendar</iv-command-item>
    </iv-command-group>
  </iv-command-list>
</iv-command>

Examples

In a dialog

Put the command in a Dialog template for a command palette.

Last pick: none

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { IvButton } from '@inlaylab/ivorie/button';
import { IV_COMMAND_IMPORTS } from '@inlaylab/ivorie/command';
import { IV_DIALOG_IMPORTS } from '@inlaylab/ivorie/dialog';

@Component({
  selector: 'demo-command-dialog',
  imports: [IV_COMMAND_IMPORTS, IV_DIALOG_IMPORTS, IvButton],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="flex flex-col items-center gap-2">
      <button ivButton variant="outline" [ivDialogTrigger]="palette" [ivDialogConfig]="{ ariaLabel: 'Command palette', showCloseButton: false }">
        Open command palette
      </button>
      <p class="text-muted-foreground text-sm">Last pick: {{ picked() || 'none' }}</p>
    </div>
    <ng-template #palette let-ref>
      <iv-command>
        <iv-command-input placeholder="Search actions..." />
        <iv-command-list>
          <iv-command-empty>No results found.</iv-command-empty>
          @for (action of actions; track action) {
            <iv-command-item (select)="picked.set($event); ref.close($event)">{{ action }}</iv-command-item>
          }
        </iv-command-list>
      </iv-command>
    </ng-template>
  `,
})
export default class CommandDialogDemo {
  readonly actions = ['New file', 'Open recent', 'Toggle sidebar', 'Sign out'];
  readonly picked = signal('');
}

API

Every part also accepts class.

iv-command

Name Type Default Description
search string (two-way) '' The search text.
shouldFilter boolean true false shows every item, e.g. when you filter on the server.

iv-command-input

Name Type Default Description
placeholder string | null null Placeholder text.
aria-label string | null 'Search' Label for the input.
disabled boolean false Disables the input.

iv-command-item

Name Type Default Description
value string | null item text Text the search matches and select emits.
keywords string[] [] Extra words the search matches.
disabled boolean false Skipped by arrows, ignores clicks.
checked boolean false Shows a check mark.

Output: select (string): the item's value, on click or Enter.

Other parts

  • iv-command-list, iv-command-empty (shown when nothing matches), iv-command-group (heading), iv-command-separator, iv-command-shortcut.
  • A group with no matching item hides.

Accessibility

The input is a combobox that controls the listbox. The highlight uses aria-activedescendant, so focus stays in the input. Disabled items have aria-disabled.