Skip to main content
Copy for LLM

Command Palette with Pages

A bulk action often needs one more choice: "Set status…" asks which status. An entry with opens shows that choice as a page of the same <x-wirekit::command-palette>:

  • the field empties, and what the reader types searches the page,
  • the values carry the digits 1 to 9, and a digit chooses one while the field is empty,
  • Backspace in the empty field, or Back above it, goes up a level, and Escape closes the palette.

Open the demo, choose "Set status…" and press a digit. Type to narrow a page, and press Backspace until you are back on the top level.

The Demo

An entry that opens a page of statuses

A page stands anywhere inside the palette, before or after the entries that open it, and an entry on a page can open another page: Back then walks the trail one level at a time. Choosing a value runs its action and closes the palette, as any entry does, and the next open starts on the top level.

What the Page Does

On a page
The field Empties when the page opens. The page's placeholder stands in it, the palette's own without one
Typing Narrows the page's entries by their text, without case and accents: entwurfe finds "Entwürfe". A group whose entries all drop out hides with them
1 – 9 Choose the entry that carries the digit, while the field is empty. The first nine entries that can be chosen carry one, a disabled entry none. With text in the field, a digit is part of the search
Backspace With text in the field, delete it. In the empty field, go back one level
Back The button above the field goes back one level. It shows only while a page is open
Escape Close the palette, from any level

The top level keeps its own rule: the palette never filters it, and your search answers it, as Server-Side Search describes.

Values From Your Server

A page with remote takes its values from your search, the way the top level does. The palette sends wirekit-command-palette-query with the page's name in detail.page as soon as the page opens, with an empty query, and again as the reader types; on the top level detail.page is null. Render the values into the page, and the palette shows them:

{{-- 1. One handler answers the top level and the remote page: `page` says which. --}}
<x-wirekit::command-palette name="bulk-actions" label="Bulk actions"
    x-on:wirekit-command-palette-query="$wire.search($event.detail.page, $event.detail.query)">
    <x-wirekit::command-palette.item opens="category">Assign category…</x-wirekit::command-palette.item>

    {{-- 2. `remote`: the component renders the page's values for its query. --}}
    <x-wirekit::command-palette.page name="category" heading="Assign category" remote>
        @foreach ($categories as $category)
            <x-wirekit::command-palette.item :id="'category-' . $category->id" wire:key="category-{{ $category->id }}" wire:click="assignCategory({{ $category->id }})">
                {{ $category->name }}
            </x-wirekit::command-palette.item>
        @endforeach
    </x-wirekit::command-palette.page>
</x-wirekit::command-palette>
// 3. The query of the category page narrows its values; the top level has none here.
public string $categorySearch = '';

public function search(?string $page, string $query): void
{
    if ($page === 'category') {
        $this->categorySearch = $query;
    }
}

// 4. Nine values at most, so each one carries a digit.
public function render()
{
    return view('livewire.product-list', [
        'categories' => Category::query()
            ->when($this->categorySearch !== '', fn ($query) => $query->where('name', 'like', '%'.$this->categorySearch.'%'))
            ->orderBy('name')
            ->limit(9)
            ->get(),
    ]);
}

A page your server answers shows its loading and error slots while you report the request through wirekit:command-palette-state, as Command Palette with a Remote Search shows. Its count is announced once you report the answer, or once its values arrive.

Events

Event Detail When
wirekit-command-palette-query query, page On every keystroke on the top level and on a remote page, debounced, and once when such a level opens. A page the palette filters sends none
wirekit:command-palette-page page, name When the reader opens a page or goes back from one. page is null on the top level, name the palette's own
wirekit:command-palette-submit query, page On Enter with nothing highlighted, on any level

Accessibility

  • A page is a role="group" inside the listbox, named by its heading, and only the open level is in the accessibility tree.
  • Each change of level is said through the palette's status region: the level's name and how many entries it holds, "Set status, 3 entries". The region is in the page before its first sentence, so a screen reader speaks it.
  • The field keeps the focus on every change of level, so the arrows, Enter and the digits stay where the reader is. Back is a button before the field, reached with Shift+Tab.
  • The chevron of an entry with opens and the digit beside a value are hidden from screen readers; the entry's text is its name. The digit is a key the palette binds, so the entry states it as aria-keyshortcuts while it carries one, beside an aria-keyshortcuts of your own.

Props

The props of <x-wirekit::command-palette.page> and the opens prop of <x-wirekit::command-palette.item> are listed with the others on the Command Palette page.

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store