- 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-search>
<ng-icon hlm name="lucideSearch" class="shrink-0 opacity-50" />
<input type="text" hlm-command-search-input placeholder="Type a command or search..." />
</hlm-command-search>
<hlm-command-list>
<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>
<!-- Empty state -->
<div *hlmCommandEmptyState hlmCommandEmpty>No results found.</div>
</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-search>
<ng-icon hlm name="lucideSearch" />
<input type="text" hlm-command-search-input placeholder="Type a command or search..." />
</hlm-command-search>
<hlm-command-list>
<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>
<!-- Empty state -->
<div *brnCommandEmpty hlmCommandEmpty>No results found.</div>
</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 { BrnDialogImports } from '@spartan-ng/brain/dialog';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { HlmCommandImports } from '@spartan-ng/helm/command';
import { HlmDialogImports } from '@spartan-ng/helm/dialog';
import { HlmIconImports } from '@spartan-ng/helm/icon';
import { HlmKbdImports } from '@spartan-ng/helm/kbd';
@Component({
selector: 'spartan-command-dialog',
imports: [HlmDialogImports, BrnDialogImports, 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-dialog [state]="state()" (stateChanged)="stateChanged($event)">
<hlm-dialog-content *brnDialogContent="let ctx" class="w-[400px] p-0">
<hlm-command hlmCommandDialog>
<hlm-command-search>
<ng-icon hlm name="lucideSearch" />
<input placeholder="Type a command or search..." hlm-command-search-input />
</hlm-command-search>
<div *hlmCommandEmptyState hlmCommandEmpty>No results found.</div>
<hlm-command-list>
<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-dialog-content>
</hlm-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-search>
<ng-icon hlm name="lucideSearch" />
<input placeholder="Search framework..." hlm-command-search-input />
</hlm-command-search>
<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 |
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 |
BrnCommandSearchInput
Selector: input[brnCommandSearchInput]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | The initial value of the search input |
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. |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| valueChange | string | - | when the selection has changed |
Helm API
HlmCommandDialog
Selector: [hlmCommandDialog]
HlmCommandEmptyState
Selector: [hlmCommandEmptyState]
HlmCommandEmpty
Selector: [hlmCommandEmpty]
HlmCommandGroupLabel
Selector: [hlmCommandGroupLabel],hlm-command-group-label
HlmCommandGroup
Selector: [hlmCommandGroup],hlm-command-group
HlmCommandItem
Selector: button[hlmCommandItem],button[hlm-command-item]
HlmCommandList
Selector: [hlmCommandList],hlm-command-list
HlmCommandSearchInput
Selector: input[hlmCommandSearchInput],input[hlm-command-search-input]
HlmCommandSearch
Selector: [hlmCommandSearch],hlm-command-search
HlmCommandSeparator
Selector: [hlmCommandSeparator],hlm-command-separator
HlmCommandShortcut
Selector: [hlmCommandShortcut],hlm-command-shortcut
HlmCommand
Selector: [hlmCommand],hlm-command
On This Page