diff --git a/src/components/medications/__tests__/medication-reorder-dialog.test.tsx b/src/components/medications/__tests__/medication-order-editor.test.tsx similarity index 100% rename from src/components/medications/__tests__/medication-reorder-dialog.test.tsx rename to src/components/medications/__tests__/medication-order-editor.test.tsx diff --git a/src/components/ui/__tests__/filter-bar.test.tsx b/src/components/ui/__tests__/filter-bar.test.tsx index 5830b2e0f..bde2d54db 100644 --- a/src/components/ui/__tests__/filter-bar.test.tsx +++ b/src/components/ui/__tests__/filter-bar.test.tsx @@ -1,4 +1,6 @@ import { describe, expect, it } from "vitest"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; import { renderToStaticMarkup } from "react-dom/server"; import { I18nProvider } from "@/lib/i18n/context"; @@ -141,3 +143,21 @@ describe("FilterBar shell", () => { expect(html).toContain('aria-label="Filter entfernen: Quelle"'); }); }); + +describe("FilterBarSelect — menu positioning (source pin)", () => { + // The pill trigger paints its own label spans and mounts no + // ``. Radix's default item-aligned placement silently + // skips ALL positioning when the value node is absent — the open + // menu then lays out below the height-locked app shell, fully + // off-viewport, which users report as "clicking does nothing". SSR + // markup cannot exercise an open portal, so this pins the source: + // the content must request popper placement, which has no + // value-node dependency. + it("requests popper placement on the select content", () => { + const src = readFileSync( + join(process.cwd(), "src/components/ui/filter-bar.tsx"), + "utf8", + ); + expect(src).toMatch(//); + }); +}); diff --git a/src/components/ui/filter-bar.tsx b/src/components/ui/filter-bar.tsx index 599ecdadd..4df8852b8 100644 --- a/src/components/ui/filter-bar.tsx +++ b/src/components/ui/filter-bar.tsx @@ -175,7 +175,14 @@ export function FilterBarSelect({ {label} )} - + {/* `position="popper"` is load-bearing: this trigger paints its + own label spans and mounts no `SelectValue`, and Radix's + default item-aligned placement silently skips ALL positioning + when the value node is absent — the open menu then lays out + below the height-locked app shell, fully off-viewport. Popper + placement has no value-node dependency and anchors the menu + under the pill like the date-range popover next to it. */} + {allLabel} {options.map((opt) => (