Version v3 Documentation
Keyboard Shortcut Service
Global keyboard shortcut management for application-wide hotkeys. Register, suspend, and unregister shortcuts with automatic input element detection and cross-platform modifier support.
Basic Usage
RegisterAsync. The returned IDisposable handle lets you unregister the shortcut when no longer needed._shortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+K", async () =>
{
// Handle shortcut
await Task.CompletedTask;
});Multiple Shortcuts
Ctrl, Shift, Alt, and Meta. Try pressing them!// Ctrl shortcuts
_saveShortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+S", HandleSave);
_saveAsShortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+Shift+S", HandleSaveAs);
_newShortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+N", HandleNew);
// Alt shortcut
_altShortcut = await KeyboardShortcutService.RegisterAsync("Alt+Q", HandleQuickActions);
// Meta (Windows key) shortcut
_metaShortcut = await KeyboardShortcutService.RegisterAsync("Meta+M", HandleSystemMenu);
// Don't forget to dispose
public void Dispose()
{
_saveShortcut?.Dispose();
_saveAsShortcut?.Dispose();
_newShortcut?.Dispose();
_altShortcut?.Dispose();
_metaShortcut?.Dispose();
}Suspend During Dialog
Suspend and Resume to temporarily disable all shortcuts while a dialog or modal is open, preventing conflicts with dialog-specific interactions.// Suspend shortcuts when opening a dialog
private void OpenDialog()
{
_dialogOpen = true;
KeyboardShortcutService.Suspend();
}
private void CloseDialog()
{
_dialogOpen = false;
KeyboardShortcutService.Resume();
}
// Handle dialog dismissed via click-outside or Escape
private void OnDialogOpenChanged(bool isOpen)
{
_dialogOpen = isOpen;
if (!isOpen)
{
KeyboardShortcutService.Resume();
}
}Conditional Shortcuts
private bool _editMode;
private IDisposable? _conditionalShortcut;
private async Task OnEditModeChanged(bool enabled)
{
_editMode = enabled;
if (enabled)
{
// Register shortcut when entering edit mode
_conditionalShortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+D", async () =>
{
await DuplicateItem();
});
}
else
{
// Unregister when leaving edit mode
_conditionalShortcut?.Dispose();
_conditionalShortcut = null;
}
}
public void Dispose()
{
_conditionalShortcut?.Dispose();
}Installation
dotnet add package BlazorBlueprint.PrimitivesSetup
The service is automatically registered when you add BlazorBlueprint services in Program.cs.
builder.Services.AddBlazorBlueprintPrimitives();Usage
@using BlazorBlueprint.Primitives.Services
@inject IKeyboardShortcutService KeyboardShortcutService@inject IKeyboardShortcutService KeyboardShortcutService
@implements IDisposable
<p>Press Ctrl+K to trigger the shortcut</p>
@code {
private IDisposable? _shortcut;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_shortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+K", async () =>
{
Console.WriteLine("Shortcut triggered!");
await Task.CompletedTask;
});
}
}
public void Dispose()
{
_shortcut?.Dispose();
}
}Shortcut String Format
Shortcuts are defined as strings with modifiers and a key separated by +.
Supported Modifiers
Ctrl/Control
Also: Cmd, Command
Shift
Shift key
Alt
Also: Option, Opt
Meta
Also: Win, Windows
Supported Special Keys
The following special keys are supported and can be used with or without modifiers. Aliases are accepted during parsing and normalized automatically.
| Key | Aliases | Example |
|---|---|---|
Escape |
Esc | "Escape" |
Enter |
Return | "Ctrl+Enter" |
Space |
Spacebar | "Ctrl+Space" |
Tab |
— | "Ctrl+Tab" |
Backspace |
Back | "Ctrl+Backspace" |
Delete |
Del | "Shift+Delete" |
Insert |
Ins | "Shift+Insert" |
Home |
— | "Ctrl+Home" |
End |
— | "Ctrl+End" |
PageUp |
PgUp | "PageUp" |
PageDown |
PgDn | "PageDown" |
ArrowUp |
Up | "Alt+ArrowUp" |
ArrowDown |
Down | "Alt+ArrowDown" |
ArrowLeft |
Left | "Ctrl+ArrowLeft" |
ArrowRight |
Right | "Ctrl+ArrowRight" |
F1–F12 |
— | "F1", "Ctrl+F5" |
Examples
// Simple shortcuts
"Ctrl+S" // Save
"Ctrl+Z" // Undo
"Delete" // Delete key only
// With Shift
"Ctrl+Shift+S" // Save As
"Ctrl+Shift+Z" // Redo
// With Alt
"Alt+F4" // Close (careful - browser may intercept)
"Ctrl+Alt+T" // Custom action
// Function keys
"F1" // Help
"Ctrl+F5" // Force refresh
// Special keys
"Escape" // Escape key
"Enter" // Enter key
"Space" // Spacebar
// Arrow keys
"Alt+ArrowUp" // Move up
"Alt+Down" // "Down" is an alias for "ArrowDown"
// Navigation keys
"Ctrl+Home" // Go to start
"Ctrl+End" // Go to end
"PageUp" // Page up
"PgDn" // "PgDn" is an alias for "PageDown"Behavior
Input Element Skipping
Shortcuts are automatically disabled when the user is typing in form elements. This prevents shortcuts from interfering with text input. The following elements are skipped:
<input>— all input types (text, number, email, etc.)<textarea>— multiline text areas<select>— dropdown selectscontenteditable— any element with contenteditable attribute
Cross-Platform Modifier Keys
Ctrl and Meta (Cmd on macOS) are treated as equivalent. A shortcut registered as "Ctrl+S" will fire when the user presses Ctrl+S on Windows/Linux or Cmd+S on macOS. You don't need to register both.
Default Action Prevention
When a registered shortcut is triggered, the browser's default action for that key combination is automatically prevented. For example, registering "Ctrl+S" will prevent the browser's "Save Page" dialog from appearing.
API Reference
IKeyboardShortcutService Methods
Registration
| Property | Type | Default | Description |
|---|---|---|---|
| RegisterAsync(string, Func<Task>) | Task<IDisposable> | - | Register a shortcut with auto-generated ID. Returns a disposable handle to unregister. |
| RegisterAsync(string, Func<Task>, string) | Task<IDisposable> | - | Register a shortcut with a specific ID for later unregistration via Unregister(). |
| Unregister(string) | void | - | Unregister a shortcut by its ID. Prefer disposing the handle returned by RegisterAsync instead. |
Lifecycle
| Property | Type | Default | Description |
|---|---|---|---|
| Suspend() | void | - | Suspend all shortcut handling globally (e.g., while a dialog is open). |
| Resume() | void | - | Resume shortcut handling after suspension. |
Properties
State
| Property | Type | Default | Description |
|---|---|---|---|
| IsSuspended | bool | false | Whether shortcut handling is currently suspended. |
Best Practices
Register in OnAfterRenderAsync
Always register shortcuts in OnAfterRenderAsync with the firstRender guard. The service relies on JavaScript interop, which is only available after the component has rendered.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_shortcut = await KeyboardShortcutService.RegisterAsync("Ctrl+K", HandleShortcut);
}
}Always Dispose Registrations
Implement IDisposable and dispose all shortcut handles when the component is destroyed. Failing to dispose will leave stale shortcuts registered that reference a destroyed component.
@implements IDisposable
@code {
private IDisposable? _shortcut1;
private IDisposable? _shortcut2;
public void Dispose()
{
_shortcut1?.Dispose();
_shortcut2?.Dispose();
}
}Suspend During Modals
Call Suspend() when opening dialogs, sheets, or drawers that have their own keyboard interactions. Remember to Resume() when they close — including when the user dismisses them by clicking outside or pressing Escape.
Avoid Reserved Browser Shortcuts
Some keyboard shortcuts are reserved by browsers and cannot be intercepted. While preventDefault works for most combinations, the following are typically blocked at the browser/OS level:
Browser Shortcut Conflicts
Some keyboard shortcuts are reserved by browsers and cannot be overridden. Avoid using:
- Ctrl+T - New tab
- Ctrl+W - Close tab
- Ctrl+N - New window (in some browsers)
- Ctrl+Tab - Switch tabs
- F5 / Ctrl+R - Refresh
- F11 - Fullscreen
- F12 - Developer tools