Search
An lt-input with room for a magnifying glass. Both classes are set, so every state and variable from Input applies here too.
How to use it
Section titled “How to use it”<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/tokens/tokens.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/search/search.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/button/button.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/label/label.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/sr-only/sr-only.css"><!-- Or everything in one file: https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/dist/lotek.css --><form class="lt-search-row" role="search"><label class="lt-label lt-sr-only" for="search">Search cases</label><input class="lt-input lt-search" type="search" id="search" name="q" placeholder="Search cases" /><button class="lt-button" type="submit">Search</button></form>import "@lo-tek/interfaces/tokens.css"import "@lo-tek/interfaces/search.css"import "@lo-tek/interfaces/button.css"import "@lo-tek/interfaces/label.css"import "@lo-tek/interfaces/sr-only.css"lt is used in two ways, and which one depends on whether you create the element or find it.
If you create the markup, spread the attributes in. That is the way in React, Astro and anything else that renders:
import { lt } from "@lo-tek/interfaces/react"
<form className={lt.search.row} role="search"> <label {...lt.label()} htmlFor="search">Search cases</label> <input {...lt.search()} id="search" /></form>The import is from /react here, since the block is JSX. From there the keys are className and htmlFor. In Astro and anything else without React, import @lo-tek/interfaces and you get class and for.
If the element is already there, set them on it. That is the way when you enhance HTML a server or a template has sent:
import { lt } from "@lo-tek/interfaces"
const field = document.querySelector<HTMLInputElement>("#search")
lt.setAttributes(field, lt.search())lt.search() sets both lt-input and lt-search, and type="search". lt.search.row gives the class for the row with the field and the button.
type="search" gives the browser’s own cross for clearing the field, and “Search” instead of “Enter” on the mobile keyboard. Safari and Chrome draw the cross differently, Firefox does not draw it at all, and whether Escape clears the field varies.
role="search" on the form lets screen readers jump straight to the search on the page.
The label cannot be dropped
Section titled “The label cannot be dropped”The placeholder disappears as soon as the user types, and several screen readers do not read it out. If the field is so obviously a search that a visible label becomes noise, hide it with .lt-sr-only rather than leaving it out.
Searching as the user types
Section titled “Searching as the user types”<label class="lt-label lt-sr-only" for="search">Search the cases</label><input class="lt-input lt-search" type="search" id="search" name="q" /><p class="lt-sr-only" role="status" id="matches"></p>
<script type="module"> const field = document.getElementById("search") const status = document.getElementById("matches") let timeout
field.addEventListener("input", () => { clearTimeout(timeout) timeout = setTimeout(async () => { const response = await fetch(`/api/search?q=${encodeURIComponent(field.value)}`) const cases = await response.json()
renderResults(cases) status.textContent = `${cases.length} matches` }, 300) })</script>The 300 millisecond delay is not only for the server. Without it the number of matches is read out on every keystroke.
Classes you can style
Section titled “Classes you can style”| Class | What it is |
|---|---|
.lt-search | The search field. Used together with .lt-input. |
.lt-search-row | The row with the field and the button |
| Variable | Default |
|---|---|
--lt-search-icon-space | var(--lt-spacing-10) |
--lt-search-icon-size | var(--lt-spacing-5) |
The icon comes from --lt-icon-search and follows the theme. See Customising.
Accessibility
Section titled “Accessibility”- Announce the number of matches in an element with
role="status". Without it, someone listening to the page does not know whether the search found anything. - Do not remove the browser’s cross without offering something else. Clearing the field by hand is awkward on a phone.
- If search is the main function of the page, let the field have focus from the start. If it is one of several tools, do not: focus that jumps is confusing.