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:::
- 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
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 itsheading, 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
opensand 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 asaria-keyshortcutswhile it carries one, beside anaria-keyshortcutsof your own.
Props
The props of <x-wirekit:: and the opens prop of
<x-wirekit:: are listed with the others on the
Command Palette page.