SearchPanel
An inline search card with a field, live results, and an empty state.
Usage
Live Filtering
Loading demo...
Best Practices
- Use
TxCommandPalettefor a globally invoked launcher and this panel for search that stays on the page; both share one keyboard contract. - As a launcher, run the action in
selectand clear the query; as a filter, keep the query visible. - For remote search, pass
:filter="items => items"to disable the built-in match and debounce your own fetch onqueryChange. - Put synonyms in
keywords, and mark unavailable entriesdisabledinstead of removing them fromitems. - Size
minHeightfor your most common result count; too small brings the jumping back.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | '' | Query text, bound with v-model. |
items | SearchPanelItem[] | [] | Candidate items. |
placeholder | string | 'Search' | Field placeholder. |
ariaLabel | string | - | Accessible name of the field; falls back to placeholder. |
idleCount | number | 5 | Items shown for an empty query; 0 shows all. |
emptyThreshold | number | 3 | Shortest query that may show the empty state. |
emptyTitle | string | 'No results found' | Empty-state title. |
emptyDescription | string | 'Adjust your search to try again' | Empty-state description. |
clearLabel | string | 'Clear search' | Accessible name of the clear button. |
listLabel | string | 'Search results' | Accessible name of the result list. |
minHeight | number | string | 248 | Reserved height, so results don't resize the panel. |
filter | (items, query) => items | - | Replaces the built-in match: case-insensitive includes over label and keywords. |
clearable | boolean | true | Shows the clear button. |
disabled | boolean | false | Disables the field. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | string | Fires when the query changes. |
queryChange | string | Same value as update:modelValue, for hosts without v-model. |
select | SearchPanelItem | Fires when a result is clicked or chosen with Enter. |
clear | - | Fires when the clear button or Escape empties the field. |
Slots
| Slot | Scope | Description |
|---|---|---|
item | { item, active, query } | Replaces a row's content. |
empty | { query } | Replaces the empty state. |
footer | - | Content below the list, inside the card. |
Exposed Methods
| Name | Description |
|---|---|
focus() / blur() | Focuses or blurs the field. |
clear() | Empties the query and emits clear. |
Types
| Name | Description |
|---|---|
SearchPanelItem | { id, label, keywords?, disabled? }; keywords join the built-in match but aren't displayed. |
Overview
- Renders inline: no overlay, no modal semantics, no focus trap — it fits in a page, sidebar, or popover.
- ↑ ↓ wrap and skip disabled rows, Home / End jump to the first and last enabled rows, Enter selects, and Escape clears when there is text. Enter is ignored during IME composition.
- Follows the combobox pattern: the field is
role="combobox"witharia-autocomplete="list",aria-controls, andaria-activedescendant; rows arerole="option"withtabindex="-1", so focus stays in the field. - The highlight is
is-active, and pointer movement syncs it to the row under the mouse. - Selecting a result doesn't write it back into the field; the host handles
select. - Below
emptyThresholdcharacters, a query with no matches doesn't show the empty state.
Technologies
- The empty state reuses
TxSearchEmpty, tuned only through its public CSS variables andiconslot. - Adapted from Beautiful UI, © 2026 Shane Levine, MIT; keyboard navigation and ARIA are additions.
- Source:
packages/tuffex/packages/components/src/search-panel/.
查看源码
packages/tuffex/packages/components/src/search-panel/index.ts