diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.integration.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.integration.test.tsx
index d4fbb7e153e..3de88fb6f57 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.integration.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.integration.test.tsx
@@ -40,7 +40,7 @@ vi.mock("@/components/llm_calls/fetch_models", () => ({
fetchAvailableModels: vi.fn().mockResolvedValue([]),
}));
-vi.mock("@/components/HelpLink", () => ({
+vi.mock("@/components/DocsMenu", () => ({
DocsMenu: () => null,
}));
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.test.tsx
index a8609aef629..50c8c12c9c2 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.test.tsx
@@ -41,7 +41,7 @@ vi.mock("@/components/llm_calls/fetch_models", () => ({
fetchAvailableModels: vi.fn().mockResolvedValue([]),
}));
-vi.mock("@/components/HelpLink", () => ({
+vi.mock("@/components/DocsMenu", () => ({
DocsMenu: () => null,
}));
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.tsx
index 52b66edcbe5..b8e51939dd0 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/_components/cost_tracking_settings.tsx
@@ -19,7 +19,7 @@ import AddProviderForm from "./add_provider_form";
import ProviderMarginTable from "./provider_margin_table";
import AddMarginForm from "./add_margin_form";
import PricingCalculator from "./pricing_calculator/index";
-import { DocsMenu } from "@/components/HelpLink";
+import { DocsMenu } from "@/components/DocsMenu";
import HowItWorks from "./how_it_works";
import { useDiscountConfig } from "./use_discount_config";
import { useMarginConfig } from "./use_margin_config";
diff --git a/ui/litellm-dashboard/src/components/DocsMenu.test.tsx b/ui/litellm-dashboard/src/components/DocsMenu.test.tsx
new file mode 100644
index 00000000000..327f1368b5f
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/DocsMenu.test.tsx
@@ -0,0 +1,69 @@
+import React from "react";
+import { describe, it, expect } from "vitest";
+import { screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { renderWithProviders } from "../../tests/test-utils";
+import { DocsMenu } from "./DocsMenu";
+
+describe("DocsMenu", () => {
+ const items = [
+ { label: "Custom pricing", href: "https://docs.example.com/pricing" },
+ { label: "Cost tracking", href: "https://docs.example.com/cost" },
+ ];
+
+ it("should render the menu button with default text", () => {
+ renderWithProviders();
+
+ expect(screen.getByRole("button", { name: /docs/i })).toBeInTheDocument();
+ });
+
+ it("should hide menu items initially", () => {
+ renderWithProviders();
+ expect(screen.queryByText("Custom pricing")).not.toBeInTheDocument();
+ });
+
+ it("should show menu items when button is clicked", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ await user.click(screen.getByRole("button", { name: /docs/i }));
+
+ expect(screen.getByText("Custom pricing")).toBeInTheDocument();
+ expect(screen.getByText("Cost tracking")).toBeInTheDocument();
+ });
+
+ it("should close the menu when an item is clicked", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ await user.click(screen.getByRole("button", { name: /docs/i }));
+ await user.click(screen.getByText("Custom pricing"));
+
+ expect(screen.queryByText("Cost tracking")).not.toBeInTheDocument();
+ });
+
+ it("should set aria-expanded correctly based on menu state", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const button = screen.getByRole("button", { name: /docs/i });
+ expect(button).toHaveAttribute("aria-expanded", "false");
+
+ await user.click(button);
+ expect(button).toHaveAttribute("aria-expanded", "true");
+ });
+
+ it("should close menu when clicking outside", async () => {
+ const user = userEvent.setup();
+ renderWithProviders(
+
+
+
+
,
+ );
+ await user.click(screen.getByRole("button", { name: /docs/i }));
+ expect(screen.getByText("Custom pricing")).toBeInTheDocument();
+ await user.click(screen.getByRole("button", { name: /outside/i }));
+ expect(screen.queryByText("Custom pricing")).not.toBeInTheDocument();
+ });
+});
diff --git a/ui/litellm-dashboard/src/components/DocsMenu.tsx b/ui/litellm-dashboard/src/components/DocsMenu.tsx
new file mode 100644
index 00000000000..81958f70683
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/DocsMenu.tsx
@@ -0,0 +1,67 @@
+import React, { useState, useRef, useEffect } from "react";
+import { ExternalLink, ChevronDown } from "lucide-react";
+
+interface DocMenuItem {
+ label: string;
+ href: string;
+}
+
+interface DocsMenuProps {
+ items: DocMenuItem[];
+ children?: React.ReactNode;
+ className?: string;
+}
+
+export const DocsMenu: React.FC = ({ items, children = "Docs", className = "" }) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const menuRef = useRef(null);
+
+ useEffect(() => {
+ const handleClickOutside = (event: MouseEvent) => {
+ if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+ setIsOpen(false);
+ }
+ };
+
+ if (isOpen) {
+ document.addEventListener("mousedown", handleClickOutside);
+ }
+
+ return () => {
+ document.removeEventListener("mousedown", handleClickOutside);
+ };
+ }, [isOpen]);
+
+ return (
+
+
+
+ {isOpen && (
+
+ )}
+
+ );
+};
diff --git a/ui/litellm-dashboard/src/components/HelpLink.test.tsx b/ui/litellm-dashboard/src/components/HelpLink.test.tsx
deleted file mode 100644
index e502126477a..00000000000
--- a/ui/litellm-dashboard/src/components/HelpLink.test.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import React from "react";
-import { describe, it, expect } from "vitest";
-import { screen } from "@testing-library/react";
-import userEvent from "@testing-library/user-event";
-import { renderWithProviders } from "../../tests/test-utils";
-import { HelpLink, HelpIcon, DocsMenu } from "./HelpLink";
-
-describe("HelpLink", () => {
- it("should render with default children and open in new tab", () => {
- renderWithProviders();
-
- const link = screen.getByRole("link", { name: /learn more/i });
- expect(link).toHaveAttribute("href", "https://docs.example.com");
- expect(link).toHaveAttribute("target", "_blank");
- expect(link).toHaveAttribute("rel", "noopener noreferrer");
- });
-
- it("should render custom children text", () => {
- renderWithProviders(Custom docs link);
-
- expect(screen.getByText("Custom docs link")).toBeInTheDocument();
- });
-
- it("should have the correct href", () => {
- renderWithProviders();
- expect(screen.getByRole("link")).toHaveAttribute("href", "https://docs.example.com/test");
- });
-
- it("should include a screen-reader-only label for accessibility", () => {
- renderWithProviders();
-
- expect(screen.getByText("(opens in a new tab)")).toBeInTheDocument();
- });
-});
-
-describe("HelpIcon", () => {
- it("should render a help button with accessible label", () => {
- renderWithProviders();
-
- expect(screen.getByRole("button", { name: /help information/i })).toBeInTheDocument();
- });
-
- it("should show tooltip content on hover", async () => {
- const user = userEvent.setup();
- renderWithProviders();
-
- await user.hover(screen.getByRole("button", { name: /help information/i }));
-
- expect(screen.getByText("Tooltip help text")).toBeInTheDocument();
- });
-
- it("should hide tooltip content when not hovered", () => {
- renderWithProviders();
- expect(screen.queryByText("Hidden tooltip")).not.toBeInTheDocument();
- });
-
- it("should show learn more link when learnMoreHref is provided", async () => {
- const user = userEvent.setup();
- renderWithProviders();
- await user.hover(screen.getByRole("button", { name: /help information/i }));
- expect(screen.getByText("Learn more")).toBeInTheDocument();
- });
-
- it("should use custom learn more text when provided", async () => {
- const user = userEvent.setup();
- renderWithProviders(
- ,
- );
-
- await user.hover(screen.getByRole("button", { name: /help information/i }));
-
- const link = screen.getByRole("link", { name: /read docs/i });
- expect(link).toHaveAttribute("href", "https://docs.example.com");
- });
-
- it("should not show learn more link when learnMoreHref is not provided", async () => {
- const user = userEvent.setup();
- renderWithProviders();
-
- await user.hover(screen.getByRole("button", { name: /help information/i }));
-
- expect(screen.queryByRole("link")).not.toBeInTheDocument();
- });
-});
-
-describe("DocsMenu", () => {
- const items = [
- { label: "Custom pricing", href: "https://docs.example.com/pricing" },
- { label: "Cost tracking", href: "https://docs.example.com/cost" },
- ];
-
- it("should render the menu button with default text", () => {
- renderWithProviders();
-
- expect(screen.getByRole("button", { name: /docs/i })).toBeInTheDocument();
- });
-
- it("should hide menu items initially", () => {
- renderWithProviders();
- expect(screen.queryByText("Custom pricing")).not.toBeInTheDocument();
- });
-
- it("should show menu items when button is clicked", async () => {
- const user = userEvent.setup();
- renderWithProviders();
-
- await user.click(screen.getByRole("button", { name: /docs/i }));
-
- expect(screen.getByText("Custom pricing")).toBeInTheDocument();
- expect(screen.getByText("Cost tracking")).toBeInTheDocument();
- });
-
- it("should close the menu when an item is clicked", async () => {
- const user = userEvent.setup();
- renderWithProviders();
-
- await user.click(screen.getByRole("button", { name: /docs/i }));
- await user.click(screen.getByText("Custom pricing"));
-
- expect(screen.queryByText("Cost tracking")).not.toBeInTheDocument();
- });
-
- it("should set aria-expanded correctly based on menu state", async () => {
- const user = userEvent.setup();
- renderWithProviders();
-
- const button = screen.getByRole("button", { name: /docs/i });
- expect(button).toHaveAttribute("aria-expanded", "false");
-
- await user.click(button);
- expect(button).toHaveAttribute("aria-expanded", "true");
- });
-
- it("should close menu when clicking outside", async () => {
- const user = userEvent.setup();
- renderWithProviders(
-
-
-
-
,
- );
- await user.click(screen.getByRole("button", { name: /docs/i }));
- expect(screen.getByText("Custom pricing")).toBeInTheDocument();
- await user.click(screen.getByRole("button", { name: /outside/i }));
- expect(screen.queryByText("Custom pricing")).not.toBeInTheDocument();
- });
-});
diff --git a/ui/litellm-dashboard/src/components/HelpLink.tsx b/ui/litellm-dashboard/src/components/HelpLink.tsx
deleted file mode 100644
index 35e2e5f535f..00000000000
--- a/ui/litellm-dashboard/src/components/HelpLink.tsx
+++ /dev/null
@@ -1,199 +0,0 @@
-import React, { useState, useRef, useEffect } from "react";
-import { ExternalLink, ChevronDown } from "lucide-react";
-
-interface HelpLinkProps {
- href: string;
- children?: React.ReactNode;
- variant?: "inline" | "subtle" | "button";
- className?: string;
-}
-
-interface DocMenuItem {
- label: string;
- href: string;
-}
-
-interface DocsMenuProps {
- items: DocMenuItem[];
- children?: React.ReactNode;
- className?: string;
-}
-
-/**
- * A reusable component for linking to documentation, styled similar to Linear's help links.
- *
- * @example
- * // Inline "Learn more" style
- *
- * Learn more about custom pricing
- *
- *
- * @example
- * // Subtle link (just icon + text, minimal styling)
- *
- * View docs
- *
- *
- * @example
- * // Button style (more prominent)
- *
- * Custom Pricing Documentation
- *
- */
-export const HelpLink: React.FC = ({
- href,
- children = "Learn more",
- variant = "inline",
- className = "",
-}) => {
- const baseClasses =
- "inline-flex items-center gap-1.5 transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-1 rounded-sm";
-
- const variantClasses = {
- inline: "text-info text-sm font-medium hover:underline",
- subtle: "text-muted-foreground hover:text-foreground text-xs",
- button:
- "text-info border border-border px-3 py-1.5 rounded-md bg-card hover:bg-accent text-sm font-medium shadow-xs",
- };
-
- return (
-
- {children}
-
- (opens in a new tab)
-
- );
-};
-
-/**
- * A minimal help icon with tooltip for inline contextual help.
- * Similar to Linear's "?" icons that appear next to labels.
- */
-interface HelpIconProps {
- content: React.ReactNode;
- learnMoreHref?: string;
- learnMoreText?: string;
-}
-
-export const HelpIcon: React.FC = ({ content, learnMoreHref, learnMoreText = "Learn more" }) => {
- const [showTooltip, setShowTooltip] = React.useState(false);
-
- return (
-
-
- {showTooltip && (
-
- )}
-
- );
-};
-
-/**
- * A dropdown menu for multiple documentation links.
- * Linear-style: Single "Docs" button that expands to show multiple relevant links.
- *
- * @example
- *
- * Docs
- *
- */
-export const DocsMenu: React.FC = ({ items, children = "Docs", className = "" }) => {
- const [isOpen, setIsOpen] = useState(false);
- const menuRef = useRef(null);
-
- useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
- setIsOpen(false);
- }
- };
-
- if (isOpen) {
- document.addEventListener("mousedown", handleClickOutside);
- }
-
- return () => {
- document.removeEventListener("mousedown", handleClickOutside);
- };
- }, [isOpen]);
-
- return (
-
-
-
- {isOpen && (
-
- )}
-
- );
-};