Liking cljdoc? Tell your friends :D

x-search-field

A form-associated custom element providing search-box UX: inline search icon, clear button, and Enter-to-search event. Integrates with x-form via ElementInternals.

Tag

<x-search-field name="q" placeholder="Search…" label="Site search"></x-search-field>

Observed Attributes

AttributeTypeDefaultNotes
namestring""Field name in form payload
valuestring""Current value (reflects input)
placeholderstring""Input placeholder text
labelstring""Sets aria-label on the input
disabledbooleanabsentDisables input, hides clear button
requiredbooleanabsentMarks field as required
autocompleteenum"off""on" | "off"
debouncenumber0Milliseconds to debounce x-search-field-input; 0/absent/invalid = fire immediately

Properties

All properties reflect to their corresponding attributes.

PropertyType
valuestring
namestring
placeholderstring
labelstring
autocompletestring
disabledboolean
requiredboolean
debouncenumber

Reading value returns the live input.value (not the attribute). Setting value syncs both the attribute and the input DOM node.

Events

EventBubblesComposedCancelableDetail
x-search-field-inputyesyesno{name, value}
x-search-field-changeyesyesno{name, value}
x-search-field-searchyesyesyes{name, value}
x-search-field-clearyesyesno{name}

x-search-field-search is dispatched when the user presses Enter. It is cancelable but does not auto-submit a parent form.

Debouncing input

Set the debounce attribute (or .debounce property) to a positive millisecond count to coalesce rapid typing into a single x-search-field-input event, fired once the user pauses. This is opt-in — with debounce absent or 0, the event fires on every keystroke as before.

Only the outward x-search-field-input event is delayed. Local UI feedback (the clear button, form value, and validity) stays synchronous with each keystroke, so the field never feels laggy. The coalesced event carries the field's final value. A pending debounced dispatch is cancelled when the field is cleared, the parent form is reset, or the element is disconnected — so a stale event never lands after the value is gone.

x-search-field-change (blur), x-search-field-search (Enter), and x-search-field-clear are never debounced.

<!-- Fire x-search-field-input at most once per 300ms of quiet typing -->
<x-search-field name="q" placeholder="Search…" debounce="300"></x-search-field>

Shadow DOM Structure

:host
  style
  div[part=wrapper]
    span[part=icon]      — inline SVG magnifying glass, pointer-events:none
    input[part=input]    — type="search", native clear button suppressed
    button[part=clear]   — "×", hidden (.clear-hidden) when empty or disabled

CSS Custom Properties

PropertyDefault (light)
--x-search-field-bg#ffffff
--x-search-field-color#111827
--x-search-field-border1px solid #d1d5db
--x-search-field-border-radius6px
--x-search-field-focus-ring-color#2563eb
--x-search-field-icon-color#9ca3af
--x-search-field-clear-color#9ca3af
--x-search-field-disabled-opacity0.45

Dark mode values are applied automatically via @media (prefers-color-scheme: dark) inside the shadow style.

Form Association

x-search-field is a form-associated custom element (static formAssociated = true). It:

  • Participates in <form> submission via ElementInternals.setFormValue
  • Supports required validation (valueMissing) via ElementInternals.setValidity
  • Exposes reportValidity() through the browser's ElementInternals implementation
  • Responds to formDisabledCallback (syncs disabled state)
  • Responds to formResetCallback (clears value)

Usage inside x-form

<x-form>
  <x-search-field name="q" label="Site search" placeholder="Search…" required></x-search-field>
  <button type="submit">Search</button>
  <button type="reset">Clear</button>
</x-form>

x-form's collect-values picks up x-search-field via the (.-value field) property fallback — no x-form changes required.

Accessibility

  • The label attribute sets aria-label on the inner <input> (no visible label element is rendered).
  • aria-required is set to "true" / "false" on the input based on the required attribute.
  • The clear button has a static aria-label="Clear search".
  • The search icon SVG carries aria-hidden="true" and is excluded from pointer events.
  • Focus is moved back to the input after the clear button is activated.
  • Animations respect @media (prefers-reduced-motion: reduce).

Usage Examples

Standalone with event logging

<x-search-field id="site-search" name="q" label="Search" placeholder="Search…"></x-search-field>

<script>
  const sf = document.getElementById('site-search');
  sf.addEventListener('x-search-field-search', e => {
    console.log('Search:', e.detail.value);
  });
  sf.addEventListener('x-search-field-clear', () => {
    console.log('Cleared');
  });
</script>

Inside x-form

<x-form id="search-form">
  <x-search-field name="q" label="Site search" placeholder="Search the site…" required></x-search-field>
  <button type="submit">Search</button>
  <button type="reset">Reset</button>
</x-form>

<script>
  document.getElementById('search-form').addEventListener('x-form-submit', e => {
    console.log('Form values:', e.detail.values); // { q: "…" }
  });
</script>

CSS theming

x-search-field {
  --x-search-field-bg: #f1f5f9;
  --x-search-field-border-radius: 9999px;
  --x-search-field-focus-ring-color: #7c3aed;
}

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close