diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.test.tsx index 77cbcf6211d..5302ac3b7f7 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.test.tsx @@ -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(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.tsx index df87c511cf4..2d98b67cb4a 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/content_filter/PatternModal.tsx @@ -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 = ({ value={selectedPattern} onValueChange={(pattern: PrebuiltPattern | null) => pattern && onPatternNameChange(pattern.name)} itemToStringLabel={(pattern: PrebuiltPattern) => pattern.display_name} + filter={matchesPatternQuery} > diff --git a/ui/litellm-dashboard/src/app/globals.css b/ui/litellm-dashboard/src/app/globals.css index 97f61a610d9..7013e502c22 100644 --- a/ui/litellm-dashboard/src/app/globals.css +++ b/ui/litellm-dashboard/src/app/globals.css @@ -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; +}