Overlays

AppCommandPalette

Search and jump: press Ctrl+K, type, and go anywhere in the app.

<app-command-palette id="jump"><app-command-group label="Pages"><app-command-item label="Dashboard" href="/" /></app-command-group></app-command-palette>

<app-command-palette> is app-wide search and jump. It opens near the top of the screen over a dimmed page, takes a search, and lists the matching links in groups. Arrow keys move through every group, Enter opens the highlighted link, and Escape closes it.

The dialog is the same themed Bootstrap modal <app-modal> renders, so open it the same ways: data-bs-toggle="modal" data-bs-target="#id" on a trigger, or WUI.modal.open('id') from your own shortcut. The list behaviour is the shared <wui-command-palette> element, the same one the React <AppCommandPalette> uses. On Razor it also filters the items you rendered as the user types, and choosing one goes to its href.

Playground

Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the palette. Open it and type to see the filter.

<app-command-palette id="pgPalette">…</app-command-palette>

Search and jump

Compose with <app-command-group> children, each holding <app-command-item> links. Every item needs a label and an href; icon, description and meta are optional. Groups render in order, and a group left with no match hides itself while you type.

Pages, actions and people
Type to narrow the list. The matching text in each label is bold.
Show code
<app-button data-bs-toggle="modal" data-bs-target="#jump">Search</app-button>

<app-command-palette id="jump">
    <app-command-group label="Pages">
        <app-command-item label="Dashboard" href="/" icon="house" meta="G D" />
        <app-command-item label="Projects" href="/projects" icon="folder" description="Every project you can see" />
    </app-command-group>
    <app-command-group label="Actions">
        <app-command-item label="New project" href="/projects/new" icon="plus" />
    </app-command-group>
</app-command-palette>
Every item is a linkRazor renders the whole list on the server and the element filters it in the page, so there is no loading state and no remote search. An item without href is an error when the page renders. For a search that calls your API as the user types, use the React AppCommandPalette.

Opening it

A trigger with data-bs-toggle="modal" data-bs-target="#id" opens it, as on this page. For Ctrl+K, call WUI.modal.open('id') from a key listener of your own; the palette returns focus to wherever the user was when it closes, and clears the search for next time.

Ctrl+K, with a footer of key hints
Press Ctrl + K (or Cmd + K on a Mac) anywhere on this page.
Show code
<script>
    document.addEventListener('keydown', function (e) {
        if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && !e.repeat && e.key.toLowerCase() === 'k') {
            e.preventDefault();
            WUI.modal.open('jump');
        }
    });
</script>
React has a hook for thisOn React, useCommandPaletteShortcut(onOpen) does the same job. Razor has no hooks, so the few lines above are the whole recipe.

Keyboard and pointer

Focus stays in the input the whole time. ArrowDown and ArrowUp move the highlighted result across every group and wrap at both ends; the highlighted result scrolls into view. Enter opens it. Hovering a result highlights it. Escape or a click on the dimmed page closes the palette, and focus goes back to where it was.

Screen readersThe input is a combobox that points at the listbox and at the highlighted result, so each arrow press is announced. Each group is labelled by its heading. The empty text sits in a status region, so it is read out when it appears.

When to use

Use it when

  • An app has more pages and actions than its navigation can show at once.
  • Regular users want to jump straight to a record or run an action from the keyboard.
  • The same search should reach pages, actions and records in one place.

Reach for something else when

  • You are picking a value for a form field. → app-autocomplete
  • You are filtering the list on the current page. → app-search
  • The palette would be the only way to reach a page. → app-shell

Every option

Each cell opens its own palette: highlight on and off, every item shape, the empty state and the footer. Razor has no loading state, because its list is rendered on the server.

highlight

highlight (default, true)
highlight="false"

item shapes

icon, description and meta
label only

empty state and footer

empty-text (default, "No results")
empty-text="Nothing matches that"
footer

Attributes

AttributeTypeDefaultDescription
id *string-The modal id a trigger or WUI.modal.open targets. Also seeds the result and heading ids.
placeholderstringSearch…Placeholder in the input.
empty-textstringNo resultsShown when the typed search matches no item.
aria-labelstringSearchAccessible name of the dialog and its input.
highlightbooltrueBold the typed search inside each item label, case-insensitively.
classstring-Extra classes on the modal shell, as on <app-modal>.

On <app-command-group>: label (the heading). On <app-command-item>: label, href (required), description, icon (a library icon name) and meta (short trailing text). <app-command-palette-footer> holds content under the list, such as key hints.