Component
Search Autocomplete
Search Autocomplete.
- Component
- Vanilla
- HTML
- MIT
What it does
Capabilities
- ARIA
- Keyboard nav
Preview
Live component
No interactive preview for this component.
Install it with the CLI below, or read the implementation on this page.
Install
Add to your project
npx devsnips add Vanilla/Components/Forms/search-autocomplete Vanilla/Components/Forms/search-autocomplete <!--
Search Bar with Autocomplete
- Live search suggestions
- Keyboard navigation support
- Mobile-friendly design
- ARIA roles and states
- Minimal styling with smooth animations
-->
<form class="search-container" role="search">
<div class="search-wrapper">
<input
type="search"
class="search-input"
placeholder="Search..."
aria-label="Search"
aria-expanded="false"
aria-controls="search-suggestions"
aria-autocomplete="list"
autocomplete="off"
>
<button type="submit" class="search-button" aria-label="Submit search">
<svg viewBox="0 0 24 24" width="24" height="24">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="currentColor"/>
</svg>
</button>
<ul id="search-suggestions" class="search-suggestions" role="listbox" hidden>
<!-- Demo suggestions -->
<li role="option" tabindex="-1">
<button type="button" class="suggestion-button">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z" fill="currentColor"/>
</svg>
<span>Search suggestion 1</span>
</button>
</li>
<li role="option" tabindex="-1">
<button type="button" class="suggestion-button">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z" fill="currentColor"/>
</svg>
<span>Search suggestion 2</span>
</button>
</li>
<li role="option" tabindex="-1">
<button type="button" class="suggestion-button">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z" fill="currentColor"/>
</svg>
<span>Search suggestion 3</span>
</button>
</li>
</ul>
</div>
</form>
<style>
.search-container {
max-width: 600px;
margin: 2rem auto;
padding: 0 1rem;
}
.search-wrapper {
position: relative;
}
.search-input {
width: 100%;
padding: 0.75rem 3rem 0.75rem 1rem;
border: 2px solid var(--ds-border, #ddd);
border-radius: var(--ds-radius-md, 8px);
font-size: 1rem;
transition: border-color 0.3s;
}
.search-input:focus {
outline: none;
border-color: var(--ds-accent, #4a90e2);
border-radius: var(--ds-radius-md, 8px) 8px 0 0;
}
.search-button {
position: absolute;
right: 0.5rem;
top: 50%;
transform: translateY(-50%);
padding: 0.5rem;
border: none;
background: none;
color: var(--ds-muted, #666);
cursor: pointer;
transition: color 0.3s;
}
.search-button:hover {
color: var(--ds-foreground, #333);
}
.search-suggestions {
position: absolute;
top: 100%;
left: 0;
right: 0;
margin: 0;
padding: 0;
list-style: none;
background: white;
border: 2px solid var(--ds-accent, #4a90e2);
border-top: none;
border-radius: 0 0 8px 8px;
box-shadow: var(--ds-shadow-md, 0 4px 6px rgba(0, 0, 0, 0.1));
z-index: 1000;
}
.suggestion-button {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
padding: 0.75rem 1rem;
border: none;
background: none;
text-align: left;
cursor: pointer;
transition: background-color 0.3s;
}
.suggestion-button:hover,
.suggestion-button:focus {
background-color: var(--ds-surface-2, #f5f5f5);
}
/* Focus styles */
.search-button:focus-visible {
outline: 2px solid var(--ds-accent, #4a90e2);
outline-offset: 2px;
border-radius: var(--ds-radius-sm, 4px);
}
/* Mobile optimization */
@media (max-width: 600px) {
.search-input {
padding: 0.875rem 3rem 0.875rem 1rem;
}
.suggestion-button {
padding: 1rem;
}
}
/* devsnips-qa:quality-bar */
@media (prefers-reduced-motion: reduce){*{animation-duration:0.01ms !important;animation-iteration-count:1 !important;transition-duration:0.01ms !important;scroll-behavior:auto !important;}}
/* DevSnips design tokens (Swiss) — edit tokens.css to re-theme */
:root{
--ds-bg:#fff;--ds-surface:#fff;--ds-surface-2:#f7f7f7;--ds-surface-3:#ededed;--ds-foreground:#0a0a0a;--ds-muted:#525252;--ds-subtle:#a3a3a3;--ds-border:#e5e5e5;--ds-border-strong:#d4d4d4;--ds-accent:#2563eb;--ds-accent-hover:#1d4ed8;--ds-accent-fg:#fff;--ds-accent-soft:#eff6ff;--ds-success:#16a34a;--ds-success-soft:#f0fdf4;--ds-warning:#d97706;--ds-warning-soft:#fffbeb;--ds-danger:#dc2626;--ds-danger-soft:#fef2f2;--ds-info:#2563eb;--ds-info-soft:#eff6ff;--ds-font-sans:system-ui,-apple-system,'Segoe UI',Roboto,Inter,'Helvetica Neue',Arial,sans-serif;--ds-font-mono:ui-monospace,'SF Mono','JetBrains Mono',Menlo,Consolas,monospace;--ds-text-xs:.75rem;--ds-text-sm:.875rem;--ds-text-base:1rem;--ds-text-lg:1.125rem;--ds-text-xl:1.25rem;--ds-text-2xl:1.5rem;--ds-text-3xl:1.875rem;--ds-text-4xl:2.25rem;--ds-leading-tight:1.25;--ds-leading-normal:1.5;--ds-leading-relaxed:1.625;--ds-weight-normal:400;--ds-weight-medium:500;--ds-weight-semibold:600;--ds-weight-bold:700;--ds-space-0:0;--ds-space-px:1px;--ds-space-1:.25rem;--ds-space-2:.5rem;--ds-space-3:.75rem;--ds-space-4:1rem;--ds-space-5:1.25rem;--ds-space-6:1.5rem;--ds-space-8:2rem;--ds-space-10:2.5rem;--ds-space-12:3rem;--ds-space-16:4rem;--ds-radius-sm:.25rem;--ds-radius-md:.5rem;--ds-radius-lg:.75rem;--ds-radius-xl:1rem;--ds-radius-2xl:1.5rem;--ds-radius-full:9999px;--ds-shadow-sm:0 1px 2px 0 rgba(0,0,0,.05);--ds-shadow-md:0 4px 6px -1px rgba(0,0,0,.08),0 2px 4px -2px rgba(0,0,0,.05);--ds-shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.05);--ds-duration-fast:120ms;--ds-duration-normal:200ms;--ds-duration-slow:300ms;--ds-ease-out:cubic-bezier(.16,1,.3,1);--ds-ease-in-out:cubic-bezier(.4,0,.2,1);--ds-ring:0 0 0 2px #2563eb;--ds-container:1200px;--ds-gutter:1rem;
}
@media (prefers-color-scheme: dark){:root{--ds-bg:#0a0a0a;--ds-surface:#111;--ds-surface-2:#171717;--ds-surface-3:#1f1f1f;--ds-foreground:#fafafa;--ds-muted:#a3a3a3;--ds-subtle:#737373;--ds-border:#262626;--ds-border-strong:#404040;--ds-accent:#3b82f6;--ds-accent-hover:#60a5fa;--ds-accent-fg:#fff;--ds-accent-soft:#172554;--ds-success:#22c55e;--ds-success-soft:#052e16;--ds-warning:#f59e0b;--ds-warning-soft:#422006;--ds-danger:#ef4444;--ds-danger-soft:#450a0a;--ds-info:#3b82f6;--ds-info-soft:#172554;--ds-ring:0 0 0 2px #3b82f6;}}
</style>
<script>
const searchForm = document.querySelector('.search-container');
const searchInput = document.querySelector('.search-input');
const suggestionsList = document.querySelector('.search-suggestions');
const suggestions = document.querySelectorAll('[role="option"]');
// Toggle suggestions visibility
searchInput.addEventListener('input', (e) => {
const hasValue = e.target.value.length > 0;
suggestionsList.hidden = !hasValue;
searchInput.setAttribute('aria-expanded', hasValue);
});
// Handle keyboard navigation
searchInput.addEventListener('keydown', (e) => {
if (!['ArrowDown', 'ArrowUp', 'Escape'].includes(e.key)) return;
e.preventDefault();
if (e.key === 'Escape') {
suggestionsList.hidden = true;
searchInput.setAttribute('aria-expanded', 'false');
return;
}
if (suggestionsList.hidden) {
suggestionsList.hidden = false;
searchInput.setAttribute('aria-expanded', 'true');
suggestions[0].querySelector('button').focus();
return;
}
const currentIndex = Array.from(suggestions).findIndex(
suggestion => suggestion.contains(document.activeElement)
);
let nextIndex;
if (e.key === 'ArrowDown') {
nextIndex = currentIndex < suggestions.length - 1 ? currentIndex + 1 : 0;
} else {
nextIndex = currentIndex > 0 ? currentIndex - 1 : suggestions.length - 1;
}
suggestions[nextIndex].querySelector('button').focus();
});
// Close suggestions when clicking outside
document.addEventListener('click', (e) => {
if (!searchForm.contains(e.target)) {
suggestionsList.hidden = true;
searchInput.setAttribute('aria-expanded', 'false');
}
});
// Handle suggestion selection
suggestions.forEach(suggestion => {
suggestion.querySelector('button').addEventListener('click', () => {
searchInput.value = suggestion.textContent.trim();
suggestionsList.hidden = true;
searchInput.setAttribute('aria-expanded', 'false');
searchInput.focus();
});
});
</script> # Snippet 11 Search Autocomplete
Snippet 11 Search Autocomplete with responsive design with animations and hover interactions.
**Technology:** vanilla
**Category:** components
**Subcategory:** forms
**Tags:** accessibility, animation, hover-effect, shadow, responsive, flexbox, center, layout
**Responsive:** Yes 227 lines UTF-8 · LF · Spaces: 2
DevSnips AI ready Claude · Cursor · Windsurf
Agent skill & Model Context Protocol
Pass this component straight into your AI workflow. DevSnips exposes each resource as a structured, addressable registry entry, so your agent installs the real files instead of approximating them.
devsnips://components/forms/search-autocomplete I want to use this DevSnips resource in production: Page: https://devsnips.site/library/vanilla/components/forms/search-autocomplete/ Install: npx devsnips add Vanilla/Components/Forms/search-autocomplete This is the Search Autocomplete — Search Autocomplete. Use this DevSnips resource as the starting point for my project. Adapt it to my project's stack and conventions, fix any issues, and make it production-ready while preserving its intended design and behavior.
Paste into ChatGPT, Claude or your agent — it already carries the page URL and the exact install path.
Resource URI
devsnips://components/forms/search-autocomplete