mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-20 00:11:50 +00:00
refactor(ui): remove unused HelpLink and HelpIcon components
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
decbb96382
commit
9cbad58a70
2 changed files with 1 additions and 199 deletions
|
|
@ -3,85 +3,7 @@ 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(<HelpLink href="https://docs.example.com" />);
|
||||
|
||||
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(<HelpLink href="https://docs.example.com">Custom docs link</HelpLink>);
|
||||
|
||||
expect(screen.getByText("Custom docs link")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should have the correct href", () => {
|
||||
renderWithProviders(<HelpLink href="https://docs.example.com/test" />);
|
||||
expect(screen.getByRole("link")).toHaveAttribute("href", "https://docs.example.com/test");
|
||||
});
|
||||
|
||||
it("should include a screen-reader-only label for accessibility", () => {
|
||||
renderWithProviders(<HelpLink href="https://docs.example.com" />);
|
||||
|
||||
expect(screen.getByText("(opens in a new tab)")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("HelpIcon", () => {
|
||||
it("should render a help button with accessible label", () => {
|
||||
renderWithProviders(<HelpIcon content="Some help text" />);
|
||||
|
||||
expect(screen.getByRole("button", { name: /help information/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should show tooltip content on hover", async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<HelpIcon content="Tooltip help text" />);
|
||||
|
||||
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(<HelpIcon content="Hidden tooltip" />);
|
||||
expect(screen.queryByText("Hidden tooltip")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should show learn more link when learnMoreHref is provided", async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<HelpIcon content="Help text" learnMoreHref="https://docs.example.com" />);
|
||||
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(
|
||||
<HelpIcon content="Help text" learnMoreHref="https://docs.example.com" learnMoreText="Read docs" />,
|
||||
);
|
||||
|
||||
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(<HelpIcon content="Help text" />);
|
||||
|
||||
await user.hover(screen.getByRole("button", { name: /help information/i }));
|
||||
|
||||
expect(screen.queryByRole("link")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
import { DocsMenu } from "./HelpLink";
|
||||
|
||||
describe("DocsMenu", () => {
|
||||
const items = [
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
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;
|
||||
|
|
@ -19,119 +12,6 @@ interface DocsMenuProps {
|
|||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A reusable component for linking to documentation, styled similar to Linear's help links.
|
||||
*
|
||||
* @example
|
||||
* // Inline "Learn more" style
|
||||
* <HelpLink href="https://docs.litellm.ai/docs/proxy/custom_pricing">
|
||||
* Learn more about custom pricing
|
||||
* </HelpLink>
|
||||
*
|
||||
* @example
|
||||
* // Subtle link (just icon + text, minimal styling)
|
||||
* <HelpLink href="https://docs.litellm.ai/docs/proxy/cost_tracking" variant="subtle">
|
||||
* View docs
|
||||
* </HelpLink>
|
||||
*
|
||||
* @example
|
||||
* // Button style (more prominent)
|
||||
* <HelpLink href="https://docs.litellm.ai/docs/proxy/custom_pricing" variant="button">
|
||||
* Custom Pricing Documentation
|
||||
* </HelpLink>
|
||||
*/
|
||||
export const HelpLink: React.FC<HelpLinkProps> = ({
|
||||
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 (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`${baseClasses} ${variantClasses[variant]} ${className}`}
|
||||
title="Open documentation in a new tab"
|
||||
>
|
||||
<span>{children}</span>
|
||||
<ExternalLink className="h-3.5 w-3.5 shrink-0" aria-hidden="true" />
|
||||
<span className="sr-only">(opens in a new tab)</span>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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<HelpIconProps> = ({ content, learnMoreHref, learnMoreText = "Learn more" }) => {
|
||||
const [showTooltip, setShowTooltip] = React.useState(false);
|
||||
|
||||
return (
|
||||
<div className="relative inline-block ml-1.5">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center w-4 h-4 text-muted-foreground hover:text-foreground transition-colors cursor-help focus:outline-hidden focus:ring-2 focus:ring-ring rounded-full"
|
||||
onMouseEnter={() => setShowTooltip(true)}
|
||||
onMouseLeave={() => setShowTooltip(false)}
|
||||
onFocus={() => setShowTooltip(true)}
|
||||
onBlur={() => setShowTooltip(false)}
|
||||
aria-label="Help information"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="10" strokeWidth="1.5" />
|
||||
<path strokeLinecap="round" d="M12 17h0M12 13.5a1.5 1.5 0 0 1 1-1.415A1.5 1.5 0 1 0 12 9" strokeWidth="1.5" />
|
||||
</svg>
|
||||
</button>
|
||||
{showTooltip && (
|
||||
<div
|
||||
className="absolute left-1/2 -translate-x-1/2 bottom-full mb-2 z-floating bg-gray-900 text-white p-3 rounded-lg text-xs shadow-lg w-64"
|
||||
style={{ pointerEvents: "none" }}
|
||||
>
|
||||
<div className="mb-2">{content}</div>
|
||||
{learnMoreHref && (
|
||||
<a
|
||||
href={learnMoreHref}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 text-info hover:text-blue-200 font-medium"
|
||||
style={{ pointerEvents: "auto" }}
|
||||
>
|
||||
{learnMoreText}
|
||||
<ExternalLink className="h-3 w-3" aria-hidden="true" />
|
||||
</a>
|
||||
)}
|
||||
<div
|
||||
className="absolute left-1/2 -translate-x-1/2 top-full w-0 h-0"
|
||||
style={{
|
||||
borderTop: "6px solid rgb(17 24 39)",
|
||||
borderLeft: "6px solid transparent",
|
||||
borderRight: "6px solid transparent",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* A dropdown menu for multiple documentation links.
|
||||
* Linear-style: Single "Docs" button that expands to show multiple relevant links.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue