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 { 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>
  `,
  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, 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>
  `,
})
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 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, 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>
  `,
  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 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, 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>
  `,
  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 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, 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>
  `,
  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 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 .