From 6a69d20b5daf2472387fcd4767c9d856f76bdfa3 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Thu, 23 Jul 2026 12:05:06 -0700 Subject: [PATCH] fix(ui): resolve nested tab routes to their sidebar item legacyKeyForPathname matched the full relative path against a single route segment, so a nested tab route like /caching/health resolved to no key and the shell fell back to the default page, leaving the Caching nav item unhighlighted. Match on the first path segment instead, which fixes every migrated page with nested tab routes (models-and-endpoints too), not just Caching. --- ui/litellm-dashboard/src/utils/migratedPages.test.ts | 10 ++++++++++ ui/litellm-dashboard/src/utils/migratedPages.ts | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ui/litellm-dashboard/src/utils/migratedPages.test.ts b/ui/litellm-dashboard/src/utils/migratedPages.test.ts index 5812c1eec40..7e7ba8adc34 100644 --- a/ui/litellm-dashboard/src/utils/migratedPages.test.ts +++ b/ui/litellm-dashboard/src/utils/migratedPages.test.ts @@ -221,12 +221,22 @@ describe("legacyKeyForPathname", () => { expect(legacyKeyForPathname("/ui/skills")).toBe("skills"); }); + it("maps a nested tab route back to its sidebar key via the first path segment", async () => { + vi.doMock("@/components/networking", () => ({ serverRootPath: "/" })); + const { legacyKeyForPathname } = await import("./migratedPages"); + + expect(legacyKeyForPathname("/ui/caching/health")).toBe("caching"); + expect(legacyKeyForPathname("/ui/caching/coordination-redis/")).toBe("caching"); + expect(legacyKeyForPathname("/ui/models-and-endpoints/add")).toBe("models"); + }); + it("returns null for a not-yet-migrated path", async () => { vi.doMock("@/components/networking", () => ({ serverRootPath: "/" })); const { legacyKeyForPathname } = await import("./migratedPages"); expect(legacyKeyForPathname("/ui/")).toBeNull(); expect(legacyKeyForPathname("/ui/some-legacy-page")).toBeNull(); + expect(legacyKeyForPathname("/ui/some-legacy-page/nested")).toBeNull(); }); it("strips a non-root serverRootPath prefix before matching", async () => { diff --git a/ui/litellm-dashboard/src/utils/migratedPages.ts b/ui/litellm-dashboard/src/utils/migratedPages.ts index 73ab71ce4ac..34908a31f65 100644 --- a/ui/litellm-dashboard/src/utils/migratedPages.ts +++ b/ui/litellm-dashboard/src/utils/migratedPages.ts @@ -76,8 +76,10 @@ export function legacyPageHref(pageKey: string): string { export function legacyKeyForPathname(pathname: string): string | null { const base = uiBase(); const rel = (pathname.startsWith(base) ? pathname.slice(base.length) : pathname).replace(/^\/+|\/+$/g, ""); + const firstSegment = rel.split("/")[0] ?? ""; + if (!firstSegment) return null; for (const [key, segment] of Object.entries(MIGRATED_PAGES)) { - if (rel === segment) return key; + if (firstSegment === segment) return key; } return null; }