diff --git a/frontend/src/components/explore-view/explore-view.ts b/frontend/src/components/explore-view/explore-view.ts index 71cf9a0..5ce4947 100644 --- a/frontend/src/components/explore-view/explore-view.ts +++ b/frontend/src/components/explore-view/explore-view.ts @@ -12,6 +12,8 @@ import '@awesome.me/webawesome/dist/components/icon/icon.js'; /* ── Constants ── */ const DEBOUNCE_MS = 300; +const MIN_QUERY_LENGTH = 2; +const MAX_SECTION_RESULTS = 10; const CAA_GROUP_BASE = 'https://coverartarchive.org/release-group'; const TOP_RESULTS_COUNT = 3; @@ -67,6 +69,7 @@ export class ExploreView extends LitElement { @state() private results: MBSearchResult | null = null; @state() private loading = false; @state() private error = ''; + @state() private queryTooShort = false; /** Monotonic counter to discard stale responses. */ private searchVersion = 0; @@ -481,13 +484,26 @@ export class ExploreView extends LitElement { this.debounceTimer = null; } - if (!this.searchQuery.trim()) { + const trimmed = this.searchQuery.trim(); + + if (!trimmed) { this.results = null; this.error = ''; this.loading = false; + this.queryTooShort = false; return; } + if (trimmed.length < MIN_QUERY_LENGTH) { + this.results = null; + this.error = ''; + this.loading = false; + this.queryTooShort = true; + return; + } + + this.queryTooShort = false; + this.debounceTimer = setTimeout(() => { this.debounceTimer = null; void this.executeSearch(); @@ -499,6 +515,7 @@ export class ExploreView extends LitElement { this.results = null; this.error = ''; this.loading = false; + this.queryTooShort = false; if (this.debounceTimer !== null) { clearTimeout(this.debounceTimer); this.debounceTimer = null; @@ -666,6 +683,13 @@ export class ExploreView extends LitElement { } private renderBody() { + // Query too short + if (this.queryTooShort) { + return html`
`; + } + // No query entered yet if (!this.searchQuery.trim() && !this.results) { return html` `;