Skip to content

Latest commit

 

History

History
87 lines (73 loc) · 9.57 KB

File metadata and controls

87 lines (73 loc) · 9.57 KB

TextInput / SearchInput

The bordered text-field primitives. TextInput is the base: a wrapper that carries all chrome (border, focus, invalid state) around a chromeless input, sized to the shared toolbar control heights. SearchInput is TextInput preconfigured for filtering: search-icon prefix, a clear button that appears with content, and an optional shortcut hint while empty.

<script lang="ts">
  import { SearchInput, TextInput } from "@kenn-io/kit-ui";

  let name = $state("");
  let query = $state("");
</script>

<TextInput bind:value={name} placeholder="Display name" />
<SearchInput bind:value={query} keys={["⌘", "K"]} block />

TextInput props

Prop Type Default Notes
value string (bindable) ""
type "text" | "search" | "email" | "url" | "password" | "tel" "text" Text-like types only; date/checkbox/etc. keep native chrome elsewhere
placeholder string —
size "sm" | "md" | "lg" "md" 24px / 28px toolbar controls; 36px-minimum lg form control
invalid boolean false Red border + aria-invalid
disabled / readonly / required boolean false Forwarded to the native input
block boolean false Stretch to container width (default is a 180px inline field)
id / name string — For <label for> / forms
ariaLabel string — Required in spirit when no <label> is associated
autofocus boolean false Focus on mount
autocomplete string —
role / ariaExpanded / ariaControls / ariaActivedescendant / ariaAutocomplete combobox wiring — For fields that drive a listbox (CommandPalette): role="combobox" plus pointers at the list and highlighted option
oninput / onchange (value: string) => void — Called with the new value
onkeydown (event: KeyboardEvent) => void —
onblur () => void — Called when the control loses focus
ariaDescribedby string — Connects supporting or error text to the native input
prefix / suffix Snippet — Adornments inside the border (icon, unit, kbd, button). Interactive suffix actions must handle disabled themselves — the wrapper only dims
inputEl HTMLInputElement (bindable) — The underlying input, for focus management
class string ""

Focus renders as an --accent-blue border and visible focus ring, while invalid renders as --accent-red; both follow the FindBar card convention. Browsers with :has() enhance the ring onto the wrapper, while older engines keep an input-level or native outline fallback. The native webkit search-cancel button is suppressed — the wrapper owns the clear affordance.

FormField composes the lg size with a persistent label and accessible error message. Large inputs and buttons share a 36px minimum height and grow with the user's type size. Use TextInput directly when the surrounding form owns those elements.

SearchInput props

Forwarded from TextInput: value, placeholder, size, invalid, disabled, readonly, block, autofocus, id, name, ariaLabel (default "Search"), the combobox wiring props (role, ariaExpanded, ariaControls, ariaActivedescendant, ariaAutocomplete), oninput, onchange, onkeydown. (type, prefix, and suffix are owned by SearchInput.) Plus:

Prop Type Default Notes
keys string[] — Shortcut hint (KbdBadge) shown while empty, e.g. ["⌘", "K"]
onclear () => void — After the clear button or Escape empties the field
clearLabel string "Clear search" Clear button label

Clearing behavior: the clear button only renders with content on an enabled, non-readonly field (disabled fields can't be mutated through it), and clearing — by click or Escape — returns focus to the input so keyboard users aren't dropped when the button unmounts. Escape stops propagation only when it actually clears — a search-in-modal clears before the modal's Escape-to-close fires and a second Escape reaches the modal, while a readonly/disabled/empty field passes Escape straight through. inputEl is bindable for app shortcut handlers that focus the field.

Where NOT to use it

  • FindBar, Typeahead, SelectDropdown keep their own inputs — they're comboboxes/cards with their own ARIA wiring and chrome ownership.
  • DateRangePicker's custom tab uses native type="date" inputs (native pickers beat styled text fields for dates).
  • FilterDropdown's search box uses SearchInput internally (size="sm" block).