From 55ff0e10ebbe2c7b628f3bccea900fc3e158f636 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Sat, 25 Jul 2026 22:56:37 -0700 Subject: [PATCH] fix(ui): truncate long team names in the models table team dropdown The Team dropdown popup is pinned to the trigger width via w-(--anchor-width) and clips its overflow, while Base UI's ItemText wrapper is flex-1 shrink-0 with min-width: auto, so it sizes itself to the full nowrap label and simply overflows the popup. Teams without a team_alias render their 36-char id, so those options were sliced mid-character with no ellipsis. Clears min-width: auto off the text wrapper and truncates the label at the call site. The underlying gap is in the shared Select primitive, which any long-labelled select in the dashboard will hit; that is left for a separate change. --- .../components/AllModelsTable.test.tsx | 24 +++++++++++++++++++ .../components/AllModelsTable.tsx | 11 +++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.test.tsx index 4dc45b9f825..bc29b40dbe5 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.test.tsx @@ -358,6 +358,30 @@ describe("AllModelsTable", () => { expect(onTeamChange).toHaveBeenCalledWith("team-1"); }); + it("truncates long team options instead of clipping them at the popup edge", async () => { + const user = userEvent.setup(); + const longLabel = "db29687d-0ca2-4bbe-a0f1-9c5f0f7c2a11"; + render( + , + ); + + await user.click(screen.getByTestId("models-team-select")); + + const option = await screen.findByRole("option", { name: longLabel }); + const label = option.querySelector("[data-slot='select-item-label']"); + + expect(label).not.toBeNull(); + expect(label).toHaveClass("truncate"); + expect(label).toHaveAttribute("title", longLabel); + expect(option).toHaveClass("[&>div]:min-w-0"); + }); + it("runs the full reset from the filter drawer", async () => { const user = userEvent.setup(); const onResetFilters = vi.fn(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx index d073519d162..b42a92d9283 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx @@ -224,8 +224,15 @@ export function AllModelsTable({ {teamOptions.map((option) => ( - - {option.label} + + + {option.label} + ))}