Skip to main content

glint-command-action

The glint-command-action component adds a button to your application that opens a command dialog. This dialog allows users to quickly execute commands by typing, providing a faster alternative to traditional navigation. It also includes the Ctrl+K keyboard shortcut for convenient access.

Usage

To use the component, simply add the <glint-command-action/> tag to your HTML. It's typically placed within a ProjectComponent or similar layout component.

<div id="my-buttons">
<glint-command-action/>
</div>

Command Providers

Commands are built from a sequence of arguments. CommandProviders are services that generate these argument options, which the user selects by typing and pressing Enter in the command dialog. The dialog does not support free-text input; all options must be provided by a CommandProvider.

Core Interfaces

The CommandProvider interface defines the core functionality for generating and executing commands:

  • categories?(): CommandArgumentCategory[]: Defines categories that can be referenced by arguments.
  • generateArguments?(command: Command): CommandArgumentGenerator: Based on the current command, generates options for the next argument.
  • summary?(command: Command): CommandSummary | undefined: Provides a summary to explain the command to the user.
  • execute?(command: Command): CommandStageGenerator: Performs the final action when the command is executed.

The CommandArgument interface defines the structure of a single argument:

  • type: CommandArgumentType: Controls the continuation behavior.
  • value: string: The value of the argument.
  • category: string: A reference to a predefined category.
  • data: unknown: Custom data to be passed to generateArguments() and execute().
  • icon?: VariableIcon: An optional icon.
  • description?: string: An optional description.

Generating Arguments

CommandProviders generate arguments using an asynchronous generator function (async*). This allows the provider to yield multiple arguments and await asynchronous operations (e.g., fetching data from an API) before yielding more.

async function* declarations in javascript

class MyCommandService {
async* generateArguments(command: Command): CommandArgumentGenerator {
// If no arguments exist, yield an initial option.
if (command.args.length === 0) {
yield {
type: CommandArgumentType.EXECUTE,
value: '/foo',
/* ... */
};
}

// Await an API call and yield results as arguments.
const response = await fetch('...');
if (response.ok) {
yield { /* ... */ };
}
}
}

The CommandArgumentType enum defines how the dialog behaves after an argument is selected:

  • CommandArgumentType.PARTIAL: Requires more arguments to be executed.
  • CommandArgumentType.IMMEDIATE: Executes the command immediately without showing progress.
  • CommandArgumentType.EXECUTE: Executes the command and keeps the dialog open to display execution output.

Execution

The execute method can contain any asynchronous logic. It also uses an asynchronous generator to provide real-time feedback to the user via stages, such as pending and success.

class MyCommandService {
async* execute(command: Command): CommandStageGenerator {
// Yield a pending stage to show work is in progress.
const pending = yield stagePending({ title: 'Doing stuff' });

// Perform an asynchronous task...
// The pending stage can be updated with more information.
pending.update({ extraInfo: 'progress...' });

// Mark the pending stage as complete.
pending.complete();

// Yield a success stage to indicate completion.
yield stageSuccess({
title: 'Success!'
});
}
}

Providing Command Providers

Via @Component Providers

You can register a CommandProvider directly within a component's metadata. This is useful for providers specific to a particular component or page.

import { COMMAND_PALETTE_PROVIDERS } from '@glint/command-palette';

@Component({
providers: [
{
provide: COMMAND_PALETTE_PROVIDERS,
multi: true,
useValue: { service: MyCommandService },
}
]
})

For reusable providers or those used in plugins, the ExtensionModule is the preferred method. This allows for a modular, clean way to register providers.

import { ExtensionModule } from '@glint/extension';

@NgModule({
imports: [
ExtensionModule.forExtension({
commandProviders: [
{
service: MyCommandService
}
]
})
]
})
export class MyExtensionModule {}