Skip to content

Command Palette — vyuh_command_palette

vyuh_command_palette is the Vyuh command palette package. It provides a plugin, global launch shortcut, dialog, tabbed result list, and a pluggable search-provider contract.

dart
import 'package:vyuh_command_palette/vyuh_command_palette.dart';

CommandPalettePlugin

Register the plugin with the Vyuh platform, optionally passing a CommandPaletteConfig.

dart
CommandPalettePlugin(
  config: CommandPaletteConfig(
    canOpen: () => session.isSignedIn,
  ),
)

The plugin:

  • Installs a global hardware-key handler on init.
  • Opens or toggles the dialog when the launch shortcut matches.
  • Owns registered SearchProviders.
  • Dispatches searches to providers in registration order.
  • Clears providers on dispose.

The default launch shortcut is PlatformLaunchShortcut: Cmd+K on macOS and Ctrl+K elsewhere. The default tab-cycle shortcut inside the dialog is plain Tab.

Register Providers

Providers return one or more SearchTabs for each query. Queries are sent on every debounced keystroke, including an empty string for the idle browse state.

dart
final provider = NavigationSearchProvider(tabName: 'App')
  ..addItem(
    title: 'Areas',
    subtitle: 'Master data',
    icon: FluentIcons.building_factory_24_regular,
    searchTerms: const ['production', 'site'],
    canAccess: () => permissions.canReadAreas(),
    onSelected: (context) => context.go('/areas'),
  );

vyuh.commandPalette?.registerSearchProvider(provider);

NavigationSearchProvider is dependency-free by default: it uses simple substring matching. Apps can inject a NavigationMatcher for fuzzy matching when another package already provides that dependency.

Provider Contract

dart
class LotSearchProvider implements SearchProvider {
  @override
  Future<List<SearchTab>> search(String query) async {
    final lots = await api.searchLots(query);
    return [
      SearchTab(
        name: 'Lots',
        items: [
          for (final lot in lots)
            PaletteItem(
              title: lot.code,
              subtitle: lot.productName,
              icon: FluentIcons.box_24_regular,
              onSelected: (context) => context.go('/lots/${lot.id}'),
              metadata: {'lotId': lot.id},
            ),
        ],
      ),
    ];
  }
}

Provider failures should return const [] and log internally. The plugin also catches provider errors and treats that provider as empty for the query, so one failing provider does not break the palette.

Public Types

TypeUse
CommandPalettePluginPlugin lifecycle, provider registry, and show(context)
CommandPaletteConfigLaunch shortcut, tab-cycle shortcut, and canOpen gate
PlatformLaunchShortcutCmd+K / Ctrl+K platform activator
SearchProviderAsync provider interface
SearchTabNamed result tab returned by a provider
PaletteItemSelectable result row with title, subtitle, icon, action, metadata
NavigationSearchProviderBuilt-in provider for route/navigation entries
ShowCommandPaletteAction / ShowCommandPaletteIntentActions integration for widget-tree launchers
CommandPaletteDialogDialog widget used by the action/plugin

Open Programmatically

For button-triggered launch, call show(context) on the registered plugin or invoke the action directly.

dart
Button.icon(
  icon: FluentIcons.search_24_regular,
  tooltip: 'Command palette',
  onPressed: () async => vyuh.commandPalette?.show(context),
)

CommandPaletteConfig.canOpen is checked on both the global-key path and the widget-tree Actions.invoke path, so auth/session gates remain consistent.