The SearchBox component provides a styled search input with a submit button, automatic language detection, keyboard shortcuts, and analytics tracking.
Import
import SearchBox from "../components/SearchBox.astro";
Usage
Basic Usage
src/pages/[lang]/index.astro
---
import SearchBox from "../../components/SearchBox.astro";
---
<SearchBox />
With Custom Placeholder
<SearchBox placeholder="Buscar palabra..." />
With Pre-filled Query
src/pages/[lang]/buscar.astro
---
const urlParams = new URLSearchParams(Astro.url.search);
const query = urlParams.get("q") || "";
---
<SearchBox
placeholder={t("home.search.placeholder")}
query={query}
/>
Props
placeholder
string
default:"Buscar palabra..."
The placeholder text displayed in the search input field. Should be localized based on the current language.
Pre-fill the search input with an initial query value. Useful for displaying search results pages with the current search term.
Features
Language Detection
The component automatically detects the current language and sets the appropriate search action URL:
const lang = getLangFromUrl(Astro.url);
const prefix = lang === "en" ? "/en" : "/es";
const action = `${prefix}/buscar/`;
<form
class="bg-card border-theme shadow-theme-sm flex items-center gap-2 rounded-lg border p-1"
action={action}
method="get"
>
<input
type="search"
name="q"
value={query}
placeholder={placeholder}
aria-label={t("search.aria_label")}
class="text-theme min-w-0 flex-1 border-none bg-transparent"
/>
<button
class="search-btn"
type="submit"
aria-label={t("search.button_aria_label")}
>
<Search size={16} />
<span class="hidden md:inline">{t("search.button_text")}</span>
</button>
</form>
Keyboard Shortcuts
Press / to focus the search input from anywhere on the page:
document.addEventListener("keydown", (e) => {
if (e.key === "/" && !(e.target instanceof HTMLInputElement)) {
e.preventDefault();
const input = document.querySelector('input[type="search"]');
input?.focus();
}
});
The keyboard shortcut only works when focus is not already on an input element to avoid interfering with typing.
Analytics Tracking
Search submissions are automatically tracked with Umami:
document.addEventListener("astro:page-load", () => {
const form = document.querySelector('form[action*="buscar"]');
if (form) {
form.addEventListener("submit", () => {
const input = form.querySelector('input[name="q"]');
if (input && input.value && window.umami) {
window.umami.track("Search", { query: input.value });
}
});
}
});
Styling
The submit button has gradient styling and dynamic effects:
.search-btn {
position: relative;
background: var(--btn-primary-bg);
box-shadow:
0 2px 8px var(--btn-primary-shadow),
0 1px 3px var(--shadow-md);
}
.search-btn:hover {
box-shadow:
0 4px 12px var(--btn-primary-shadow),
0 2px 6px var(--shadow-md);
transform: translateY(-1px);
}
.search-btn:active {
box-shadow: 0 1px 4px var(--btn-primary-shadow);
transform: translateY(0) scale(0.95);
}
Responsive Behavior
The button text is hidden on mobile devices:
<span class="hidden md:inline">
{t("search.button_text")}
</span>
Accessibility
ARIA Labels
Both the input and button include proper ARIA labels:
<input
aria-label={t("search.aria_label")}
type="search"
/>
<button
aria-label={t("search.button_aria_label")}
type="submit"
>
Focus States
Visible focus indicators for keyboard navigation:
.search-btn:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
Internationalization
The component uses the useTranslations() helper for all text:
const t = useTranslations(lang);
<input aria-label={t("search.aria_label")} />
<button aria-label={t("search.button_aria_label")}>
<span>{t("search.button_text")}</span>
</button>
Translation Keys
search.aria_label - Input field label
search.button_aria_label - Button label
search.button_text - Button visible text
The form submits to /{lang}/buscar/ with the query parameter:
GET /es/buscar/?q=chapín
GET /en/buscar/?q=guatemalan
View Transitions
The component works seamlessly with Astro’s View Transitions API. The search state persists across navigation, and event listeners are reattached on page load:
document.addEventListener("astro:page-load", () => {
// Reattach event listeners
});
Layout Examples
Hero Section
<section class="hero">
<h1>Diccionario Chapín</h1>
<p>Discover Guatemalan slang</p>
<SearchBox placeholder="Search for a word..." />
</section>
Search Page
<div class="mx-auto max-w-[1100px] px-6">
<div class="card-with-gradient shadow-theme-lg my-6">
<h1 class="gradient-text">{t("search.title")}</h1>
<p class="text-muted">{t("search.subtitle")}</p>
<SearchBox placeholder={t("home.search.placeholder")} />
</div>
<div id="searchResults"></div>
</div>
Browser Support
- Modern browsers with ES6+ support
input[type="search"] for native search functionality
- CSS custom properties for theming
- View Transitions API (with fallback)
Related Pages