From b7f672e0f24f7b41f458d6df1b04f95dbf71f84f Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Tue, 22 Apr 2025 12:49:57 +0000 Subject: [PATCH] feat(dees-searchbar): Add dees-searchbar component with live search and filter demo --- changelog.md | 7 ++ ts_web/00_commitinfo_data.ts | 2 +- ts_web/elements/dees-searchbar.demo.ts | 46 +++++++ ts_web/elements/dees-searchbar.ts | 160 +++++++++++++++++++++++++ ts_web/elements/dees-searchbox.ts | 0 ts_web/elements/index.ts | 1 + 6 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 ts_web/elements/dees-searchbar.demo.ts create mode 100644 ts_web/elements/dees-searchbar.ts delete mode 100644 ts_web/elements/dees-searchbox.ts diff --git a/changelog.md b/changelog.md index 4ca69d1..f617c63 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2025-04-22 - 1.7.0 - feat(dees-searchbar) +Add dees-searchbar component with live search and filter demo + +- Introduces a new dees-searchbar element with an input field, a search button, and filters +- Wires up events for 'search-changed' and 'search-submit' to provide real‐time feedback +- Adds a demo file to showcase usage and logging of search events + ## 2025-04-22 - 1.6.0 - feat(documentation/dees-heading) Add codex documentation overview and dees-heading component demo diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index c683877..d833764 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@design.estate/dees-catalog', - version: '1.6.0', + version: '1.7.0', description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.' } diff --git a/ts_web/elements/dees-searchbar.demo.ts b/ts_web/elements/dees-searchbar.demo.ts new file mode 100644 index 0000000..7ac4e59 --- /dev/null +++ b/ts_web/elements/dees-searchbar.demo.ts @@ -0,0 +1,46 @@ +import { html } from '@design.estate/dees-element'; + +export const demoFunc = () => { + const onChanged = (e: CustomEvent) => { + // find the demo wrapper and update the 'changed' log inside it + const wrapper = (e.target as HTMLElement).closest('.demoWrapper'); + const el = wrapper?.querySelector('#changed'); + if (el) el.textContent = `search-changed: ${e.detail.value}`; + }; + const onSubmit = (e: CustomEvent) => { + // find the demo wrapper and update the 'submitted' log inside it + const wrapper = (e.target as HTMLElement).closest('.demoWrapper'); + const el = wrapper?.querySelector('#submitted'); + if (el) el.textContent = `search-submit: ${e.detail.value}`; + }; + return html` + +
+ +
+
search-changed:
+
search-submit:
+
+
+ `; +}; \ No newline at end of file diff --git a/ts_web/elements/dees-searchbar.ts b/ts_web/elements/dees-searchbar.ts new file mode 100644 index 0000000..c1c1e20 --- /dev/null +++ b/ts_web/elements/dees-searchbar.ts @@ -0,0 +1,160 @@ +import { + customElement, + DeesElement, + property, + html, + cssManager, + unsafeCSS, + css, + type TemplateResult, + domtools, + query, +} from '@design.estate/dees-element'; + +import * as colors from './00colors.js'; +import { demoFunc } from './dees-searchbar.demo.js'; + +declare global { + interface HTMLElementTagNameMap { + 'dees-searchbar': DeesSearchbar; + } +} + +@customElement('dees-searchbar') +export class DeesSearchbar extends DeesElement { + // DEMO + public static demo = demoFunc; + + // STATIC + public static styles = [ + cssManager.defaultStyles, + css` + :host { + padding: 40px; + font-family: Dees Sans; + display: block; + background: ${cssManager.bdTheme('#eeeeeb', '#000000')}; + } + + .searchboxContainer { + position: relative; + margin: auto; + max-width: 800px; + background: ${cssManager.bdTheme('#00000015', '#ffffff15')}; + --boxHeight: 60px; + height: var(--boxHeight); + border-radius: var(--boxHeight); + display: grid; + grid-template-columns: 1fr 140px; + justify-content: center; + align-items: center; + border-top: 1px solid ${cssManager.bdTheme('#00000015', '#ffffff20')}; + } + + input { + height: 100%; + width: 100%; + border: none; + background: none; + color: ${cssManager.bdTheme('#000000', '#eeeeeb')}; + padding-left: 25px; + margin-right: -8px; + outline: none; + font-size: 16px; + } + + .searchButton { + --buttonPadding: 8px; + background: ${cssManager.bdTheme('#eeeeeb', '#000000')}; + color: ${cssManager.bdTheme('#000000', '#eeeeeb')}; + line-height: calc(var(--boxHeight) - (var(--buttonPadding) * 2)); + border-radius: var(--boxHeight); + transform: scale(1) ; + transform-origin: 50% 50%; + text-align: center; + + transition: transform 0.1s, background 0.1s; + margin-right: var(--buttonPadding); + user-select: none; + } + + .searchButton:hover { + color: #fff; + background: ${cssManager.bdTheme(colors.bright.blue, colors.dark.blue)}; + } + + .searchButton:active { + color: #fff; + background: ${cssManager.bdTheme(colors.bright.blueActive, colors.dark.blueActive)}; + transform: scale(0.98); + } + + .filters { + margin: auto; + max-width: 800px; + } + `, + ]; + + // INSTANCE + + @property() + public filters = []; + + + @query('input') + public searchInput!: HTMLInputElement; + @query('.searchButton') + public searchButton!: HTMLElement; + + constructor() { + super(); + } + + public render(): TemplateResult { + return html` +
+ +
Search ->
+
+ ${this.filters.length > 0 ? html` +
+ Filters + +
+ ` : html``} + `; + } + /** + * Lifecycle: after first render, wire up events for input and submit actions + */ + public firstUpdated(): void { + // dispatch change on each input + this.searchInput.addEventListener('input', () => { + this.dispatchEvent(new CustomEvent('search-changed', { + bubbles: true, + composed: true, + detail: { value: this.searchInput.value } + })); + }); + // submit on Enter key + this.searchInput.addEventListener('keydown', (e: KeyboardEvent) => { + if (e.key === 'Enter') { + this._dispatchSubmit(); + } + }); + // submit on button click + this.searchButton.addEventListener('click', () => this._dispatchSubmit()); + } + + /** + * Dispatch a submit event with the current search value + */ + private _dispatchSubmit(): void { + this.dispatchEvent(new CustomEvent('search-submit', { + bubbles: true, + composed: true, + detail: { value: this.searchInput.value } + })); + } +} diff --git a/ts_web/elements/dees-searchbox.ts b/ts_web/elements/dees-searchbox.ts deleted file mode 100644 index e69de29..0000000 diff --git a/ts_web/elements/index.ts b/ts_web/elements/index.ts index 3cec901..1555e53 100644 --- a/ts_web/elements/index.ts +++ b/ts_web/elements/index.ts @@ -36,6 +36,7 @@ export * from './dees-mobilenavigation.js'; export * from './dees-modal.js'; export * from './dees-input-multitoggle.js'; export * from './dees-pdf.js'; +export * from './dees-searchbar.js'; export * from './dees-simple-appdash.js'; export * from './dees-simple-login.js'; export * from './dees-speechbubble.js';