Command palette

A commercial license is required to use Tailwind Plus Elements.

The <el-command-palette> component provides a fast, keyboard-friendly way for users to search and select from a predefined list of options. It's typically displayed inside a dialog — often triggered with a Cmd+K shortcut — making it ideal for building power-user features like global searches.

Component API

<el-command-palette>

The main command component that manages filtering and coordinates with its child components

Attributes
nameThe form field name for the command when used in forms.
valueThe selected value of the command. Can be read and set programmatically.
Events
changeDispatched when the active item changes. Detail contains relatedTarget property with the active item or null.
Methods
setFilterCallback(cb)Allows you to customize the filtering behavior of the command. The callback receives an object with query, node and content properties, and should return a boolean.
reset()Resets the command to its initial state.

<el-command-list>

Contains all the command items and groups. All focusable children will be considered options.

<el-defaults>

Optional container for suggestion items that are shown when the input is empty.

<el-command-group>

Groups related command items together.

<el-no-results>

Optional element shown when no items match the current query.

<el-command-preview>

Optional preview content shown when a specific item is active.

Attributes
forThe id of the item this preview content is associated with.

Examples

Basic example

Use the <el-command-palette>, <el-command-list>,<el-no-results> components, along with a native <button> and <input>, to build a command palette:

<button command="show-modal" commandfor="my-command-palette" type="button">
  Open command palette
</button>

<el-dialog>
  <dialog id="my-command-palette">
    <el-command-palette>
      <input autofocus placeholder="Search users…" />

      <el-command-list>
        <a href="/users/1" hidden>Michael Foster</a>
        <a href="/users/2" hidden>Dries Vincent</a>
        <a href="/users/3" hidden>Lindsay Walton</a>
        <a href="/users/4" hidden>Courtney Henry</a>
        <a href="/users/5" hidden>Tom Cook</a>
      </el-command-list>

      <el-no-results hidden>No users found.</el-no-results>
    </el-command-palette>
  </dialog>
</el-dialog>

Opening and closing

Typically the <el-command-palette> element is conditionally shown by rendering it within a dialog. See the Dialog documentation for information on how to open and close dialogs.

Using with buttons

When using a <button> as a command item, the onclick event will be invoked when it's selected:

<el-command-list>
  <button onclick="createProject()" type="button" hidden>Create project</button>
  <button onclick="createTask()" type="button" hidden>Create task</button>
  <button onclick="createUser()" type="button" hidden>Create user</button>
</el-command-list>

When using an <a> as a command item, the href attribute will be used to navigate to the link when it's selected:

<el-command-list>
  <a href="/users/1" hidden>Michael Foster</a>
  <a href="/users/2" hidden>Dries Vincent</a>
  <a href="/users/3" hidden>Lindsay Walton</a>
</el-command-list>

Showing option previews

Use the <el-command-preview> component to show a preview of the active option by connecting it using the for and id attributes:

<el-command-palette>
  <input autofocus placeholder="Search users…" />

  <el-command-list>
    <a id="user-1" href="/users/1" hidden>Michael Foster</a>
    <a id="user-2" href="/users/2" hidden>Dries Vincent</a>
    <a id="user-3" href="/users/3" hidden>Lindsay Walton</a>
    <a id="user-4" href="/users/4" hidden>Courtney Henry</a>
    <a id="user-5" href="/users/5" hidden>Tom Cook</a>
  </el-command-list>

  <el-command-preview for="user-1" hidden>
    <dl>
      <dt>Name</dt>
      <dd>Michael Foster</dd>
      <dt>Email</dt>
      <dd><a href="mailto:michael.foster@example.com">michael.foster@example.com</a></dd>
      <dt>Role</dt>
      <dd>Product Designer</dd>
    </dl>
  </el-command-preview>

  <el-command-preview for="user-2" hidden>
    <dl>
      <dt>Name</dt>
      <dd>Dries Vincent</dd>
      <dt>Email</dt>
      <dd><a href="mailto:dries.vincent@example.com">dries.vincent@example.com</a></dd>
      <dt>Role</dt>
      <dd>Software Engineer</dd>
    </dl>
  </el-command-preview>

  <!-- ... -->

  <el-no-results hidden>No users found.</el-no-results>
</el-command-palette>

Showing default commands

Use the <el-defaults> component to show a list of default commands when the search input is empty:

<el-command-list>
  <el-defaults>
    <button onclick="createProject()" type="button">Create project</button>
    <button onclick="createTask()" type="button">Create task</button>
    <button onclick="createUser()" type="button">Create user</button>
  </el-defaults>

  <!-- ... -->
</el-command-list>

Handling no results

Use the <el-no-results> component to show a message when no results are found:

<el-command-palette>
  <el-command-list>
    <!-- ... -->
  </el-command-list>

  <el-no-results hidden>No results found.</el-no-results>
</el-command-palette>

Use the <el-command-group> component to group related commands together:

<el-command-list>
  <el-command-group aria-labelledby="clients-group-label" hidden>
    <div id="clients-group-label">Clients</div>
    <a href="/clients/1">Workflow Inc.</a>
    <a href="/clients/2">Conglomerate Inc.</a>
    <a href="/clients/3">Big Ltd.</a>
  </el-command-group>

  <el-command-group aria-labelledby="projects-group-label" hidden>
    <div id="projects-group-label">Projects</div>
    <a href="/projects/1">Website redesign</a>
    <a href="/projects/2">New iOS app</a>
    <a href="/projects/3">New Android app</a>
  </el-command-group>
</el-command-list>

Customizing the filter logic

Use the setFilterCallback() method on the <el-command-palette> component to customize the filtering behavior:

<script type="module">
  function onReady() {
    let command = document.getElementById('my-command-palette')

    command.setFilterCallback(({ query, node, content }) => {
      if (query.startsWith('>')) {
        return node.dataset.type === 'client' && content.toLowerCase().includes(query.slice(1).toLowerCase())
      }
      if (query.startsWith('#')) {
        return node.dataset.type === 'project' && content.toLowerCase().includes(query.slice(1).toLowerCase())
      }
      return content.toLowerCase().includes(query.toLowerCase())
    })
  }

  if (customElements.get('el-command')) {
    onReady()
  } else {
    window.addEventListener('elements:ready', onReady)
  }
</script>

<el-command-palette id="my-command-palette">
  <input autofocus placeholder="Search users…" />
  <el-command-list>
    <el-command-group aria-labelledby="clients-group-label" hidden>
      <div id="clients-group-label">Clients</div>
      <a href="/clients/1" data-type="client">Workflow Inc.</a>
      <a href="/clients/2" data-type="client">Conglomerate Inc.</a>
      <a href="/clients/3" data-type="client">Big Ltd.</a>
    </el-command-group>

    <el-command-group aria-labelledby="projects-group-label" hidden>
      <div id="projects-group-label">Projects</div>
      <a href="/projects/1" data-type="project">Website redesign</a>
      <a href="/projects/2" data-type="project">New iOS app</a>
      <a href="/projects/3" data-type="project">New Android app</a>
    </el-command-group>
  </el-command-list>
</el-command-palette>

Additionally, you can also perform the filtering yourself by only rendering the options you want — for example maybe you're filtering the results server-side. In this case, you can completely disable the built-in filtering by updating the setFilterCallback() method to always return true:

command.setFilterCallback(() => true)