diff --git a/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.tsx b/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.tsx index ddb2a33cdaa..6496c67a871 100644 --- a/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.tsx @@ -1,12 +1,19 @@ +import { + useBlogPosts, + type BlogPost, +} from "@/app/(dashboard)/hooks/blogPosts/useBlogPosts"; import { useDisableBlogPosts } from "@/app/(dashboard)/hooks/useDisableBlogPosts"; -import { useBlogPosts, type BlogPost } from "@/app/(dashboard)/hooks/blogPosts/useBlogPosts"; -import { LoadingOutlined } from "@ant-design/icons"; -import { Button, Dropdown, Space, Typography } from "antd"; -import type { MenuProps } from "antd"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Loader2 } from "lucide-react"; import React from "react"; -const { Text, Title, Paragraph } = Typography; - function formatDate(dateStr: string): string { const date = new Date(dateStr + "T00:00:00"); return date.toLocaleDateString("en-US", { @@ -18,66 +25,76 @@ function formatDate(dateStr: string): string { export const BlogDropdown: React.FC = () => { const disableBlogPosts = useDisableBlogPosts(); - const { data, isLoading, isError, refetch } = useBlogPosts(); if (disableBlogPosts) { return null; } - let items: MenuProps["items"]; - - if (isLoading) { - items = [{ key: "loading", label: , disabled: true }]; - } else if (isError) { - items = [ - { - key: "error", - label: ( - - Failed to load posts - + + + {isLoading ? ( +
+ +
+ ) : isError ? ( +
+ + Failed to load posts + + - - ), - disabled: true, - }, - ]; - } else if (!data || data.posts.length === 0) { - items = [{ key: "empty", label: No posts available, disabled: true }]; - } else { - items = [ - ...data.posts.slice(0, 5).map((post: BlogPost) => ({ - key: post.url, - label: ( - - - {post.title} - - - {formatDate(post.date)} - - {post.description} - - ), - })), - { type: "divider" as const }, - { - key: "view-all", - label: ( - - View all posts - - ), - }, - ]; - } - - return ( - - - +
+ ) : !data || data.posts.length === 0 ? ( +
+ No posts available +
+ ) : ( + <> + {data.posts.slice(0, 5).map((post: BlogPost) => ( + + +
+ {post.title} +
+
+ {formatDate(post.date)} +
+

+ {post.description} +

+
+
+ ))} + + + + View all posts + + + + )} +
+ ); }; diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/SSOSettingsLoadingSkeleton.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/SSOSettingsLoadingSkeleton.tsx index 59e34f255e3..06a326ed4ab 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/SSOSettingsLoadingSkeleton.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/SSOSettingsLoadingSkeleton.tsx @@ -1,66 +1,48 @@ "use client"; -import { Card, Descriptions, Skeleton, Space, Typography } from "antd"; +import { Card } from "@/components/ui/card"; +import { Skeleton } from "@/components/ui/skeleton"; import { Shield } from "lucide-react"; -const { Title, Text } = Typography; export default function SSOSettingsLoadingSkeleton() { - const descriptionsConfig = { - column: { - xxl: 1, - xl: 1, - lg: 1, - md: 1, - sm: 1, - xs: 1, - }, - }; - return ( - - - {/* Header Section */} + +
- +
- SSO Configuration - Manage Single Sign-On authentication settings +

SSO Configuration

+

+ Manage Single Sign-On authentication settings +

- - + +
- {/* Descriptions Table Skeleton */} - - {/* Provider Row */} - }> -
- +
+ {[100, 200, 250, 180, 220].map((w, i) => ( +
+
+ +
+
+ +
- - - }> - - - - }> - - - - }> - - - - }> - - - - + ))} +
+
); } diff --git a/ui/litellm-dashboard/src/components/atoms/Tooltip.tsx b/ui/litellm-dashboard/src/components/atoms/Tooltip.tsx index 5eebeaeec37..1ebf4022fac 100644 --- a/ui/litellm-dashboard/src/components/atoms/Tooltip.tsx +++ b/ui/litellm-dashboard/src/components/atoms/Tooltip.tsx @@ -1,5 +1,5 @@ import React, { useState, useRef } from "react"; -import { QuestionCircleOutlined } from "@ant-design/icons"; +import { HelpCircle } from "lucide-react"; interface TooltipProps { content: React.ReactNode; @@ -8,16 +8,26 @@ interface TooltipProps { className?: string; } -export const Tooltip: React.FC = ({ content, children, width = "auto", className = "" }) => { +/** + * Legacy custom tooltip preserved for atom-level backwards compatibility. + * For new code, use shadcn `` from @/components/ui/tooltip. + */ +export const Tooltip: React.FC = ({ + content, + children, + width = "auto", + className = "", +}) => { const [showTooltip, setShowTooltip] = useState(false); - const [tooltipPosition, setTooltipPosition] = useState<"top" | "bottom">("top"); + const [tooltipPosition, setTooltipPosition] = useState<"top" | "bottom">( + "top", + ); const tooltipRef = useRef(null); - // Function to check if tooltip would fit above const checkTooltipPosition = () => { if (tooltipRef.current) { const rect = tooltipRef.current.getBoundingClientRect(); - const tooltipHeight = 300; // Approximate height of the tooltip + const tooltipHeight = 300; const spaceAbove = rect.top; const spaceBelow = window.innerHeight - rect.bottom; @@ -32,8 +42,8 @@ export const Tooltip: React.FC = ({ content, children, width = "au return (
{children || ( - { checkTooltipPosition(); setShowTooltip(true); @@ -46,7 +56,7 @@ export const Tooltip: React.FC = ({ content, children, width = "au className={`absolute left-1/2 -translate-x-1/2 z-50 bg-black/90 text-white p-2 rounded-md text-sm font-normal shadow-lg ${className}`} style={{ [tooltipPosition === "top" ? "bottom" : "top"]: "100%", - width: width, + width, marginBottom: tooltipPosition === "top" ? "8px" : "0", marginTop: tooltipPosition === "bottom" ? "8px" : "0", }} @@ -57,8 +67,14 @@ export const Tooltip: React.FC = ({ content, children, width = "au style={{ top: tooltipPosition === "top" ? "100%" : "auto", bottom: tooltipPosition === "bottom" ? "100%" : "auto", - borderTop: tooltipPosition === "top" ? "6px solid rgba(0, 0, 0, 0.9)" : "6px solid transparent", - borderBottom: tooltipPosition === "bottom" ? "6px solid rgba(0, 0, 0, 0.9)" : "6px solid transparent", + borderTop: + tooltipPosition === "top" + ? "6px solid rgba(0, 0, 0, 0.9)" + : "6px solid transparent", + borderBottom: + tooltipPosition === "bottom" + ? "6px solid rgba(0, 0, 0, 0.9)" + : "6px solid transparent", borderLeft: "6px solid transparent", borderRight: "6px solid transparent", }}