Autocomplete
A free-text input that filters a list of suggestions. The committed value is the text you type; selecting a suggestion fills it in.
Value:
<NaviusAutocomplete Items="_frameworks" @bind-Value="_value" TItem="string">
<ItemTemplate Context="framework">
<NaviusAutocompleteItem class="... data-[highlighted]:bg-accent data-[selected]:font-medium">
@framework
</NaviusAutocompleteItem>
</ItemTemplate>
<ChildContent>
<NaviusAutocompleteInput Placeholder="Search framework…" aria-label="Framework" class="..." />
<NaviusAutocompletePortal>
<NaviusAutocompletePositioner Side="bottom" Align="start" SideOffset="4">
<NaviusAutocompletePopup class="... bg-popover shadow-md
data-[open]:animate-in data-[closed]:animate-out">
<NaviusAutocompleteList class="outline-none" />
<NaviusAutocompleteEmpty class="...">No frameworks found.</NaviusAutocompleteEmpty>
</NaviusAutocompletePopup>
</NaviusAutocompletePositioner>
</NaviusAutocompletePortal>
</ChildContent>
</NaviusAutocomplete>
@code {
private string? _value;
private static readonly string[] _frameworks =
{
"Next.js", "SvelteKit", "Nuxt.js", "Remix",
"Astro", "Blazor", "SolidStart", "Qwik City",
};
}Features
- A compound of composable parts (Root, Input, Portal, Positioner, Popup, List, Item, Empty) you assemble and style yourself.
- Live, case-insensitive filtering with a pluggable
Filterand genericItems<T>. - Focus stays in the input; the highlight moves via
aria-activedescendant; arrows never steal focus. - Can be controlled (
@bind-Value,@bind-Open) or uncontrolled (DefaultOpen). - The Popup self-portals to
document.body, stays anchored, and flips when space is tight. - Styles off the discrete contract:
data-open/data-closedon the Popup,data-highlighted/data-selectedon items.
Installation
Reference the Navius.Primitives package for the headless primitive, or vendor a styled version with the CLI: navius add copies the styled zits/ui component plus the brain files it depends on.
navius add autocompleteAnatomy
Import the parts and assemble them. The List renders the filtered Items through your ItemTemplate.
@using Navius.Primitives.Components.Autocomplete
<NaviusAutocomplete Items="_options" @bind-Value="_value" TItem="string">
<ItemTemplate Context="item">
<NaviusAutocompleteItem>@item</NaviusAutocompleteItem>
</ItemTemplate>
<ChildContent>
<NaviusAutocompleteInput />
<NaviusAutocompletePortal>
<NaviusAutocompletePositioner>
<NaviusAutocompletePopup>
<NaviusAutocompleteList />
<NaviusAutocompleteEmpty />
</NaviusAutocompletePopup>
</NaviusAutocompletePositioner>
</NaviusAutocompletePortal>
</ChildContent>
</NaviusAutocomplete>API Reference
Root
Owns the filtered collection, the open state and the committed value. Cascades the Autocomplete context. Renders no DOM of its own.
| Prop | Type | Default |
|---|---|---|
| Items | IReadOnlyList<TItem> | [] |
| Value | string? | - |
| ValueChanged | EventCallback<string?> | - |
| Open | bool | false |
| OpenChanged | EventCallback<bool> | - |
| DefaultOpen | bool | false |
| ItemToString | Func<TItem, string>? | - |
| Filter | Func<TItem, string, bool>? | - |
| ItemTemplate | RenderFragment<TItem>? | - |
| Dir | string? | - |
| ChildContent | RenderFragment? | - |
Input
The editable text field (role=combobox). Typing filters the list and updates the value. Renders an input.
| Prop | Type | Default |
|---|---|---|
| Placeholder | string? | - |
| Attributes | IDictionary<string, object>? | - |
Positioner
Owns placement (side / align / offsets / collision). A flag-setter; the Popup renders the positioning element the engine anchors and writes data-side / data-align + --anchor-* onto.
| Prop | Type | Default |
|---|---|---|
| Side | string | "bottom" |
| Align | string | "start" |
| SideOffset | double | 0 |
| AlignOffset | double | 0 |
| Flip | bool | true |
| AvoidCollisions | bool | true |
| ChildContent | RenderFragment? | - |
Popup
The floating listbox surface, self-portaled and anchored to the input. role=listbox.
| Prop | Type | Default |
|---|---|---|
| ChildContent | RenderFragment? | - |
| Attributes | IDictionary<string, object>? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-open] | Present while the popup is open. |
| [data-closed] | Present while the popup is closed (during the exit transition). |
| [data-starting-style] | Present on the first committed open frame. |
| [data-ending-style] | Present while the popup is animating out. |
| [data-side] | "top" | "right" | "bottom" | "left" |
| [data-align] | "start" | "center" | "end" |
List
Renders one Item per filtered entry using the Root's ItemTemplate. Renders a div.
| Prop | Type | Default |
|---|---|---|
| Attributes | IDictionary<string, object>? | - |
Item
A single suggestion. Highlighted by keyboard/pointer; selecting it commits its value. Renders a div with role=option.
| Prop | Type | Default |
|---|---|---|
| ChildContent | RenderFragment? | - |
| Attributes | IDictionary<string, object>? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-highlighted] | Present when the item is the active (aria-activedescendant) option. |
| [data-selected] | Present when the item matches the committed value. |
Empty
Shown inside the Popup when the filter matches nothing. Renders a div.
| Prop | Type | Default |
|---|---|---|
| ChildContent | RenderFragment? | - |
Accessibility
Implements the combobox WAI-ARIA APG pattern (editable, list-autocomplete): the highlighted option is tracked with aria-activedescendant so DOM focus never leaves the input. This behavior is covered by the browser test suite and an axe-core WCAG gate in CI.
The Input renders role="combobox" but ships without an accessible name. Pair it with a NaviusLabel or supply an aria-label; a placeholder is not an accessible name.
Keyboard interactions
| Key | Description |
|---|---|
| ArrowDown | Opens the list if closed; otherwise moves the highlight to the next option. |
| ArrowUp | Moves the highlight to the previous option. |
| Enter | Selects the highlighted option and closes the list. |
| Escape | Closes the list, keeping focus in the input. |
| Tab | Closes the list and moves focus to the next element. |