Command

A command palette provides a searchable list of actions or items. Users type into a search input to filter and select commands via keyboard or mouse. This pattern is commonly used for quick-access command palettes (e.g., Ctrl+K interfaces), searchable menus, and action launchers.

The component renders a search region containing a text input and a listbox for results. The search value is bindable, allowing consumers to implement their own filtering logic and dynamically update the listbox content.

Example

Show demo markup
<div class="command" role="dialog" aria-label="Command palette"><input type="search" aria-label="Search commands" placeholder="Type a command..." /><ul role="listbox" aria-label="Commands"><li role="option" aria-selected="false">Open file</li><li role="option" aria-selected="false">Save</li></ul></div>
Usage example
<script lang="ts">
    import Command from "./Command.svelte";

    let q = $state("");
    const commands = [
        { id: "new", name: "New file" },
        { id: "open", name: "Open file" },
        { id: "save", name: "Save" }
    ];
    let filtered = $derived(
        commands.filter((c) => c.name.toLowerCase().includes(q.toLowerCase()))
    );
</script>

<Command label="Command palette" placeholder="Search commands..." bind:value={q}>
    {#each filtered as c (c.id)}
        <div role="option" tabindex="-1">{c.name}</div>
    {/each}
</Command>
Show Svelte source
// In your Svelte component:
import Command from "lily-design-system-svelte-headless/components/Command/Command.svelte";

<Command>
  <!-- content -->
</Command>

Usage

Application command palette triggered by Ctrl+K:

<Command label="Command palette" placeholder="Type a command..." value={query}>
    <div role="option" tabindex="-1" onclick={() => navigate('/dashboard')}>Go to Dashboard</div>
    <div role="option" tabindex="-1" onclick={() => navigate('/settings')}>Open Settings</div>
    <div role="option" tabindex="-1" onclick={() => toggleTheme()}>Toggle Dark Mode</div>
</Command>

Admin panel action launcher with dynamic filtering:

<Command label="Actions" placeholder="Search actions..." value={actionQuery}>
    {#each filteredActions as action}
        <div role="option" tabindex="-1" onclick={() => action.execute()}>
            {action.name} <kbd>{action.shortcut}</kbd>
        </div>
    {/each}
</Command>

Props

  • label: string (required) -- accessible name for both the search region and the input
  • placeholder: string (default: undefined) -- placeholder text for the search input
  • value: string (default: "", bindable) -- current search text, supports two-way binding via two-way value binding
  • children: slot (required) -- listbox content, typically option or command items
  • ...restProps: any additional HTML attributes spread onto the outer <div>

Keyboard Interactions

  • Tab: Moves focus into and out of the search input
  • Additional keyboard navigation (arrow keys within the listbox) should be implemented by the consumer

ARIA

  • role="search" -- identifies the outer container as a search landmark region
  • aria-label={label} -- provides accessible name for the search region and input
  • role="listbox" -- identifies the results container as a listbox for selectable options
  • aria-label={label} -- provides accessible name for the listbox

When to Use

  • Use Command for quick-access search interfaces such as Ctrl+K action launchers or searchable menus.
  • Use Command when users need to search and execute actions from a large set without navigating through menus.
  • Use Command for keyboard-driven navigation where users can jump to pages, run actions, or switch contexts.
  • Use Command in developer tools, admin panels, or productivity applications where power users expect a command palette.

When Not to Use

  • Do not use Command for site search or content search -- use SearchInput instead.
  • Do not use Command for form input with a dropdown list of options -- use Combobox instead.
  • Do not use Command for navigation menus that should always be visible -- use NavigationMenu instead.

Headless

This headless Command component provides a <div> with role="search" and aria-label, an <input type="search"> with autocomplete="off", and a <div> with role="listbox" for displaying results. The consumer provides all visual styling including modal/overlay presentation, result item layout, keyboard shortcut hints, grouping headers, and animations.

Styles

The consumer provides all CSS styling. The component renders with a .command class for targeting. No default styles are included — this is a fully headless component.

Testing

  • Verify the component renders a <div> element with class command
  • Verify role="search"` -- identifies the outer container as a search landmark region
  • Verify aria-label={label}` -- provides accessible name for the search region and input
  • Verify role="listbox"` -- identifies the results container as a listbox for selectable options
  • Verify aria-label={label}` -- provides accessible name for the listbox
  • Verify keyboard interactions work correctly
  • Verify pass-through attributes are applied

Advice

  • Designers: Present the command palette in a modal overlay centered on screen. Group related commands and show keyboard shortcut hints alongside each action.
  • Developers: Implement filtering logic by reacting to the bindable value prop. Add arrow key navigation for the listbox items in your consumer code. Pair with a Dialog for modal presentation.

Implementation Notes

  • Wraps content in a <div> with role="search" and aria-label for semantic search region
  • Contains an <input type="search"> with autocomplete="off" to prevent browser autocomplete interference
  • Contains a <div> with role="listbox" for displaying filtered results
  • Supports two-way binding on the value prop component
  • Children slot is rendered inside the listbox for consumer-controlled list items
  • Spreads restProps on the outer search container

Related components

  • combobox — a text input combined with a dropdown list for filtering options
  • menu — a list of actions or options triggered by a button
  • search-input — an input for entering a search query <input type="search">

References

  • WAI-ARIA Listbox Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/listbox/
  • WAI-ARIA Combobox Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/

Canonical contract

Generated from this component's canonical metadata — the machine-checked source the implementations are held to.

Metadata

  • Component: command
  • PascalCase: Command
  • Description: a command palette for searching and executing actions
  • Status: beta — implemented and unit-tested in all seven frameworks with an axe-clean demo page; not yet exercised in composed flows
  • HTML tag: <div>
  • CSS class: .command
  • Interactive: yes

ARIA

  • role="search" -- identifies the outer container as a search landmark region
  • aria-label={label} -- provides accessible name for the search region and input
  • role="listbox" -- identifies the results container as a listbox for selectable options
  • aria-label={label} -- provides accessible name for the listbox

Keyboard

  • **Tab**: Moves focus into and out of the search input
  • Additional keyboard navigation (arrow keys within the listbox) should be implemented by the consumer

Props

  • label: string (required) -- accessible name for both the search region and the input
  • placeholder: string (default: undefined) -- placeholder text for the search input
  • value: string (default: "", bindable) -- current search text, supports two-way binding via two-way value binding
  • children: slot (required) -- listbox content, typically option or command items
  • ...restProps: any additional HTML attributes spread onto the outer <div>