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 togenerateArguments()andexecute().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 },
}
]
})
Via ExtensionModule (Recommended for Plugins)
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 {}