- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Autocomplete
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Dropdown Menu
- Empty
- Field
- Form Field
- Hover Card
- Icon
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Label
- Menubar
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner (Toast)
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
Command
Fast, composable, command menu for Angular.
import { Component } from '@angular/core';
import { provideIcons } from '@ng-icons/core';
import {
lucideCalculator,
lucideCalendar,
lucideCog,
lucidePlus,
lucideSearch,
lucideSmile,
lucideUser,
lucideWallet,
} from '@ng-icons/lucide';
import { HlmCommandImports } from '@spartan-ng/helm/command';
import { HlmIconImports } from '@spartan-ng/helm/icon';
@Component({
selector: 'spartan-command-preview',
imports: [HlmCommandImports, HlmIconImports],
providers: [
provideIcons({
lucideSearch,
lucideCalendar,
lucideSmile,
lucidePlus,
lucideUser,
lucideWallet,
lucideCog,
lucideCalculator,
}),
],
host: {
class: 'block w-full',
},
template: `
<hlm-command class="rounded-lg border shadow-md md:min-w-[450px]">
<hlm-command-input placeholder="Type a command or search..." />
<hlm-command-list>
<div *hlmCommandEmptyState hlmCommandEmpty>No results found.</div>
<hlm-command-group>
<hlm-command-group-label>Suggestions</hlm-command-group-label>
<button hlm-command-item value="Calendar">
<ng-icon name="lucideCalendar" />
Calendar
</button>
<button hlm-command-item value="Search Emoji">
<ng-icon name="lucideSmile" />
Search Emoji
</button>
<button hlm-command-item value="Calculator" disabled>
<ng-icon name="lucideCalculator" />
Calculator
</button>
</hlm-command-group>
<hlm-command-separator />
<hlm-command-group>
<hlm-command-group-label>Settings</hlm-command-group-label>
<button hlm-command-item value="Profile">
<ng-icon name="lucideUser" />
Profile
<hlm-command-shortcut>⌘P</hlm-command-shortcut>
</button>
<button hlm-command-item value="Billing">
<ng-icon name="lucideWallet" />
Billing
<hlm-command-shortcut>⌘B</hlm-command-shortcut>
</button>
<button hlm-command-item value="Settings">
<ng-icon name="lucideCog" />
Settings
<hlm-command-shortcut>⌘S</hlm-command-shortcut>
</button>
</hlm-command-group>
</hlm-command-list>
</hlm-command>
`,
})
export class CommandPreview {}Installation
ng g @spartan-ng/cli:ui command
npx nx g @spartan-ng/cli:ui command
Usage
import { HlmCommandImports } from '@spartan-ng/helm/command';<hlm-command>
<hlm-command-input placeholder="Type a command or search..." />
<hlm-command-list>
<div *hlmCommandEmptyState hlmCommandEmpty>No results found.</div>
<hlm-command-group>
<hlm-command-group-label>Suggestions</hlm-command-group-label>
<button hlm-command-item value="Calendar">
<ng-icon name="lucideCalendar" />
Calendar
</button>
</hlm-command-group>
<hlm-command-separator />
<hlm-command-group>
<hlm-command-group-label>Settings</hlm-command-group-label>
<button hlm-command-item value="Profile">
<ng-icon name="lucideUser" />
Profile
<hlm-command-shortcut>⌘P</hlm-command-shortcut>
</button>
</hlm-command-group>
</hlm-command-list>
</hlm-command>Examples
Dialog
Press ⌘ + J
Last command: none
import { Component, signal } from '@angular/core';
import { provideIcons } from '@ng-icons/core';
import {
lucideCalendar,
lucideCog,
lucideLayers,
lucidePlus,
lucideSearch,
lucideSmile,
lucideUser,
lucideX,
} from '@ng-icons/lucide';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { HlmCommandImports } from '@spartan-ng/helm/command';
import { HlmIconImports } from '@spartan-ng/helm/icon';
import { HlmKbdImports } from '@spartan-ng/helm/kbd';
@Component({
selector: 'spartan-command-dialog',
imports: [HlmCommandImports, HlmIconImports, HlmButtonImports, HlmKbdImports],
providers: [
provideIcons({
lucideX,
lucideCalendar,
lucideSmile,
lucidePlus,
lucideUser,
lucideLayers,
lucideCog,
lucideSearch,
}),
],
host: {
'(window:keydown)': 'onKeyDown($event)',
},
template: `
<div class="mx-auto flex max-w-screen-sm items-center justify-center space-x-4 py-20 text-sm">
<p>
Press
<kbd hlmKbd>⌘ + J</kbd>
</p>
<p>
Last command:
<code data-testid="lastCommand" hlmCode>{{ command() || 'none' }}</code>
</p>
</div>
<hlm-command-dialog [state]="state()" (stateChange)="stateChanged($event)">
<hlm-command>
<hlm-command-input placeholder="Type a command or search..." />
<hlm-command-list>
<div *hlmCommandEmptyState hlmCommandEmpty>No results found.</div>
<hlm-command-group>
<hlm-command-group-label>Suggestions</hlm-command-group-label>
<button hlm-command-item value="calendar" (selected)="commandSelected('calendar')">
<ng-icon name="lucideCalendar" />
Calendar
</button>
<button hlm-command-item value="emojy" (selected)="commandSelected('emojy')">
<ng-icon name="lucideSmile" />
Search Emoji
</button>
<button hlm-command-item value="calculator" (selected)="commandSelected('calculator')">
<ng-icon name="lucidePlus" />
Calculator
</button>
</hlm-command-group>
<hlm-command-separator />
<hlm-command-group>
<hlm-command-group-label>Settings</hlm-command-group-label>
<button hlm-command-item value="profile" (selected)="commandSelected('profile')">
<ng-icon name="lucideUser" />
Profile
<hlm-command-shortcut>⌘P</hlm-command-shortcut>
</button>
<button hlm-command-item value="billing" (selected)="commandSelected('billing')">
<ng-icon name="lucideLayers" />
Billing
<hlm-command-shortcut>⌘B</hlm-command-shortcut>
</button>
<button hlm-command-item value="settings" (selected)="commandSelected('settings')">
<ng-icon name="lucideCog" />
Settings
<hlm-command-shortcut>⌘S</hlm-command-shortcut>
</button>
</hlm-command-group>
</hlm-command-list>
</hlm-command>
</hlm-command-dialog>
`,
})
export class CommandDialog {
public readonly command = signal('');
public readonly state = signal<'closed' | 'open'>('closed');
onKeyDown(event: KeyboardEvent) {
if ((event.metaKey || event.ctrlKey) && (event.key === 'j' || event.key === 'J')) {
this.state.set('open');
}
}
stateChanged(state: 'open' | 'closed') {
this.state.set(state);
}
commandSelected(selected: string) {
this.state.set('closed');
this.command.set(selected);
}
}Combobox
You can use the Command component as a combobox. Otherwise use the Combobox component for more advanced use cases.
import { Component, signal } from '@angular/core';
import { provideIcons } from '@ng-icons/core';
import { lucideCheck, lucideChevronsUpDown, lucideSearch } from '@ng-icons/lucide';
import { BrnPopoverImports } from '@spartan-ng/brain/popover';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { HlmCommandImports } from '@spartan-ng/helm/command';
import { HlmIconImports } from '@spartan-ng/helm/icon';
import { HlmPopoverImports } from '@spartan-ng/helm/popover';
type Framework = { label: string; value: string };
@Component({
selector: 'spartan-command-combobox-preview',
imports: [HlmCommandImports, HlmIconImports, HlmButtonImports, BrnPopoverImports, HlmPopoverImports],
providers: [provideIcons({ lucideChevronsUpDown, lucideSearch, lucideCheck })],
template: `
<hlm-popover [state]="state()" (stateChanged)="stateChanged($event)" sideOffset="5">
<button
class="w-[200px] justify-between"
id="edit-profile"
hlmPopoverTrigger
(click)="state.set('open')"
hlmBtn
variant="outline"
>
{{ currentFramework() ? currentFramework()?.label : 'Select framework...' }}
<ng-icon hlm size="sm" name="lucideChevronsUpDown" class="opacity-50" />
</button>
<hlm-command *brnPopoverContent="let ctx" hlmPopoverContent class="w-[200px] p-0">
<hlm-command-input placeholder="Search framework..." />
<div *hlmCommandEmptyState hlmCommandEmpty>No results found.</div>
<hlm-command-list>
<hlm-command-group>
@for (framework of frameworks; track framework) {
<button hlm-command-item [value]="framework.value" (selected)="commandSelected(framework)">
<span>{{ framework.label }}</span>
<ng-icon
hlm
class="ml-auto"
[class.opacity-0]="currentFramework()?.value !== framework.value"
name="lucideCheck"
hlmCommandIcon
/>
</button>
}
</hlm-command-group>
</hlm-command-list>
</hlm-command>
</hlm-popover>
`,
})
export class CommandComboboxPreview {
public frameworks = [
{
label: 'AnalogJs',
value: 'analogjs',
},
{
label: 'Angular',
value: 'angular',
},
{
label: 'Vue',
value: 'vue',
},
{
label: 'Nuxt',
value: 'nuxt',
},
{
label: 'React',
value: 'react',
},
{
label: 'NextJs',
value: 'nextjs',
},
];
public readonly currentFramework = signal<Framework | undefined>(undefined);
public readonly state = signal<'closed' | 'open'>('closed');
stateChanged(state: 'open' | 'closed') {
this.state.set(state);
}
commandSelected(framework: Framework) {
this.state.set('closed');
if (this.currentFramework()?.value === framework.value) {
this.currentFramework.set(undefined);
} else {
this.currentFramework.set(framework);
}
}
}Brain API
BrnCommandEmpty
Selector: [brnCommandEmpty]
BrnCommandGroup
Selector: [brnCommandGroup]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-command-group-${++BrnCommandGroup._id}` | The id of the command list |
BrnCommandInput
Selector: input[brnCommandInput]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | this._initialId | The id of the command input |
BrnCommandItem
Selector: button[brnCommandItem]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-command-item-${++BrnCommandItem._id}` | A unique id for the item |
| value* (required) | string | - | The value this item represents. |
| disabled | boolean | false | Whether the item is disabled. |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| selected | void | - | Emits when the item is selected. |
BrnCommandList
Selector: [brnCommandList]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-command-list-${++BrnCommandList._id}` | The id of the command list |
BrnCommandSeparator
Selector: [brnCommandSeparator]
BrnCommand
Selector: [brnCommand]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-command-${++BrnCommand._id}` | The id of the command |
| filter | CommandFilter | this._config.filter | A custom filter function to use when searching. |
| disabled | boolean | false | Whether the command is disabled |
| search | string | - | The current search query. |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| valueChange | string | - | when the selection has changed |
| searchChanged | string | - | The current search query. |
Helm API
HlmCommandDialog
Selector: hlm-command-dialog
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | Command Palette | - |
| description | string | Search for a command to run... | - |
| state | BrnDialogState | closed | - |
| showCloseButton | boolean | false | - |
| dialogContentClass | ClassValue | - | - |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| stateChange | BrnDialogState | - | - |
HlmCommandEmptyState
Selector: [hlmCommandEmptyState]
HlmCommandEmpty
Selector: [hlmCommandEmpty]
HlmCommandGroupLabel
Selector: [hlmCommandGroupLabel],hlm-command-group-label
HlmCommandGroup
Selector: [hlmCommandGroup],hlm-command-group
HlmCommandInput
Selector: hlm-command-input
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | undefined | - | - |
| placeholder | string | - | - |
HlmCommandItem
Selector: button[hlmCommandItem],button[hlm-command-item]
HlmCommandList
Selector: [hlmCommandList],hlm-command-list
HlmCommandSeparator
Selector: [hlmCommandSeparator],hlm-command-separator
HlmCommandShortcut
Selector: [hlmCommandShortcut],hlm-command-shortcut
HlmCommand
Selector: [hlmCommand],hlm-command
On This Page