From 929946bdc17e375946ebea27e216302425d3c641 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Thu, 27 Aug 2026 20:50:41 -0700 Subject: [PATCH] fix(ui): give the shared product-link class a focus ring Docs went from a ghost Button to a plain anchor, which dropped the focus treatment the Button was supplying, so tabbing to Docs showed nothing while tabbing to Blog showed a ring. The ring now lives on the shared class both sides use, matching the Button primitive's values. Kept Docs as a real anchor rather than routing it back through Button: nativeButton={false} stamps role="button" onto the element, so the old DashboardHeader markup announced Docs as a button and lost its link semantics. Tests pin both the ring and the link role. --- .../components/Navbar/DocsLink/DocsLink.test.tsx | 15 +++++++++++++++ .../src/components/Navbar/DocsLink/DocsLink.tsx | 7 +++++-- .../src/components/Navbar/navProductLinkClass.ts | 4 ++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.test.tsx b/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.test.tsx index d5a155cf503..dec76041802 100644 --- a/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.test.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.test.tsx @@ -24,4 +24,19 @@ describe("DocsLink", () => { } expect(link).not.toHaveClass("text-muted-foreground"); }); + + it("carries a focus ring, so tabbing to Docs looks like tabbing to Blog", () => { + render(); + + const link = screen.getByRole("link", { name: "Docs" }); + expect(link).toHaveClass("focus-visible:ring-3"); + expect(link).toHaveClass("focus-visible:ring-ring/50"); + }); + + it("stays a link rather than being relabelled as a button by the Button primitive", () => { + render(); + + expect(screen.getByRole("link", { name: "Docs" })).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Docs" })).not.toBeInTheDocument(); + }); }); diff --git a/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.tsx b/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.tsx index 9176e1f9c38..9b4f4c90b64 100644 --- a/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/DocsLink/DocsLink.tsx @@ -4,11 +4,14 @@ import React from "react"; export const DOCS_URL = "https://docs.litellm.ai/docs/"; +const ChevronWidthSpacer: React.FC = () => ( + +); + export const DocsLink: React.FC = () => ( Docs - {/* Docs is a single outbound link; the hidden chevron keeps its box identical to the Blog dropdown trigger. */} - + ); diff --git a/ui/litellm-dashboard/src/components/Navbar/navProductLinkClass.ts b/ui/litellm-dashboard/src/components/Navbar/navProductLinkClass.ts index e0fd000ab97..56b0d51401d 100644 --- a/ui/litellm-dashboard/src/components/Navbar/navProductLinkClass.ts +++ b/ui/litellm-dashboard/src/components/Navbar/navProductLinkClass.ts @@ -1,3 +1,3 @@ -/** Shared styling for Docs / Blog in the top nav (product navigation zone). */ +/** Shared styling for Docs / Blog in the top nav (product navigation zone). Focus ring matches the Button primitive. */ export const NAV_PRODUCT_LINK_CLASS = - "inline-flex h-9 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-sm font-medium leading-none text-foreground transition-colors hover:bg-accent "; + "inline-flex h-9 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-sm font-medium leading-none text-foreground outline-none transition-colors hover:bg-accent focus-visible:ring-3 focus-visible:ring-ring/50 ";