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 {}