diff --git a/src/lib/client/search-filter.svelte.ts b/src/lib/client/search-filter.svelte.ts index 90e680b..06f1d70 100644 --- a/src/lib/client/search-filter.svelte.ts +++ b/src/lib/client/search-filter.svelte.ts @@ -62,6 +62,14 @@ class SearchFilterStore { this.persist(); } + // Übernimmt eine vorbereitete Draft-Auswahl auf einmal — wird vom + // Filter-Dropdown genutzt, der Toggles erst lokal sammelt und erst beim + // „OK"-Klick committet. Triggert den active-$effect nur ein einziges Mal. + commit(next: Set): void { + this.active = next; + this.persist(); + } + // True wenn der User die Suche eingeschränkt hat (mindestens eine aber nicht alle). get isFiltered(): boolean { return this.active.size > 0 && this.active.size < this.domains.length; diff --git a/src/lib/components/SearchFilter.svelte b/src/lib/components/SearchFilter.svelte index e2749af..eea70f1 100644 --- a/src/lib/components/SearchFilter.svelte +++ b/src/lib/components/SearchFilter.svelte @@ -1,5 +1,5 @@ @@ -62,7 +88,7 @@ aria-label="Suchfilter" aria-haspopup="menu" aria-expanded={open} - onclick={toggle} + onclick={toggleTrigger} > {searchFilterStore.label} @@ -73,22 +99,14 @@ {/if} @@ -267,6 +295,43 @@ font-size: 0.9rem; margin: 0; } + .menu-foot { + display: flex; + gap: 0.5rem; + justify-content: flex-end; + padding: 0.6rem 0.5rem 0.35rem; + border-top: 1px solid #f0f3f1; + margin-top: 0.2rem; + } + .btn { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.55rem 0.9rem; + border-radius: 8px; + border: 1px solid #cfd9d1; + background: white; + color: #1a1a1a; + cursor: pointer; + font-size: 0.92rem; + min-height: 40px; + font-family: inherit; + } + .btn.ghost { + color: #666; + } + .btn.ghost:hover { + background: #f4f8f5; + } + .btn.primary { + background: #2b6a3d; + color: white; + border-color: #2b6a3d; + font-weight: 600; + } + .btn.primary:hover { + background: #235532; + } @media (max-width: 520px) { .trigger { padding: 0.5rem 0.55rem;