command

Fast, composable, unstyled command menu for Angular.

PreviousNext
Use arrow keys to navigate, Enter to select, Escape to clear selection.
Suggestions
Calendar
Search Emoji
Calculator
Settings
Profile⌘P
Billing⌘B
Settings⌘S
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { provideIcons } from '@ng-icons/core';
import {
  lucideCalculator,
  lucideCalendar,
  lucideCreditCard,
  lucideSettings,
  lucideSmile,
  lucideUser,
} from '@ng-icons/lucide';

import { ZardCommandImports } from '@/shared/components/command/command.imports';

@Component({
  selector: 'z-demo-command-default',
  imports: [ZardCommandImports],
  template: `
    <z-command class="min-w-sm" #cmd="zCommand">
      <z-command-input placeholder="Type a command or search..." />
      <z-command-list>
        @if (cmd.isEmpty()) {
          <div class="py-6 text-center text-sm">No results found.</div>
        }

        <z-command-option-group zLabel="Suggestions">
          <z-command-option zLabel="Calendar" zValue="calendar" zIcon="lucideCalendar" />
          <z-command-option zLabel="Search Emoji" zValue="emoji" zIcon="lucideSmile" />
          <z-command-option zLabel="Calculator" zValue="calculator" zIcon="lucideCalculator" [zDisabled]="true" />
        </z-command-option-group>

        <z-command-divider />

        <z-command-option-group zLabel="Settings">
          <z-command-option zLabel="Profile" zValue="profile" zIcon="lucideUser" zShortcut="⌘P" />
          <z-command-option zLabel="Billing" zValue="billing" zIcon="lucideCreditCard" zShortcut="⌘B" />
          <z-command-option zLabel="Settings" zValue="settings" zIcon="lucideSettings" zShortcut="⌘S" />
        </z-command-option-group>
      </z-command-list>
    </z-command>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [
    provideIcons({
      lucideCalendar,
      lucideSmile,
      lucideCalculator,
      lucideUser,
      lucideCreditCard,
      lucideSettings,
    }),
  ],
})
export class ZardDemoCommandDefaultComponent {}

Installation

Copy
npx zard-cli@latest add command

Usage

import { ZardCommandImports } from '@/shared/components/command/command.imports';
Copy
<z-command #cmd="zCommand">
  <z-command-input placeholder="Type a command..." />
  <z-command-list>
    @if (cmd.isEmpty()) {
      <div class="py-6 text-center text-sm">No results found.</div>
    }
    <z-command-option-group zLabel="Suggestions">
      <z-command-option zLabel="Calendar" zValue="calendar" />
    </z-command-option-group>
  </z-command-list>
</z-command>
Copy

Examples

basic

import { type AfterViewInit, ChangeDetectionStrategy, Component, inject, viewChild } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCommandComponent } from '@/shared/components/command/command.component';
import { ZardCommandImports } from '@/shared/components/command/command.imports';
import { ZardDialogService } from '@/shared/components/dialog/dialog.service';

@Component({
  selector: 'z-demo-command-basic-dialog',
  imports: [ZardCommandImports],
  template: `
    <z-command #cmd="zCommand">
      <z-command-input placeholder="Type a command or search..." />
      <z-command-list>
        @if (cmd.isEmpty()) {
          <div class="py-6 text-center text-sm">No results found.</div>
        }
        <z-command-option-group zLabel="Suggestions">
          <z-command-option zLabel="Calendar" zValue="calendar" />
          <z-command-option zLabel="Search Emoji" zValue="emoji" />
          <z-command-option zLabel="Calculator" zValue="calculator" />
        </z-command-option-group>
      </z-command-list>
    </z-command>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class ZardDemoCommandBasicDialogComponent implements AfterViewInit {
  private readonly cmd = viewChild.required(ZardCommandComponent);
  ngAfterViewInit() {
    setTimeout(() => this.cmd().focus(), 0);
  }
}

@Component({
  selector: 'z-demo-command-basic',
  imports: [ZardButtonComponent],
  template: `
    <button type="button" z-button zType="outline" (click)="open()">Open Menu</button>
  `,
})
export class ZardDemoCommandBasicComponent {
  private readonly dialogService = inject(ZardDialogService);

  open() {
    this.dialogService.create({
      zContent: ZardDemoCommandBasicDialogComponent,
      zClosable: false,
      zHideFooter: true,
      zOkText: null,
      zCancelText: null,
      zMaskClosable: true,
      zWidth: '24rem',
      zCustomClasses: '!p-0 !gap-0 !border-0 !bg-transparent !shadow-none',
    });
  }
}

shortcuts

import { type AfterViewInit, ChangeDetectionStrategy, Component, inject, viewChild } from '@angular/core';

import { provideIcons } from '@ng-icons/core';
import { lucideCreditCard, lucideSettings, lucideUser } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCommandComponent } from '@/shared/components/command/command.component';
import { ZardCommandImports } from '@/shared/components/command/command.imports';
import { ZardDialogService } from '@/shared/components/dialog/dialog.service';

@Component({
  selector: 'z-demo-command-shortcuts-dialog',
  imports: [ZardCommandImports],
  template: `
    <z-command #cmd="zCommand">
      <z-command-input placeholder="Type a command or search..." />
      <z-command-list>
        @if (cmd.isEmpty()) {
          <div class="py-6 text-center text-sm">No results found.</div>
        }
        <z-command-option-group zLabel="Settings">
          <z-command-option zLabel="Profile" zValue="profile" zIcon="lucideUser" zShortcut="⌘P" />
          <z-command-option zLabel="Billing" zValue="billing" zIcon="lucideCreditCard" zShortcut="⌘B" />
          <z-command-option zLabel="Settings" zValue="settings" zIcon="lucideSettings" zShortcut="⌘S" />
        </z-command-option-group>
      </z-command-list>
    </z-command>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [provideIcons({ lucideUser, lucideCreditCard, lucideSettings })],
})
class ZardDemoCommandShortcutsDialogComponent implements AfterViewInit {
  private readonly cmd = viewChild.required(ZardCommandComponent);
  ngAfterViewInit() {
    setTimeout(() => this.cmd().focus(), 0);
  }
}

@Component({
  selector: 'z-demo-command-shortcuts',
  imports: [ZardButtonComponent],
  template: `
    <button type="button" z-button zType="outline" (click)="open()">Open Menu</button>
  `,
})
export class ZardDemoCommandShortcutsComponent {
  private readonly dialogService = inject(ZardDialogService);

  open() {
    this.dialogService.create({
      zContent: ZardDemoCommandShortcutsDialogComponent,
      zClosable: false,
      zHideFooter: true,
      zOkText: null,
      zCancelText: null,
      zMaskClosable: true,
      zWidth: '24rem',
      zCustomClasses: '!p-0 !gap-0 !border-0 !bg-transparent !shadow-none',
    });
  }
}

groups

import { type AfterViewInit, ChangeDetectionStrategy, Component, inject, viewChild } from '@angular/core';

import { provideIcons } from '@ng-icons/core';
import {
  lucideCalculator,
  lucideCalendar,
  lucideCreditCard,
  lucideSettings,
  lucideSmile,
  lucideUser,
} from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCommandComponent } from '@/shared/components/command/command.component';
import { ZardCommandImports } from '@/shared/components/command/command.imports';
import { ZardDialogService } from '@/shared/components/dialog/dialog.service';

@Component({
  selector: 'z-demo-command-groups-dialog',
  imports: [ZardCommandImports],
  template: `
    <z-command #cmd="zCommand">
      <z-command-input placeholder="Type a command or search..." />
      <z-command-list>
        @if (cmd.isEmpty()) {
          <div class="py-6 text-center text-sm">No results found.</div>
        }

        <z-command-option-group zLabel="Suggestions">
          <z-command-option zLabel="Calendar" zValue="calendar" zIcon="lucideCalendar" />
          <z-command-option zLabel="Search Emoji" zValue="emoji" zIcon="lucideSmile" />
          <z-command-option zLabel="Calculator" zValue="calculator" zIcon="lucideCalculator" />
        </z-command-option-group>

        <z-command-divider />

        <z-command-option-group zLabel="Settings">
          <z-command-option zLabel="Profile" zValue="profile" zIcon="lucideUser" zShortcut="⌘P" />
          <z-command-option zLabel="Billing" zValue="billing" zIcon="lucideCreditCard" zShortcut="⌘B" />
          <z-command-option zLabel="Settings" zValue="settings" zIcon="lucideSettings" zShortcut="⌘S" />
        </z-command-option-group>
      </z-command-list>
    </z-command>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [
    provideIcons({ lucideCalendar, lucideSmile, lucideCalculator, lucideUser, lucideCreditCard, lucideSettings }),
  ],
})
class ZardDemoCommandGroupsDialogComponent implements AfterViewInit {
  private readonly cmd = viewChild.required(ZardCommandComponent);
  ngAfterViewInit() {
    setTimeout(() => this.cmd().focus(), 0);
  }
}

@Component({
  selector: 'z-demo-command-groups',
  imports: [ZardButtonComponent],
  template: `
    <button type="button" z-button zType="outline" (click)="open()">Open Menu</button>
  `,
})
export class ZardDemoCommandGroupsComponent {
  private readonly dialogService = inject(ZardDialogService);

  open() {
    this.dialogService.create({
      zContent: ZardDemoCommandGroupsDialogComponent,
      zClosable: false,
      zHideFooter: true,
      zOkText: null,
      zCancelText: null,
      zMaskClosable: true,
      zWidth: '24rem',
      zCustomClasses: '!p-0 !gap-0 !border-0 !bg-transparent !shadow-none',
    });
  }
}

scrollable

import { type AfterViewInit, ChangeDetectionStrategy, Component, inject, viewChild } from '@angular/core';

import { provideIcons } from '@ng-icons/core';
import {
  lucideBell,
  lucideCalculator,
  lucideCalendar,
  lucideCircleHelp,
  lucideClipboardPaste,
  lucideCode,
  lucideCopy,
  lucideCreditCard,
  lucideFileText,
  lucideFolder,
  lucideFolderPlus,
  lucideHouse,
  lucideImage,
  lucideInbox,
  lucideLayoutGrid,
  lucideList,
  lucidePlus,
  lucideScissors,
  lucideSettings,
  lucideTrash2,
  lucideUser,
  lucideZoomIn,
  lucideZoomOut,
} from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCommandComponent } from '@/shared/components/command/command.component';
import { ZardCommandImports } from '@/shared/components/command/command.imports';
import { ZardDialogService } from '@/shared/components/dialog/dialog.service';

@Component({
  selector: 'z-demo-command-scrollable-dialog',
  imports: [ZardCommandImports],
  template: `
    <z-command #cmd="zCommand">
      <z-command-input placeholder="Type a command or search..." />
      <z-command-list>
        @if (cmd.isEmpty()) {
          <div class="py-6 text-center text-sm">No results found.</div>
        }

        <z-command-option-group zLabel="Navigation">
          <z-command-option zLabel="Home" zValue="home" zIcon="lucideHouse" zShortcut="⌘H" />
          <z-command-option zLabel="Inbox" zValue="inbox" zIcon="lucideInbox" zShortcut="⌘I" />
          <z-command-option zLabel="Documents" zValue="documents" zIcon="lucideFileText" zShortcut="⌘D" />
          <z-command-option zLabel="Folders" zValue="folders" zIcon="lucideFolder" zShortcut="⌘F" />
        </z-command-option-group>

        <z-command-divider />

        <z-command-option-group zLabel="Actions">
          <z-command-option zLabel="New File" zValue="new-file" zIcon="lucidePlus" zShortcut="⌘N" />
          <z-command-option zLabel="New Folder" zValue="new-folder" zIcon="lucideFolderPlus" zShortcut="⇧⌘N" />
          <z-command-option zLabel="Copy" zValue="copy" zIcon="lucideCopy" zShortcut="⌘C" />
          <z-command-option zLabel="Cut" zValue="cut" zIcon="lucideScissors" zShortcut="⌘X" />
          <z-command-option zLabel="Paste" zValue="paste" zIcon="lucideClipboardPaste" zShortcut="⌘V" />
          <z-command-option zLabel="Delete" zValue="delete" zIcon="lucideTrash2" zShortcut="⌫" />
        </z-command-option-group>

        <z-command-divider />

        <z-command-option-group zLabel="View">
          <z-command-option zLabel="Grid View" zValue="grid" zIcon="lucideLayoutGrid" />
          <z-command-option zLabel="List View" zValue="list" zIcon="lucideList" />
          <z-command-option zLabel="Zoom In" zValue="zoom-in" zIcon="lucideZoomIn" zShortcut="⌘+" />
          <z-command-option zLabel="Zoom Out" zValue="zoom-out" zIcon="lucideZoomOut" zShortcut="⌘-" />
        </z-command-option-group>

        <z-command-divider />

        <z-command-option-group zLabel="Account">
          <z-command-option zLabel="Profile" zValue="profile" zIcon="lucideUser" zShortcut="⌘P" />
          <z-command-option zLabel="Billing" zValue="billing" zIcon="lucideCreditCard" zShortcut="⌘B" />
          <z-command-option zLabel="Settings" zValue="settings" zIcon="lucideSettings" zShortcut="⌘S" />
          <z-command-option zLabel="Notifications" zValue="notifications" zIcon="lucideBell" />
          <z-command-option zLabel="Help & Support" zValue="help" zIcon="lucideCircleHelp" />
        </z-command-option-group>

        <z-command-divider />

        <z-command-option-group zLabel="Tools">
          <z-command-option zLabel="Calculator" zValue="calculator" zIcon="lucideCalculator" />
          <z-command-option zLabel="Calendar" zValue="calendar" zIcon="lucideCalendar" />
          <z-command-option zLabel="Image Editor" zValue="image" zIcon="lucideImage" />
          <z-command-option zLabel="Code Editor" zValue="code" zIcon="lucideCode" />
        </z-command-option-group>
      </z-command-list>
    </z-command>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [
    provideIcons({
      lucideHouse,
      lucideInbox,
      lucideFileText,
      lucideFolder,
      lucidePlus,
      lucideFolderPlus,
      lucideCopy,
      lucideScissors,
      lucideClipboardPaste,
      lucideTrash2,
      lucideLayoutGrid,
      lucideList,
      lucideZoomIn,
      lucideZoomOut,
      lucideUser,
      lucideCreditCard,
      lucideSettings,
      lucideBell,
      lucideCircleHelp,
      lucideCalculator,
      lucideCalendar,
      lucideImage,
      lucideCode,
    }),
  ],
})
class ZardDemoCommandScrollableDialogComponent implements AfterViewInit {
  private readonly cmd = viewChild.required(ZardCommandComponent);
  ngAfterViewInit() {
    setTimeout(() => this.cmd().focus(), 0);
  }
}

@Component({
  selector: 'z-demo-command-scrollable',
  imports: [ZardButtonComponent],
  template: `
    <button type="button" z-button zType="outline" (click)="open()">Open Menu</button>
  `,
})
export class ZardDemoCommandScrollableComponent {
  private readonly dialogService = inject(ZardDialogService);

  open() {
    this.dialogService.create({
      zContent: ZardDemoCommandScrollableDialogComponent,
      zClosable: false,
      zHideFooter: true,
      zOkText: null,
      zCancelText: null,
      zMaskClosable: true,
      zWidth: '24rem',
      zCustomClasses: '!p-0 !gap-0 !border-0 !bg-transparent !shadow-none',
    });
  }
}

API Reference

z-commandComponent

The main command palette container that handles search input and keyboard navigation with debounced search, ARIA accessibility, and comprehensive keyboard navigation.

PropertyDescriptionTypeDefault
[size] Size of the command palette 'sm' | 'default' | 'lg' | 'xl' 'default'
[class] Additional CSS classes string ''
(zCommandChange) Fired when the selected option changes output<ZardCommandOption> -
(zCommandSelected) Fired when an option is selected output<ZardCommandOption> -

z-command-inputComponent

Search input component with debounced input handling and accessibility features.

PropertyDescriptionTypeDefault
[placeholder] Placeholder text for input string 'Type a command or search...'
[class] Additional CSS classes string ''
(valueChange) Fired when input value changes EventEmitter<string> -

z-command-listComponent

Container for command options with proper ARIA listbox semantics.

PropertyDescriptionTypeDefault
[class] Additional CSS classes string ''

z-command-optionComponent

Individual selectable option within the command palette with enhanced accessibility and interaction features.

PropertyDescriptionTypeDefault
[zValue] Value of the option (required) any -
[zLabel] Label text (required) string -
[zIcon] Icon HTML content string ''
[zCommand] Command identifier string ''
[zShortcut] Keyboard shortcut display string ''
[zDisabled] Disabled state boolean false
[variant] Visual variant 'default' | 'destructive' 'default'
[class] Additional CSS classes string ''

z-command-option-groupComponent

Groups related command options together with semantic grouping and accessibility.

PropertyDescriptionTypeDefault
[zLabel] Group label (required) string -
[class] Additional CSS classes string ''

z-command-dividerComponent

Visual separator between command groups with semantic role.

PropertyDescriptionTypeDefault
[class] Additional CSS classes string ''
github iconwhatsapp icondiscord iconX icon

Made with in Brazil. Open source and available on GitHub .