search form
A Search form is a search field, wrapped in a form
, with possible auto-suggestions. For the form to work, you will need to set up either a name
attribute on the search input and an action
on the form, or implement your logic in a submit
event handler on the form.
Attaching autosuggestions heavily depends on your setup and is therefore not part of this component.
The autosuggestion list is a markup demonstrator; do not use this implementation in production!
We recommend to use the `autocomplete="off"` setting showcased here to prevent the browser's native suggestions to overlay the custom suggestions.
According to the Web Content Accessibility Guidelines (WCAG), it is highly reccomended to use a label together with the search form.
table of content
component variations
Default
<form class="m-search-form" autocomplete="off">
<div class="a-search-input">
<input
type="search"
id="search-input-1"
name="Default"
placeholder="Search"
/>
<button type="button" class="a-search-input__icon-close">
<i class="a-icon ui-ic-close-small"></i>
</button>
<button
type="submit"
class="a-search-input__icon-search"
aria-label="Search"
>
<i class="a-icon ui-ic-search"></i>
</button>
</div>
</form>
With suggestions
<form class="m-search-form" autocomplete="off">
<div class="a-search-input">
<input
type="search"
id="search-input-2"
name="With suggestions"
placeholder="Search"
/>
<button type="button" class="a-search-input__icon-close">
<i class="a-icon ui-ic-close-small"></i>
</button>
<button
type="submit"
class="a-search-input__icon-search"
aria-label="Search"
>
<i class="a-icon ui-ic-search"></i>
</button>
</div>
<ul class="a-search-suggestions">
<li class="a-search-suggestions__item">
<a href="#" class="a-search-suggestions__result-link">
<em>Product XYZ</em>
Lorem ipsum dolor
</a>
</li>
<li class="a-search-suggestions__item">
<a href="#" class="a-search-suggestions__result-link">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr Product XYZ
another line can be very long or very short, however when text breaks
and the Product XYZ is mentioned again,
<em>we should highlight this</em>
</a>
</li>
<li class="a-search-suggestions__item">
<a href="#" class="a-search-suggestions__result-link">
Lorem ipsum
<em>Product XYZ</em>
</a>
</li>
<li class="a-search-suggestions__item">
<a href="#" class="a-search-suggestions__result-link">
<em>Product XYZ</em>
Lorem ipsum dolor
</a>
</li>
<li class="a-search-suggestions__item a-search-suggestions__results-link">
<div class="a-link -icon">
<a href="/" target="_self">
<span>All</span>
<span>
Results
<i class="a-icon ui-ic-nosafe-lr-right-small"></i>
</span>
</a>
</div>
</li>
</ul>
</form>
Auto suggestion demonstrator
<div class="frontend-kit-example_m-search-form">
<form class="m-search-form" autocomplete="off">
<div class="a-search-input">
<input type="search" id="search-input-3" />
<button type="button" class="a-search-input__icon-close">
<i class="a-icon ui-ic-close-small"></i>
</button>
<button
type="submit"
class="a-search-input__icon-search"
aria-label="Search"
>
<i class="a-icon ui-ic-search"></i>
</button>
</div>
</form>
</div>
additional content
Instance API
The instance API can be accessed by the component
property of the searchForm element.
Attribute | description |
---|---|
searchInput |
access the underlying inputSearch component to subscribe to custom events |
demo
import { dataMock } from './demonstrators/dataMock';
export default (): void => {
const searchFields = document.querySelectorAll(
'.a-text-field.a-text-field--search',
);
[...searchFields].forEach((searchField) => {
const searchInput: HTMLInputElement = searchField.querySelector(
'[type="search"]',
);
const resetIcon: HTMLElement = searchField.querySelector(
'.a-text-field__icon-close',
);
// register the reset of the text field input
if (resetIcon instanceof HTMLElement) {
resetIcon.addEventListener('click', () => {
if (searchInput.getAttribute('type') === 'search') {
searchInput.value = '';
}
});
}
});
const exampleContainers = document.querySelectorAll(
'.frontend-kit-example_m-search-form',
);
[...exampleContainers].forEach((container) => {
const searchField = container.querySelector('.m-search-form');
searchField.addEventListener('input', (e) => {
const pastSuggestions = container.querySelector('.a-search-suggestions');
if (pastSuggestions) {
pastSuggestions.remove();
}
const term = e.target.value;
const suggestions = [];
for (let i = 0; suggestions.length < 4 && dataMock.length > i; i += 1) {
if (dataMock[i].toLowerCase().indexOf(term.toLowerCase()) !== -1) {
suggestions.push({
text: dataMock[i],
highlight: term,
href: '#',
});
}
}
const renderSuggestionLinkText = (
text: string,
highlight: string,
): string => {
if (!highlight) {
return text;
}
const searchPattern = new RegExp(highlight, 'ig');
return text.replace(searchPattern, '<em>$&</em>');
};
if (suggestions.length) {
const suggestionItems = suggestions.map((suggestion) => {
return `
<li class="a-search-suggestions__item">
<a href="#" class="a-search-suggestions__result-link">${renderSuggestionLinkText(
suggestion.text,
suggestion.highlight,
)}</a>
</li>`;
});
const suggestionList = `
<ul class="a-search-suggestions">
${suggestionItems.join('')}
<li class="a-search-suggestions__item a-search-suggestions__results-link">
<div class="a-link a-link--primary">
<a href="/" target="_self">All Results</a>
</div>
</li>
</ul>`;
searchField.insertAdjacentHTML('beforeend', suggestionList);
}
});
});
};
styles SCSS
// no styles needed here, yay!```