SearchField
A search field is a TextField with the search behaviours built in: a clear button that appears when there is something to clear, Esc to empty it, and a type="search" control so the browser offers the right keyboard and history.
import {
Label,
SearchField,
SearchFieldClearButton,
SearchFieldGroup,
SearchFieldInput,
SearchFieldSearchIcon,
} from "ropav";<SearchField default-value="oklch">
<Label>Search</Label>
<SearchFieldGroup>
<SearchFieldSearchIcon />
<SearchFieldInput class="w-64" placeholder="Search…" />
<SearchFieldClearButton />
</SearchFieldGroup>
</SearchField>SearchFieldGroup is the bordered box; the icon, the input and the clear button sit inside it in whatever order you put them.
search-field-clearable.vue
<script setup lang="ts">
import {
Label,
SearchField,
SearchFieldClearButton,
SearchFieldGroup,
SearchFieldInput,
SearchFieldSearchIcon,
} from "ropav";
</script>
<template>
<SearchField default-value="oklch" name="search">
<Label>Search the docs</Label>
<SearchFieldGroup>
<SearchFieldSearchIcon />
<SearchFieldInput class="field" placeholder="Search…" />
<SearchFieldClearButton />
</SearchFieldGroup>
</SearchField>
</template>
<style scoped>
.field {
width: calc(var(--rp-spacing) * 72);
}
</style>Searching as you type, or on submit
The field emits change for every keystroke and submit when Enter is pressed. Which one you listen to is the difference between a filter and a search: a filter narrows a list that is already on screen, a search goes and fetches something.
Validation works as it does on any field — is-required, validate, and is-invalid taking the field over when it is set either way.
Accessibility
- Esc clears the field. That is a real convenience and also a small hazard: a reader who presses it expecting to close something loses what they typed instead, so do not put a search field inside a dialog that Escape should close.
- The clear button names itself and only appears when there is text, so it is not a button that sits in the tab order doing nothing.
SearchFieldSearchIconis decoration. TheLabelis what names the field — a magnifying glass says "search" only to people who can see it.
API
SearchField
| Prop | Type | Default | Description |
|---|---|---|---|
ariaDescribedby | string | — | Ids of the elements that describe the field, on top of any nested help text. |
ariaLabel | string | — | Accessible name, for a field with no visible label. |
ariaLabelledby | string | — | Ids of the elements that name the field. |
autoCapitalize | string | — | |
autoComplete | string | — | |
autoCorrect | string | — | |
autoFocus | boolean | — | Whether the field takes focus on mount. |
defaultValue | string | — | Text the field starts with, and goes back to when the form is reset. |
enterKeyHint | string | — | Action label for the enter key on a virtual keyboard. |
form | string | — | id of the form to submit with, for a field rendered outside it. |
fullWidth | boolean | — | Whether the field stretches to fill its container. |
id | string | — | Lands on the control, which is the field as far as assistive technology is concerned. |
inputMode | string | — | Keyboard the browser should offer on a touch device. |
isDisabled | boolean | — | Whether the field is disabled — no interaction, no submission. |
isInvalid | boolean | — | Whether the value fails validation. Setting it either way takes the field over: false claims the field is valid and shadows validate, the browser and the server alike. |
isReadOnly | boolean | — | Whether the text can be read but not changed. |
isRequired | boolean | — | Whether the field has to be filled in for the form to submit. |
maxLength | number | — | |
minLength | number | — | |
name | string | — | Name submitted with the form. |
onSubmit | ((value: string) => void) | — | Called when the search is submitted from the keyboard. A prop rather than an emit, because its mere presence decides what Enter does: with a handler the key is a submit and stops there, without one it belongs to the form, which submits on Enter in a single-line field of its own accord. Vue strips a declared emit from $attrs, so an emit gives the component no way to tell whether anyone is listening. |
placeholder | string | — | Placeholder shown while the field is empty. |
size | "xs" | "sm" | "md" | "lg" | "md" | How tall the field stands, matching a button of the same size. |
spellCheck | string | boolean | — | |
type | string | "search" | Kind of control the browser should offer. |
validate | ValidationFunction<string> | — | Checks the value and returns a message when it is not acceptable. |
validationBehavior | "aria" | "native" | "native" | How the field reports validation. Inherited from the surrounding form when unset. |
value | string | — | Text in the field. Makes it controlled. |
variant | "primary" | "secondary" | "primary" | Visual variant. |
The default slot receives:
| Slot prop | Type |
|---|---|
isDisabled | boolean |
isEmpty | boolean |
isInvalid | boolean |
isReadOnly | boolean |
isRequired | boolean |
validationDetails | ValidationDetails |
validationErrors | string[] |
| Event | Payload |
|---|---|
change | string |
clear | — |
focusChange | boolean |
update:value | string |
SearchFieldClearButton
Slots: default.
SearchFieldGroup
The default slot receives:
| Slot prop | Type |
|---|---|
isDisabled | boolean |
isFocusVisible | boolean |
isFocusWithin | boolean |
isHovered | boolean |
isInvalid | boolean |
SearchFieldInput
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | — | Placeholder shown while the control is empty. Declared so it can also be set here rather than only on the field; every other native attribute arrives by attribute fallthrough. |
value | string | — | Text in the control. Set here it takes the control over from the field, so the caller owns the value — exactly as a value prop does in React. Without a listener to go with it the text is pinned. |
| Event | Payload |
|---|---|
change | string |
update:value | string |
SearchFieldSearchIcon
Slots: default.