diff --git a/docs/ui-guidelines.md b/docs/ui-guidelines.md index 1eeb0af91..5b00604e2 100644 --- a/docs/ui-guidelines.md +++ b/docs/ui-guidelines.md @@ -236,20 +236,15 @@ lists) uses the unified `` rail from `src/components/ui/filter-bar.tsx` — never a per-page row of large labelled ` onSearchChange(e.target.value)} + placeholder={t("labs.filter.searchPlaceholder")} + aria-label={t("labs.filter.searchLabel")} + aria-keyshortcuts="/" + className="w-full min-w-0 pr-11 pl-9 [&::-webkit-search-cancel-button]:appearance-none" + /> + {searchDraft === "" ? ( + + ) : ( + )} + - +
+ + + + { + if (isLabStatusFilter(val)) onStatusChange(val); + }} + options={statusOptions} + allValue="ALL" + allLabel={t("labs.filter.statusAll")} + /> + + {categoryOptions.length > 0 && ( + + )} + +
); } diff --git a/src/components/ui/filter-bar.tsx b/src/components/ui/filter-bar.tsx index abacb0576..3291d1c7b 100644 --- a/src/components/ui/filter-bar.tsx +++ b/src/components/ui/filter-bar.tsx @@ -28,22 +28,19 @@ import { cn } from "@/lib/utils"; * instead of the per-page rows of large labelled Selects + date inputs * that had drifted apart. The grammar: * - * [search] [filter icon] [Zeitraum] [Typ] [Quelle] … [Zurücksetzen] [count] + * [filter icon] [Zeitraum] [Typ] [Quelle] … [Zurücksetzen] [count] * * - Each dimension renders as ONE compact pill that is trigger and * active-filter chip at once: inactive it shows just the dimension * name ("Typ"), active it shows `Name: Wert`, picks up the primary * accent, and grows a removable ✕. No second chip row, no duplicated * state. - * - Canonical order at the call sites: search (if present), date range, - * type, source — surface-specific dimensions append after. + * - Canonical order at the call sites: date range, type, source — + * surface-specific dimensions append after. * - Reset appears only while at least one dimension is active. - * - Mobile (< sm): standard pill rails use a horizontal scroll row (hidden + * - Mobile (< sm): the rail is a horizontal scroll row (hidden * scrollbar, edge-bleed) so pills never wrap into a tall block; the - * result count drops onto its own line. Surfaces that integrate search - * into the rail (such as labs) wrap on mobile instead via - * `railClassName` (`max-sm:flex-wrap`) so the search input stays - * full-width and pills wrap naturally underneath. + * result count drops onto its own line. * - Purely presentational: filter state, query keys and fetching stay * in the owning page/component — this file only renders the controls. * @@ -87,7 +84,6 @@ export function FilterBar({ onReset, count, children, - railClassName, }: { /** True when at least one dimension is active — shows the reset button. */ isFiltered: boolean; @@ -95,8 +91,6 @@ export function FilterBar({ onReset: () => void; /** Result count node (already translated/formatted by the caller). */ count?: React.ReactNode; - /** Optional classes for the row of filter controls. */ - railClassName?: string; children: React.ReactNode; }) { const { t } = useTranslations(); @@ -108,12 +102,7 @@ export function FilterBar({ {/* Pill rail — horizontal scroll row below `sm` (hidden scrollbar, edge-bleed so the row scrolls to the screen edge), wrapping flex row on desktop. */} -
+