Skip to content

Template Search Results

The result rows are created in JavaScript with create(), so filtering is a matter of rendering a new set of instances and replacing the old ones. The markup, the styles, and the data stay in separate places.

Code

The following example assumes that you have imported the component and set up the theme.

Search Results
<sv-template id="search-result">
39 collapsed lines
<template>
<div class="result">
<a class="result-title" href="[[ url ]]">[[ title ]]</a>
<p class="result-summary">[[ summary ]]</p>
<span class="result-section">[[ section ]]</span>
</div>
</template>
<style>
.result {
display: grid;
gap: 0.3em;
padding: 0.8em 1em;
background-color: var(--sv-gray-7);
border: var(--sv-bdr-sz-sm) solid var(--sv-gray-5);
border-radius: var(--sv-bdr-rad-md);
}
.result-title {
font-weight: 600;
color: var(--sv-accent);
text-decoration: none;
}
.result-summary {
margin: 0;
font-size: 0.85em;
color: var(--sv-gray-2);
}
.result-section {
justify-self: start;
padding: 0.1em 0.6em;
font-size: 0.7em;
color: var(--sv-gray-3);
background-color: var(--sv-gray-6);
border-radius: 999px;
}
</style>
</sv-template>
<div class="search">
5 collapsed lines
<input type="search" class="search-input" aria-label="Search the docs" placeholder="Search the docs" />
<div class="search-results"></div>
<p class="search-empty" hidden>Nothing matched that search.</p>
</div>
<script type="application/x-typescript" module>
42 collapsed lines
const template = document.querySelector<Template>("#search-result")!;
const input = document.querySelector<HTMLInputElement>(".search-input")!;
const results = document.querySelector(".search-results")!;
const empty = document.querySelector<HTMLElement>(".search-empty")!;
const articles = [
{
title: "Installation",
summary: "Add the package, import a component, and load a theme.",
section: "Getting started",
url: "#installation",
},
{
title: "Theming",
summary: "Override the color, spacing, and radius custom properties.",
section: "Guides",
url: "#theming",
},
{
title: "Form controls",
summary: "Inputs, toggles, and sliders that submit like native elements.",
section: "Components",
url: "#form-controls",
},
{
title: "Server rendering",
summary: "Ship the markup first and upgrade the components on load.",
section: "Guides",
url: "#server-rendering",
},
];
const render = () => {
const query = input.value.trim().toLowerCase();
const matches = articles.filter(article => `${article.title} ${article.summary}`.toLowerCase().includes(query));
results.replaceChildren(...matches.map(article => template.create(article)));
empty.hidden = matches.length > 0;
};
input.addEventListener("input", render);
render();
</script>
<style>
28 collapsed lines
.search {
display: grid;
gap: 0.75em;
max-inline-size: 32rem;
padding: clamp(1rem, 4vw, 2rem);
margin-inline: auto;
.search-input {
padding: 0.5em 0.8em;
font: inherit;
color: var(--sv-gray-1);
background-color: var(--sv-gray-6);
border: var(--sv-bdr-sz-sm) solid var(--sv-gray-5);
border-radius: var(--sv-bdr-rad-md);
}
.search-results {
display: grid;
gap: 0.5em;
}
.search-empty {
margin: 0;
font-size: 0.85em;
color: var(--sv-gray-3);
text-align: center;
}
}
</style>