99 lines
2.8 KiB
JavaScript
99 lines
2.8 KiB
JavaScript
/**
|
|
* Search Bar Component
|
|
* Search input with icon
|
|
*/
|
|
class SearchBar extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: 'open' });
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.render();
|
|
this.addEventListeners();
|
|
}
|
|
|
|
addEventListeners() {
|
|
const input = this.shadowRoot.querySelector('.search-input');
|
|
const form = this.shadowRoot.querySelector('.search-form');
|
|
|
|
form.addEventListener('submit', (e) => {
|
|
e.preventDefault();
|
|
this.dispatchEvent(new CustomEvent('search', {
|
|
detail: { query: input.value },
|
|
bubbles: true,
|
|
composed: true
|
|
}));
|
|
});
|
|
|
|
input.addEventListener('input', (e) => {
|
|
this.dispatchEvent(new CustomEvent('search-input', {
|
|
detail: { query: e.target.value },
|
|
bubbles: true,
|
|
composed: true
|
|
}));
|
|
});
|
|
}
|
|
|
|
render() {
|
|
this.shadowRoot.innerHTML = `
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
}
|
|
|
|
.search-form {
|
|
display: flex;
|
|
align-items: center;
|
|
position: relative;
|
|
}
|
|
|
|
.search-icon {
|
|
position: absolute;
|
|
left: var(--spacing-md, 1rem);
|
|
width: 20px;
|
|
height: 20px;
|
|
color: var(--color-text-light, #64748b);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.search-input {
|
|
width: 100%;
|
|
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
|
|
padding-left: calc(var(--spacing-md, 1rem) + 20px + var(--spacing-sm, 0.5rem));
|
|
font-size: var(--font-size-sm, 0.875rem);
|
|
color: var(--color-text, #1e293b);
|
|
background-color: var(--color-background-tertiary, #f1f5f9);
|
|
border: 1px solid transparent;
|
|
border-radius: var(--radius-lg, 0.75rem);
|
|
outline: none;
|
|
transition: all var(--transition-fast, 150ms ease);
|
|
}
|
|
|
|
.search-input::placeholder {
|
|
color: var(--color-text-light, #64748b);
|
|
}
|
|
|
|
.search-input:focus {
|
|
background-color: var(--color-background, #ffffff);
|
|
border-color: var(--color-primary, #2563eb);
|
|
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
|
}
|
|
</style>
|
|
<form class="search-form" role="search">
|
|
<svg class="search-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
|
</svg>
|
|
<input
|
|
type="search"
|
|
class="search-input"
|
|
placeholder="Search books, authors..."
|
|
aria-label="Search books and authors"
|
|
>
|
|
</form>
|
|
`;
|
|
}
|
|
}
|
|
|
|
customElements.define('search-bar', SearchBar);
|