From de25e199d446d12f1995235f739a6172a51ce51a Mon Sep 17 00:00:00 2001
From: Yuneng Jiang
Date: Sat, 15 Aug 2026 00:33:20 -0700
Subject: [PATCH] fix(ui): de-duplicate the reset budget option and polish
shadcn surfaces
Create Key offered two options labelled "Never resets" in the Reset Budget
dropdown. BudgetDurationDropdown renders its unset item using the caller's
placeholder, and create_key_button passed placeholder="Never resets" alongside
showNeverResets, so the omit option and the explicit-null option looked
identical while behaving differently. An omitted budget_duration picks up
default_key_generate_params and the linked budget tier's schedule, whereas the
"none" sentinel is converted to an explicit null and truly never resets. The
unset item now reads "Not set", matching getBudgetDurationLabel, and the
create-key test mock passes the placeholder through so a future collision fails
the suite
The rest is migration cleanup found during manual QA. The models and endpoints
tab strip hides its scrollbar and fades at the right edge using a vendored copy
of the shadcn scroll-fade utility, keeping the CLI package out of the build.
globals.css neutralises the @tailwindcss/forms resting-state rules for
combobox-chip-input, which lets twelve call sites drop the same copy-pasted
className workaround. Guardrails moves to the line tab variant and stops
clipping its textarea focus ring, the log drawer JSON tree takes the app
background, the audit log empty state centres, the caching page selects no
longer stretch to the row height, the usage page team filter shares its row
with the Export button through a new filterSlot prop, and the cost optimization
and vector store tab strips drop their leftover full-width divider
---
ui/litellm-dashboard/eslint-suppressions.json | 5 ++
.../caching/_components/cache_dashboard.tsx | 6 +-
.../_components/CostOptimizationView.tsx | 2 +-
.../_components/GuardrailTestPanel.tsx | 2 +-
.../_components/GuardrailsPanel.tsx | 2 +-
.../custom_code/CustomCodeModal.tsx | 5 +-
.../guardrails/_components/pii_components.tsx | 1 -
.../(dashboard)/models-and-endpoints/page.tsx | 2 +-
.../old-usage/_components/usage.tsx | 2 +-
.../components/chat_ui/ChatComposer.tsx | 7 +-
.../src/app/(dashboard)/playground/page.tsx | 13 ++-
.../components/EntityUsage/EntityUsage.tsx | 11 +--
.../vector-stores/_components/index.tsx | 2 +-
ui/litellm-dashboard/src/app/globals.css | 72 +++++++++++++++
.../EntityUsageExport/UsageExportHeader.tsx | 87 ++++++++++---------
.../components/ModelSelect/ModelSelect.tsx | 6 +-
.../CommunityEngagementButtons.tsx | 80 +++++++++--------
.../src/components/TeamSSOSettings.tsx | 6 +-
.../common_components/team_multi_select.tsx | 7 +-
.../organisms/create_key_button.test.tsx | 25 +++++-
.../organisms/create_key_button.tsx | 2 +-
.../src/components/public_model_hub.tsx | 2 +-
.../search_tools/SearchToolSelector.tsx | 7 +-
.../components/shared/DataTable/DataTable.tsx | 5 +-
.../src/components/shared/MultiSelect.tsx | 2 +-
.../src/components/ui/button-group.tsx | 76 ++++++++++++++++
.../src/components/user_agent_activity.tsx | 6 +-
.../view_logs/LogDetailsDrawer/JsonViewer.tsx | 6 +-
28 files changed, 295 insertions(+), 154 deletions(-)
create mode 100644 ui/litellm-dashboard/src/components/ui/button-group.tsx
diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json
index 2b903f763d9..4a6d7006893 100644
--- a/ui/litellm-dashboard/eslint-suppressions.json
+++ b/ui/litellm-dashboard/eslint-suppressions.json
@@ -2974,6 +2974,11 @@
"count": 1
}
},
+ "src/components/ui/button-group.tsx": {
+ "local/filename-pascal-case": {
+ "count": 1
+ }
+ },
"src/components/ui/button.tsx": {
"local/filename-pascal-case": {
"count": 1
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_dashboard.tsx b/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_dashboard.tsx
index 6759a9af63f..c1a4968f58b 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_dashboard.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_dashboard.tsx
@@ -190,7 +190,7 @@ const CacheDashboard: React.FC = ({ accessToken, token, userRole
Metrics" on the Usage page or individual requests in the Logs page.
-
+
= ({ accessToken, token, userRole
))
}
-
+
No virtual keys found
@@ -237,7 +237,7 @@ const CacheDashboard: React.FC = ({ accessToken, token, userRole
))
}
-
+
No models found
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx
index 702bb5b8034..8122cfa7a9c 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx
@@ -63,7 +63,7 @@ const CostOptimizationView: React.FC = ({ accessToken
-
+
Overall
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailTestPanel.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailTestPanel.tsx
index 8297c1e1e3b..5c79a2292a2 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailTestPanel.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailTestPanel.tsx
@@ -131,7 +131,7 @@ export function GuardrailTestPanel({
{/* Input Section */}
-
+
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailsPanel.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailsPanel.tsx
index 9df2fa04c04..80267f97a94 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailsPanel.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/GuardrailsPanel.tsx
@@ -126,7 +126,7 @@ const GuardrailsPanel: React.FC
= ({ accessToken, userRole
return (
-
+
{isAdmin && (
<>
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/custom_code/CustomCodeModal.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/custom_code/CustomCodeModal.tsx
index 1497c789cb4..5015884de31 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/custom_code/CustomCodeModal.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/custom_code/CustomCodeModal.tsx
@@ -532,10 +532,7 @@ const CustomCodeModal: React.FC = ({ visible, onClose, onS
{option.label}
))}
-
+
No matching modes
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/pii_components.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/pii_components.tsx
index 6994f43772c..5f8e833af8d 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/pii_components.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/pii_components.tsx
@@ -59,7 +59,6 @@ export const CategoryFilter: React.FC = ({ categories, sele
))}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx
index 998f65629e0..94737d88d0f 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx
@@ -175,7 +175,7 @@ export default function ModelsAndEndpointsPage() {
) : (
-
+
{visibleSlugs.map((slug) => {
const key = slug || BASE_TAB_KEY;
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/old-usage/_components/usage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/old-usage/_components/usage.tsx
index 7ddf2622c7a..a0835729f1b 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/old-usage/_components/usage.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/old-usage/_components/usage.tsx
@@ -891,7 +891,7 @@ const UsagePage: React.FC = ({ accessToken, token, userRole, use
))
}
-
+
No tags found
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatComposer.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatComposer.tsx
index cc541c939ad..934e502492e 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatComposer.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatComposer.tsx
@@ -54,15 +54,12 @@ export function ChatComposer({
return (
{showSuggestions && suggestions.length > 0 && (
-
+
{suggestions.map((suggestion) => (
onSuggestionSelect?.(suggestion)}
>
{suggestion}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/page.tsx
index 845db38d445..d61ba2fc899 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/playground/page.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/page.tsx
@@ -49,20 +49,17 @@ export default function PlaygroundPage() {
return (
-
-
+
+
Chat
-
+
Compare
-
+
Compliance
-
+
Agent Builder (Experimental)
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx
index c69764df471..928337010f7 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx
@@ -675,18 +675,15 @@ const EntityUsage: React.FC = ({
)}
- {entityType === "team" && (
-
- )}
0}
- filterLabel={getFilterLabel(entityType)}
+ filterSlot={
+ entityType === "team" ? : undefined
+ }
+ filterLabel={entityType === "team" ? "Filter by team" : getFilterLabel(entityType)}
filterPlaceholder={getFilterPlaceholder(entityType)}
selectedFilters={selectedTags}
onFiltersChange={setSelectedTags}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/index.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/index.tsx
index 1e526131fa3..b19c5f4694c 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/index.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/index.tsx
@@ -154,7 +154,7 @@ const VectorStoreManagement: React.FC = ({ accessToken, userID
-
+
Create Vector Store
diff --git a/ui/litellm-dashboard/src/app/globals.css b/ui/litellm-dashboard/src/app/globals.css
index 7013e502c22..dddeb576720 100644
--- a/ui/litellm-dashboard/src/app/globals.css
+++ b/ui/litellm-dashboard/src/app/globals.css
@@ -30,6 +30,54 @@
}
}
+/* Verbatim end-edge subset of the shadcn scroll-fade utility (shadcn@4.17.0 dist/tailwind.css),
+ vendored so the CLI package is not a build dependency. Re-copy from upstream to update. */
+@property --scroll-fade-e {
+ syntax: "";
+ inherits: false;
+ initial-value: 0px;
+}
+@property --scroll-fade-mask {
+ syntax: "*";
+ inherits: false;
+}
+
+@theme inline {
+ @keyframes scroll-fade-reveal-e {
+ from {
+ --scroll-fade-e: var(--_scroll-fade-size-e, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
+ }
+ to {
+ --scroll-fade-e: 0px;
+ }
+ }
+}
+
+@utility scroll-fade-e {
+ --_scroll-fade-size-e: var(--scroll-fade-e-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
+ --scroll-fade-mask: linear-gradient(to right, #000 0, #000 calc(100% - var(--scroll-fade-e, 0px)), transparent 100%);
+ &:where([dir="rtl"], [dir="rtl"] *) {
+ --scroll-fade-mask: linear-gradient(to left, #000 0, #000 calc(100% - var(--scroll-fade-e, 0px)), transparent 100%);
+ }
+ -webkit-mask-image: var(--scroll-fade-mask);
+ mask-image: var(--scroll-fade-mask);
+ -webkit-mask-composite: source-in;
+ mask-composite: intersect;
+ -webkit-mask-repeat: no-repeat;
+ mask-repeat: no-repeat;
+
+ @supports (animation-timeline: scroll()) {
+ animation: scroll-fade-reveal-e 1ms ease-in-out;
+ animation-timeline: scroll(self inline);
+ animation-range: calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
+ animation-fill-mode: both;
+ }
+
+ @supports not (animation-timeline: scroll()) {
+ --scroll-fade-e: var(--_scroll-fade-size-e);
+ }
+}
+
:root {
--radius: 0.5rem;
--background: oklch(1 0 0);
@@ -211,6 +259,30 @@
outline-color: color-mix(in oklab, var(--color-ring) 50%, transparent);
}
+ /* @tailwindcss/forms paints a 1px blue-600 ring via box-shadow on :focus, which `outline-none`
+ cannot cancel. Components that declare their own focus ring override this from the utilities
+ layer; the ones that do not inherit a blue rectangle. `:not([disabled])` is here only to
+ outweigh the plugin's own (0,1,1) selector, which Tailwind emits after this block. Delete
+ along with the plugin once no route renders a Tremor form control. */
+ :is(input, textarea, select):focus:not([disabled]) {
+ --tw-ring-color: initial;
+ --tw-ring-shadow: 0 0 #0000;
+ border-color: var(--color-border);
+ }
+
+ /* Same plugin, resting state: it also gives every bare input a border, a white fill, 0.5rem/0.75rem
+ padding and 1rem text. shadcn primitives style themselves and only break where a base class omits
+ those, which today is `combobox-chip-input` alone (audited against every input-rendering file in
+ components/ui). These values restore Tailwind's own preflight, and `[data-slot]` outweighs the
+ plugin's zero-specificity `input:where(:not([type]))`. Delete along with the plugin. */
+ [data-slot="combobox-chip-input"] {
+ border-width: 0;
+ background-color: transparent;
+ padding: 0;
+ font: inherit;
+ letter-spacing: inherit;
+ }
+
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
diff --git a/ui/litellm-dashboard/src/components/EntityUsageExport/UsageExportHeader.tsx b/ui/litellm-dashboard/src/components/EntityUsageExport/UsageExportHeader.tsx
index 772a5a766e6..db386af1ffd 100644
--- a/ui/litellm-dashboard/src/components/EntityUsageExport/UsageExportHeader.tsx
+++ b/ui/litellm-dashboard/src/components/EntityUsageExport/UsageExportHeader.tsx
@@ -32,6 +32,7 @@ interface UsageExportHeaderProps {
onFiltersChange?: (filters: string[]) => void;
filterOptions?: Array<{ label: string; value: string }>;
filterMode?: "multiple" | "single";
+ filterSlot?: React.ReactNode;
customTitle?: string;
compactLayout?: boolean;
teams?: Team[];
@@ -48,6 +49,7 @@ const UsageExportHeader: React.FC = ({
onFiltersChange,
filterOptions = [],
filterMode = "multiple",
+ filterSlot,
customTitle,
compactLayout = false,
teams = [],
@@ -55,7 +57,7 @@ const UsageExportHeader: React.FC = ({
const anchor = useComboboxAnchor();
const [isExportModalOpen, setIsExportModalOpen] = useState(false);
- const hasFilters = showFilters && filterOptions.length > 0;
+ const hasFilters = filterSlot != null || (showFilters && filterOptions.length > 0);
const optionValues = filterOptions.map((option) => option.value);
const labelOf = (value: string) => filterOptions.find((option) => option.value === value)?.label ?? value;
@@ -72,6 +74,46 @@ const UsageExportHeader: React.FC = ({
);
+ const builtInFilter =
+ filterMode === "single" ? (
+ onFiltersChange?.(next ? [next] : [])}
+ itemToStringLabel={labelOf}
+ >
+ 0}
+ />
+ {filterList}
+
+ ) : (
+ onFiltersChange?.(next)}
+ >
+ } className="w-full">
+
+ {(selected: string[]) =>
+ selected.map((value) => (
+
+ {labelOf(value)}
+
+ ))
+ }
+
+
+ {selectedFilters.length > 0 && }
+
+ {filterList}
+
+ );
+
return (
<>
@@ -84,48 +126,7 @@ const UsageExportHeader: React.FC
= ({
{hasFilters && (
{filterLabel && {filterLabel} }
- {filterMode === "single" ? (
- onFiltersChange?.(next ? [next] : [])}
- itemToStringLabel={labelOf}
- >
- 0}
- />
- {filterList}
-
- ) : (
- onFiltersChange?.(next)}
- >
- } className="w-full">
-
- {(selected: string[]) =>
- selected.map((value) => (
-
- {labelOf(value)}
-
- ))
- }
-
-
- {selectedFilters.length > 0 && }
-
- {filterList}
-
- )}
+ {filterSlot ?? builtInFilter}
)}
diff --git a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx
index 6c4386aec71..d3ede5f4318 100644
--- a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx
+++ b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx
@@ -256,11 +256,7 @@ export const ModelSelect = (props: ModelSelectProps) => {
>
)}
-
+
No models found
diff --git a/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx b/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx
index 8ec31d74cd6..6e84f22a2a2 100644
--- a/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx
+++ b/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx
@@ -1,10 +1,25 @@
import { useDisableShowPrompts } from "@/app/(dashboard)/hooks/useDisableShowPrompts";
+import { buttonVariants } from "@/components/ui/button";
+import { ButtonGroup } from "@/components/ui/button-group";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
+import { cn } from "@/lib/cva.config";
import { Github, Slack } from "lucide-react";
import React from "react";
-const iconBtnClass =
- "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md border-0 bg-transparent text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700 cursor-pointer";
+const COMMUNITY_LINKS = [
+ {
+ href: "https://www.litellm.ai/support",
+ label: "Join Slack",
+ tooltip: "LiteLLM Slack community",
+ Icon: Slack,
+ },
+ {
+ href: "https://github.com/BerriAI/litellm",
+ label: "LiteLLM on GitHub",
+ tooltip: "LiteLLM on GitHub",
+ Icon: Github,
+ },
+] as const;
export const CommunityEngagementButtons: React.FC = () => {
const disableShowPrompts = useDisableShowPrompts();
@@ -14,44 +29,27 @@ export const CommunityEngagementButtons: React.FC = () => {
}
return (
-
-
-
-
- }
- >
-
-
- LiteLLM Slack community
-
-
-
- }
- >
-
-
- LiteLLM on GitHub
-
-
-
+
+
+ {COMMUNITY_LINKS.map(({ href, label, tooltip, Icon }) => (
+
+
+ }
+ >
+
+
+ {tooltip}
+
+ ))}
+
+
);
};
diff --git a/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx b/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx
index 1009e5cd7b0..7845203411a 100644
--- a/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx
+++ b/ui/litellm-dashboard/src/components/TeamSSOSettings.tsx
@@ -384,11 +384,7 @@ const TeamSSOSettings: React.FC = ({ accessToken }) => {
))
}
-
+
diff --git a/ui/litellm-dashboard/src/components/common_components/team_multi_select.tsx b/ui/litellm-dashboard/src/components/common_components/team_multi_select.tsx
index da8e99a938d..e496eea95b0 100644
--- a/ui/litellm-dashboard/src/components/common_components/team_multi_select.tsx
+++ b/ui/litellm-dashboard/src/components/common_components/team_multi_select.tsx
@@ -87,12 +87,7 @@ const TeamMultiSelect: React.FC = ({
))
}
-
+
{value.length > 0 && }
diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx
index ad5829f310a..8609bb1f82a 100644
--- a/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx
+++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx
@@ -251,9 +251,17 @@ vi.mock("../molecules/notifications_manager", () => ({
vi.mock("../agent_management/AgentSelector", () => ({ default: () => null }));
vi.mock("../common_components/budget_duration_dropdown", () => ({
NEVER_RESETS_BUDGET_DURATION: "none",
- default: ({ showNeverResets, onChange }: { showNeverResets?: boolean; onChange?: (value: string) => void }) => (
+ default: ({
+ showNeverResets,
+ placeholder,
+ onChange,
+ }: {
+ showNeverResets?: boolean;
+ placeholder?: string;
+ onChange?: (value: string) => void;
+ }) => (
onChange?.(event.target.value)}>
- n/a
+ {placeholder ?? "n/a"}
{showNeverResets ? Never resets : null}
monthly
@@ -871,6 +879,19 @@ describe("CreateKey", () => {
expect(formValues.budget_duration).toBeNull();
});
+ it("should label the omit option distinctly from 'Never resets'", async () => {
+ await openModal();
+
+ const optionLabels = Array.from(
+ screen.getByTestId("budget-duration-dropdown").querySelectorAll("option"),
+ (option) => option.textContent,
+ );
+
+ expect(optionLabels).toContain("Never resets");
+ expect(new Set(optionLabels).size).toBe(optionLabels.length);
+ expect(screen.getByRole("option", { name: "Never resets" })).toHaveValue("none");
+ });
+
it("should omit budget_duration entirely when the reset dropdown is untouched", async () => {
await openModal();
diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx
index c747cfe36fe..fc0dae1f912 100644
--- a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx
+++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx
@@ -1069,7 +1069,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
>
form.setFieldValue("budget_duration", value)}
/>
diff --git a/ui/litellm-dashboard/src/components/public_model_hub.tsx b/ui/litellm-dashboard/src/components/public_model_hub.tsx
index b642d28f21a..4ca7a52692a 100644
--- a/ui/litellm-dashboard/src/components/public_model_hub.tsx
+++ b/ui/litellm-dashboard/src/components/public_model_hub.tsx
@@ -637,7 +637,7 @@ const PublicModelHub: React.FC = ({ accessToken, isEmbedded
diff --git a/ui/litellm-dashboard/src/components/search_tools/SearchToolSelector.tsx b/ui/litellm-dashboard/src/components/search_tools/SearchToolSelector.tsx
index 5078950bb9e..8b4e9b297fa 100644
--- a/ui/litellm-dashboard/src/components/search_tools/SearchToolSelector.tsx
+++ b/ui/litellm-dashboard/src/components/search_tools/SearchToolSelector.tsx
@@ -79,12 +79,7 @@ const SearchToolSelector: React.FC = ({
))
}
-
+
{value && value.length > 0 && }
diff --git a/ui/litellm-dashboard/src/components/shared/DataTable/DataTable.tsx b/ui/litellm-dashboard/src/components/shared/DataTable/DataTable.tsx
index 2f47887d01f..08e909cc4fd 100644
--- a/ui/litellm-dashboard/src/components/shared/DataTable/DataTable.tsx
+++ b/ui/litellm-dashboard/src/components/shared/DataTable/DataTable.tsx
@@ -303,7 +303,10 @@ function DataTableBodyRow({
function MessageRow({ colSpan, children }: { colSpan: number; children: React.ReactNode }) {
return (
-
+
{children}
diff --git a/ui/litellm-dashboard/src/components/shared/MultiSelect.tsx b/ui/litellm-dashboard/src/components/shared/MultiSelect.tsx
index ef23ab2ebd4..9eea0e976e6 100644
--- a/ui/litellm-dashboard/src/components/shared/MultiSelect.tsx
+++ b/ui/litellm-dashboard/src/components/shared/MultiSelect.tsx
@@ -102,7 +102,7 @@ export function MultiSelect({
))}
>
diff --git a/ui/litellm-dashboard/src/components/ui/button-group.tsx b/ui/litellm-dashboard/src/components/ui/button-group.tsx
new file mode 100644
index 00000000000..bfbd6577044
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/ui/button-group.tsx
@@ -0,0 +1,76 @@
+import { mergeProps } from "@base-ui/react/merge-props";
+import { useRender } from "@base-ui/react/use-render";
+import { type VariantProps } from "cva";
+
+import { cn, cva } from "@/lib/cva.config";
+import { Separator } from "@/components/ui/separator";
+
+const buttonGroupVariants = cva({
+ base: "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
+ variants: {
+ orientation: {
+ horizontal:
+ "*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
+ vertical:
+ "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0",
+ },
+ },
+ defaultVariants: {
+ orientation: "horizontal",
+ },
+});
+
+function ButtonGroup({
+ className,
+ orientation,
+ ...props
+}: React.ComponentProps<"div"> & VariantProps) {
+ return (
+
+ );
+}
+
+function ButtonGroupText({ className, render, ...props }: useRender.ComponentProps<"div">) {
+ return useRender({
+ defaultTagName: "div",
+ props: mergeProps<"div">(
+ {
+ className: cn(
+ "flex items-center gap-2 rounded-md border bg-muted px-2.5 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
+ className,
+ ),
+ },
+ props,
+ ),
+ render,
+ state: {
+ slot: "button-group-text",
+ },
+ });
+}
+
+function ButtonGroupSeparator({
+ className,
+ orientation = "vertical",
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants };
diff --git a/ui/litellm-dashboard/src/components/user_agent_activity.tsx b/ui/litellm-dashboard/src/components/user_agent_activity.tsx
index b7c9056764b..74716fd866e 100644
--- a/ui/litellm-dashboard/src/components/user_agent_activity.tsx
+++ b/ui/litellm-dashboard/src/components/user_agent_activity.tsx
@@ -397,11 +397,7 @@ const UserAgentActivity: React.FC = ({ accessToken, user
))
}
-
+
{selectedTags.length > 0 && }
diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/JsonViewer.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/JsonViewer.tsx
index af99eee0d16..86b897f526f 100644
--- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/JsonViewer.tsx
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/JsonViewer.tsx
@@ -1,6 +1,6 @@
import { JsonView, defaultStyles } from "react-json-view-lite";
import "react-json-view-lite/dist/index.css";
-import { JSON_MAX_HEIGHT, COLOR_BG_LIGHT, SPACING_LARGE } from "./constants";
+import { JSON_MAX_HEIGHT, SPACING_LARGE } from "./constants";
interface JsonViewerProps {
data: any;
@@ -16,15 +16,15 @@ export function JsonViewer({ data }: JsonViewerProps) {
return (