fix(ui): restore pattern search and popup layering in the guardrail wizard

Two behaviour differences the port introduced, both found in browser QA

The antd Select matched a prebuilt pattern on its display_name and its
internal name; a Base UI Combobox only searches itemToStringLabel, so
queries like "amex" and "sg" stopped matching. Restore the second field
with a filter predicate on the Root, covered by a regression test that
searches on a token the visible label does not contain

Base UI portals a popup into a positioner whose "isolate z-50" is fixed
in the primitive, so inside an antd Modal at z-index 1000 the options
were visible but not clickable. antd hid this because its own dropdowns
and tooltips already sat above its Modal. The positioner is not reachable
from the call site, so this needs one app-wide rule keyed on an antd
modal being present, and it becomes deletable when the last one goes
This commit is contained in:
Yuneng Jiang 2026-08-13 17:27:26 -07:00
parent 4beac28ab5
commit 62523c1734
No known key found for this signature in database
3 changed files with 30 additions and 0 deletions

View file

@ -84,6 +84,20 @@ describe("PatternModal", () => {
expect(screen.queryByText("AWS access key")).not.toBeInTheDocument();
});
it("should match the internal pattern name when it is absent from the display name", async () => {
const user = userEvent.setup();
renderModal();
expect(await screen.findByText("Add prebuilt pattern")).toBeInTheDocument();
await user.click(screen.getAllByRole("combobox")[0]);
await user.keyboard("ssn");
expect(await screen.findByText("US Social Security Number")).toBeInTheDocument();
expect(screen.queryByText("Email address")).not.toBeInTheDocument();
expect(screen.queryByText("Visa card")).not.toBeInTheDocument();
});
it("should report the chosen action", async () => {
const user = userEvent.setup();
renderModal();

View file

@ -28,6 +28,11 @@ interface PatternGroup {
items: PrebuiltPattern[];
}
const matchesPatternQuery = (pattern: PrebuiltPattern, query: string) => {
const needle = query.toLowerCase();
return pattern.display_name.toLowerCase().includes(needle) || pattern.name.toLowerCase().includes(needle);
};
interface PatternModalProps {
visible: boolean;
prebuiltPatterns: PrebuiltPattern[];
@ -74,6 +79,7 @@ const PatternModal: React.FC<PatternModalProps> = ({
value={selectedPattern}
onValueChange={(pattern: PrebuiltPattern | null) => pattern && onPatternNameChange(pattern.name)}
itemToStringLabel={(pattern: PrebuiltPattern) => pattern.display_name}
filter={matchesPatternQuery}
>
<ComboboxInput className="mt-2 w-full" placeholder="Choose pattern type" />
<ComboboxContent>

View file

@ -242,3 +242,13 @@
[data-slot="dialog-content"][data-nested-dialog-open] {
visibility: hidden;
}
/* Base UI portals a popup into an `isolate z-50` positioner, which an antd Modal at z-index 1000
then paints over, so options on a half-migrated page are visible but not clickable. The
positioner is not reachable from the call site, hence the parent selector. Delete this once no
route renders an antd Modal. */
body:has(.ant-modal-wrap) div:has(> [data-slot="select-content"]),
body:has(.ant-modal-wrap) div:has(> [data-slot="combobox-content"]),
body:has(.ant-modal-wrap) div:has(> [data-slot="tooltip-content"]) {
z-index: 1100;
}