--- templateEngineOverride: njk layout: layouts/page.njk title: Command description: Command menu for search and quick actions. toc: - label: About id: about - label: Usage id: usage children: - label: HTML + JavaScript id: usage-html-js children: - label: "Step 1: Include the JavaScript files" id: usage-html-js-1 - label: "Step 2: Add your command HTML" id: usage-html-js-2 - label: HTML structure id: usage-html-js-3 - label: JavaScript API id: usage-html-js-4 - label: Jinja and Nunjucks id: usage-macro - label: Examples id: examples children: - label: Basic id: example-basic - label: Shortcuts id: example-shortcuts - label: Groups id: example-groups - label: Scrollable id: example-scrollable - label: RTL id: example-rtl - label: API Reference id: api-reference --- {% from "macros/code_preview.njk" import code_preview %} {% from "macros/code_block.njk" import code_block %} {% from "command.njk" import command, command_dialog %} {% macro command_items(suggestions_id="suggestions", settings_id="settings", shortcuts=false) %}
Suggestions
{% lucide "calendar" %} Calendar {% if shortcuts %}⌘K{% endif %}
{% lucide "smile" %} Search Emoji {% if shortcuts %}⌘E{% endif %}
{% lucide "calculator" %} Calculator

Settings
{% lucide "user" %} Profile {% if shortcuts %}⌘P{% endif %}
{% lucide "credit-card" %} Billing {% if shortcuts %}⌘B{% endif %}
{% lucide "settings" %} Settings {% if shortcuts %}⌘S{% endif %}
{% endmacro %} {% set code_standalone %} {% call command(id="demo-command-standalone", main_attrs={ "class": "border" }) %} {{ command_items("suggestions", "settings") }} {% endcall %} {% endset %} {{ code_preview("command-standalone", code_standalone | prettyHtml, class="w-full max-w-sm") }}

About

shadcn/ui's Command component is built on cmdk. Basecoat implements the same command-menu pattern with vanilla HTML, CSS, and a small JavaScript controller for filtering, active item navigation, and dialog closing.

Usage

HTML + JavaScript

Step 1: Include the JavaScript files

You can either include the JavaScript file for all the components, or just the one for this component by adding this to the <head> of your page:

{% set code_script %} {% endset %} {{ code_block(code_script | prettyHtml, "html") }}
Components with JavaScript {% lucide "arrow-right" %} Use the CLI {% lucide "arrow-right" %} command.js {% lucide "arrow-right" %}

Step 2: Add your command HTML

{{ code_block(code_standalone | prettyHtml, "html") }}

Use <dialog class="command-dialog"> for the command palette variant.

{% set code_dialog_usage %}
{% endset %} {{ code_block(code_dialog_usage | prettyHtml, "html") }}

HTML structure

The command menu can be used standalone or inside a native dialog. The structure is:

<dialog class="command-dialog"> Optional
Dialog variant. Wraps one <div class="command">. Add aria-label or aria-labelledby for an accessible name.
<div class="command">
Root command menu. Can also be used standalone without the dialog wrapper. Add data-filter="manual" when your app owns filtering, such as remote search or a local Lunr index.
<header>
Search input wrapper. The macro includes a search icon and input.
<input type="text" role="combobox">
Filter input. Use aria-expanded="true" and aria-controls="{ MENU_ID }" to point to the command list.
<div role="menu" id="{ MENU_ID }">
Command list. Set data-empty to customize the empty state.
<div role="group" aria-labelledby="{ HEADING_ID }"> Optional
Groups related command items. Hidden automatically when every item in the group is filtered out.
<span role="heading" id="{ HEADING_ID }"> Optional
Group heading. Use an id when the parent group uses aria-labelledby.
<div role="menuitem"> or <a role="menuitem">
Selectable command item. Use <a> for navigation and <div> for actions. Supports data-filter, data-keywords, data-force, data-keep-command-open, and aria-disabled="true".
<span data-shortcut> Optional
Shortcut hint aligned to the inline end of the item.
<span data-indicator> Optional
Item indicator. It becomes visible with data-checked="true" or aria-selected="true".
<hr role="separator"> Optional
Separator between groups/items. Hidden while filtering.

JavaScript API

basecoat:initialized
Once the component is initialized, it dispatches a custom non-bubbling basecoat:initialized event on itself.
command.refresh()
Rescans command items after changing children inside the existing role="menu" list.
data-filter="manual"
Disables Basecoat's built-in text filtering. Update the menu items yourself, then call command.refresh().
window.basecoat.refresh(command)
Calls the component refresh method through the global dispatcher.

Jinja and Nunjucks

You can use the command() or command_dialog() Nunjucks or Jinja macros for this component.

Use Nunjucks or Jinja macros {% lucide "arrow-right" %} Jinja macro {% lucide "arrow-right" %} Nunjucks macro {% lucide "arrow-right" %}
{% set raw_code %}{% raw %}{% call command() %}
... Calendar
... Settings
{% endcall %}{% endraw %}{% endset %} {{ code_block(raw_code, "jinja") }}

Examples

Basic

A simple command menu in a dialog. The button also shows the keyboard shortcut used in this example.

{% set code_basic %} {% call command_dialog(id="command-basic") %} {{ command_items("command-basic-suggestions", "command-basic-settings") }} {% endcall %} {% endset %} {{ code_preview("command-basic", code_basic | prettyHtml) }}

Shortcuts

{% set code_shortcuts %} {% call command(id="command-shortcuts", main_attrs={ "class": "border" }) %} {{ command_items("command-shortcuts-suggestions", "command-shortcuts-settings", true) }} {% endcall %} {% endset %} {{ code_preview("command-shortcuts", code_shortcuts | prettyHtml, class="w-full max-w-sm") }}

Groups

{% set code_groups %} {% call command(id="command-groups", main_attrs={ "class": "border" }) %} {{ command_items("command-groups-suggestions", "command-groups-settings") }} {% endcall %} {% endset %} {{ code_preview("command-groups", code_groups | prettyHtml, class="w-full max-w-sm") }}

Scrollable

{% set code_scrollable %} {% call command(id="command-scrollable", main_attrs={ "class": "border" }) %}
Pages {% for i in range(0, 18) %}
{% lucide "file" %} Page {{ i + 1 }}
{% endfor %}
{% endcall %} {% endset %} {{ code_preview("command-scrollable", code_scrollable | prettyHtml, class="w-full max-w-sm") }}

RTL

Command supports document direction. Set dir="rtl" on the command root or a parent element.

{% set code_rtl %}
{% call command(id="command-rtl", placeholder="اكتب أمراً أو ابحث...", main_attrs={ "class": "border" }) %}
اقتراحات
{% lucide "calendar" %} التقويم ⌘K
{% lucide "settings" %} الإعدادات ⌘S
{% endcall %}
{% endset %} {{ code_preview("command-rtl", code_rtl | prettyHtml, class="w-full max-w-sm") }}

API Reference

.command
Root command menu.
.command-dialog
Native dialog variant. Closes automatically when an item is clicked unless that item has data-keep-command-open.
data-filter
Overrides item text used by the filter.
data-keywords
Additional whitespace- or comma-separated search terms.
data-force
Always keeps an item visible while filtering.
data-empty
Custom empty-state text on the menu element.