mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
The dashboard's dark theme left a chunk of the bundled provider logos unreadable: 25 of them are pure black marks on a transparent background, so on a near-black surface they disappeared entirely, and another 11 are dark multicolor marks drawn for a white page. This adds the seam the rest of the work hangs off: a per-asset treatment manifest in logoTreatments.ts, and a Logo component that applies the treatment it names. Two treatments exist today. "invert" flattens a mark to solid white with brightness(0) invert(1), which is what the vendor's own white mark looks like for a pure-black transparent glyph. "plate" puts a white surface behind the mark so it reads exactly as it does on a light page. Both are dark-only, and only assets named in the manifest are touched, so light mode is unchanged and the other 96 bundled logos keep rendering byte for byte as they do today. The className an untreated logo receives is passed through verbatim rather than routed through cn(), so even the class string is unchanged. The split between invert and plate was measured per asset, not guessed: luminance, saturation and alpha coverage sampled off a canvas render. Two assets that look monochrome, aiml_api and repelloai, carry a light knockout inside dark artwork, so inversion would flatten the knockout into the mark and erase it. They get a plate instead, and a test pins that. Six assets whose artwork is an opaque dark box (aim_logo, aim_security, deepgram, jina, lakeraai, openmeter) are deliberately left untreated. A plate cannot show through an opaque image, so the only honest fix for them is a replacement asset.
308 lines
11 KiB
CSS
308 lines
11 KiB
CSS
@layer theme, base, components, utilities;
|
|
|
|
@import "tailwindcss";
|
|
@import "tw-animate-css";
|
|
|
|
@plugin '@headlessui/tailwindcss';
|
|
@plugin '@tailwindcss/forms';
|
|
|
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
|
|
/* shadcn Base UI primitives reference these variants; upstream omits them (shadcn-ui/ui#9196) */
|
|
@custom-variant data-open (&:where([data-state="open"], [data-open]:not([data-open="false"])));
|
|
@custom-variant data-closed (&:where([data-state="closed"], [data-closed]:not([data-closed="false"])));
|
|
@custom-variant data-checked (&:where([data-state="checked"], [data-checked]:not([data-checked="false"])));
|
|
@custom-variant data-unchecked (&:where([data-state="unchecked"], [data-unchecked]:not([data-unchecked="false"])));
|
|
@custom-variant data-selected (&:where([data-selected="true"]));
|
|
@custom-variant data-disabled (&:where([data-disabled="true"], [data-disabled]:not([data-disabled="false"])));
|
|
@custom-variant data-active (&:where([data-state="active"], [data-active]:not([data-active="false"])));
|
|
@custom-variant data-horizontal (&:where([data-orientation="horizontal"]));
|
|
@custom-variant data-vertical (&:where([data-orientation="vertical"]));
|
|
|
|
@utility no-scrollbar {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
&::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* The only z-index values in the dashboard. Portalled popups (src/components/ui) own the top of the
|
|
scale; everything else must sit below them. Enforced by the local/no-ad-hoc-z-index ESLint rule. */
|
|
@utility z-raised {
|
|
z-index: 1;
|
|
}
|
|
@utility z-chrome {
|
|
z-index: 10;
|
|
}
|
|
@utility z-sticky {
|
|
z-index: 20;
|
|
}
|
|
@utility z-sticky-pinned {
|
|
z-index: 25;
|
|
}
|
|
@utility z-floating {
|
|
z-index: 30;
|
|
}
|
|
@utility z-overlay {
|
|
z-index: 40;
|
|
}
|
|
@utility z-popup {
|
|
z-index: 50;
|
|
}
|
|
|
|
/* 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: "<length-percentage>";
|
|
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);
|
|
--foreground: oklch(0.13 0.028 261.692);
|
|
--card: oklch(1 0 0);
|
|
--card-foreground: oklch(0.13 0.028 261.692);
|
|
--popover: oklch(1 0 0);
|
|
--popover-foreground: oklch(0.13 0.028 261.692);
|
|
--primary: oklch(0.21 0.034 264.665);
|
|
--primary-foreground: oklch(0.985 0.002 247.839);
|
|
--secondary: oklch(0.967 0.003 264.542);
|
|
--secondary-foreground: oklch(0.21 0.034 264.665);
|
|
--muted: oklch(0.967 0.003 264.542);
|
|
--muted-foreground: oklch(0.551 0.027 264.364);
|
|
--accent: oklch(0.967 0.003 264.542);
|
|
--accent-foreground: oklch(0.21 0.034 264.665);
|
|
--destructive: oklch(0.577 0.245 27.325);
|
|
--destructive-foreground: oklch(1 0 0);
|
|
--success: oklch(0.527 0.154 150.069);
|
|
--success-foreground: oklch(1 0 0);
|
|
--warning: oklch(0.555 0.163 48.998);
|
|
--warning-foreground: oklch(1 0 0);
|
|
--info: oklch(0.546 0.245 262.881);
|
|
--info-foreground: oklch(1 0 0);
|
|
--border: oklch(0.928 0.006 264.531);
|
|
--input: oklch(0.928 0.006 264.531);
|
|
--ring: oklch(0.707 0.022 261.325);
|
|
--chart-1: oklch(0.646 0.222 41.116);
|
|
--chart-2: oklch(0.6 0.118 184.704);
|
|
--chart-3: oklch(0.398 0.07 227.392);
|
|
--chart-4: oklch(0.828 0.189 84.429);
|
|
--chart-5: oklch(0.769 0.188 70.08);
|
|
--sidebar: oklch(1 0 0);
|
|
--sidebar-foreground: oklch(0.13 0.028 261.692);
|
|
--sidebar-primary: oklch(0.21 0.034 264.665);
|
|
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
|
--sidebar-accent: oklch(0.967 0.003 264.542);
|
|
--sidebar-accent-foreground: oklch(0.21 0.034 264.665);
|
|
--sidebar-border: oklch(0.928 0.006 264.531);
|
|
--sidebar-ring: oklch(0.707 0.022 261.325);
|
|
--neutral-border: #dcddeb;
|
|
--logo-surface: oklch(1 0 0);
|
|
}
|
|
|
|
.dark {
|
|
--background: oklch(0.248 0 0);
|
|
--foreground: oklch(0.964 0 0);
|
|
--card: oklch(0.248 0 0);
|
|
--card-foreground: oklch(0.964 0 0);
|
|
--popover: oklch(0.286 0 0);
|
|
--popover-foreground: oklch(0.964 0 0);
|
|
--primary: oklch(0.928 0 0);
|
|
--primary-foreground: oklch(0.209 0 0);
|
|
--secondary: oklch(0.356 0 0);
|
|
--secondary-foreground: oklch(0.964 0 0);
|
|
--muted: oklch(0.209 0 0);
|
|
--muted-foreground: oklch(0.754 0 0);
|
|
--accent: oklch(0.309 0 0);
|
|
--accent-foreground: oklch(0.964 0 0);
|
|
--destructive: oklch(0.704 0.191 22.216);
|
|
--destructive-foreground: oklch(0.209 0 0);
|
|
--success: oklch(0.792 0.209 151.711);
|
|
--success-foreground: oklch(0.209 0 0);
|
|
--warning: oklch(0.828 0.189 84.429);
|
|
--warning-foreground: oklch(0.209 0 0);
|
|
--info: oklch(0.707 0.165 254.624);
|
|
--info-foreground: oklch(0.209 0 0);
|
|
--border: oklch(0.309 0 0);
|
|
--input: oklch(0.56 0 0);
|
|
--ring: oklch(0.569 0 0);
|
|
--chart-1: oklch(0.488 0.243 264.376);
|
|
--chart-2: oklch(0.696 0.17 162.48);
|
|
--chart-3: oklch(0.769 0.188 70.08);
|
|
--chart-4: oklch(0.627 0.265 303.9);
|
|
--chart-5: oklch(0.645 0.246 16.439);
|
|
--sidebar: oklch(0.187 0 0);
|
|
--sidebar-foreground: oklch(0.964 0 0);
|
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
--sidebar-primary-foreground: oklch(0.964 0 0);
|
|
--sidebar-accent: oklch(0.309 0 0);
|
|
--sidebar-accent-foreground: oklch(0.964 0 0);
|
|
--sidebar-border: oklch(0.187 0 0);
|
|
--sidebar-ring: oklch(0.569 0 0);
|
|
--neutral-border: var(--border);
|
|
}
|
|
|
|
@theme inline {
|
|
--radius-sm: calc(var(--radius) - 4px);
|
|
--radius-md: calc(var(--radius) - 2px);
|
|
--radius-lg: var(--radius);
|
|
--radius-xl: calc(var(--radius) + 4px);
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--color-card: var(--card);
|
|
--color-card-foreground: var(--card-foreground);
|
|
--color-popover: var(--popover);
|
|
--color-popover-foreground: var(--popover-foreground);
|
|
--color-primary: var(--primary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
--color-secondary: var(--secondary);
|
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
--color-muted: var(--muted);
|
|
--color-muted-foreground: var(--muted-foreground);
|
|
--color-accent: var(--accent);
|
|
--color-accent-foreground: var(--accent-foreground);
|
|
--color-destructive: var(--destructive);
|
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
--color-success: var(--success);
|
|
--color-success-foreground: var(--success-foreground);
|
|
--color-warning: var(--warning);
|
|
--color-warning-foreground: var(--warning-foreground);
|
|
--color-info: var(--info);
|
|
--color-info-foreground: var(--info-foreground);
|
|
--color-border: var(--border);
|
|
--color-input: var(--input);
|
|
--color-ring: var(--ring);
|
|
--color-chart-1: var(--chart-1);
|
|
--color-chart-2: var(--chart-2);
|
|
--color-chart-3: var(--chart-3);
|
|
--color-chart-4: var(--chart-4);
|
|
--color-chart-5: var(--chart-5);
|
|
--color-sidebar: var(--sidebar);
|
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
--color-sidebar-primary: var(--sidebar-primary);
|
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
--color-sidebar-accent: var(--sidebar-accent);
|
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
--color-sidebar-border: var(--sidebar-border);
|
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
--color-logo-surface: var(--logo-surface);
|
|
}
|
|
|
|
@layer base {
|
|
*,
|
|
::after,
|
|
::before,
|
|
::backdrop,
|
|
::file-selector-button {
|
|
border-color: var(--color-border);
|
|
}
|
|
|
|
* {
|
|
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;
|
|
}
|
|
|
|
/* Same plugin's white fill, on the hand-rolled controls outside components/ui that the audit
|
|
above did not cover. Tracks --background so light mode keeps the white it already painted.
|
|
Delete along with the plugin. */
|
|
:is(input, textarea, select):not([type="checkbox"], [type="radio"], [data-slot="combobox-chip-input"]) {
|
|
background-color: var(--color-background);
|
|
}
|
|
|
|
button:not(:disabled),
|
|
[role="button"]:not(:disabled) {
|
|
cursor: pointer;
|
|
}
|
|
|
|
input::placeholder,
|
|
textarea::placeholder {
|
|
color: var(--color-muted-foreground);
|
|
}
|
|
|
|
body {
|
|
background-color: var(--color-background);
|
|
color: var(--color-foreground);
|
|
}
|
|
}
|
|
|
|
.table-wrapper {
|
|
overflow-x: scroll;
|
|
margin: 0px 24px;
|
|
}
|
|
|
|
.custom-border {
|
|
border: 1px solid var(--neutral-border);
|
|
}
|
|
|
|
/* A dialog opened from inside another dialog reads as a drill-down, not a stack: base-ui stamps
|
|
this attribute on the parent while a child is open, so the parent steps aside instead of
|
|
showing its own edges around a differently sized child. */
|
|
[data-slot="dialog-content"][data-nested-dialog-open] {
|
|
visibility: hidden;
|
|
}
|