fix(ui): give status colours a readable foreground and drop the muted 70% step (#37649)

* fix(ui): give status colours a readable foreground and drop the muted 70% step

The four status tokens are lightened for dark mode, which is correct when they are used as text
and wrong for the 27 places that use them as a background under `text-white`. Every one of those
passes in light and fails in dark: success 1.78:1, warning 1.72:1, info 2.64:1, destructive
2.89:1. The cause is not 27 authoring mistakes, it is that no `--success-foreground` and no
sibling ever existed, so `text-white` was the only thing available to write. Adding the four
companions and registering them in `@theme` makes the correct pairing expressible, and the call
sites then read `text-success-foreground` instead of a hardcoded colour. Dark lands at 9.98, 10.31,
6.72 and 6.15.

Light is deliberately pure white rather than the near-white the other `-foreground` tokens use, so
the four ratios stay at exactly the 4.95, 5.03, 5.25 and 4.77 they are today instead of drifting
down to 4.73, 4.81, 5.02 and 4.56.

Separately `text-muted-foreground/70` measures 2.75:1 on a light page and 4.31:1 on a dark one,
so the same 183 occurrences fail AA in light and sit under it in dark. Dropping the opacity step
takes them to 4.84:1 and 7.34:1. The identical step on the placeholder base rule goes with them,
which is what put every input's placeholder at 2.75:1 in light.

Residual, not addressed here: `text-muted-foreground` over `bg-muted` reaches 4.39:1 in light,
still short of 4.5. Closing that needs `--muted-foreground` itself to move, which changes every
secondary label in the product and is a design call rather than a defect fix.

* fix(ui): finish the status-foreground swap and repoint no-op muted hovers

Four sites still forced text-white on a status fill because the class sat on
a child element rather than on the filled container, so the earlier sweep did
not reach them. The compliance quick-test bubble was worse: it paired bg-info
with text-success-foreground and its paragraph kept text-white on top, so the
dark-theme contrast the PR set out to fix was still reachable there

Dropping the /70 step also turned 21 existing "text-muted-foreground/70
hover:text-muted-foreground" pairs into hovers that change nothing, which
local/no-noop-hover-variant flags as an error. The affordance was "brighten on
hover", so these now hover to text-foreground, matching the 74 places that
already spell it that way

The remaining churn is prettier reflowing the handful of lines whose length
changed, since the token names are longer than text-white

* fix(ui): let the approve/reject confirm button pick the token its fill uses

Both submission review dialogs put text-success-foreground on the shared
button class while the fill below it swings between bg-success for Approve and
bg-destructive for Reject, so Reject drew a success token over a destructive
fill. The two tokens resolve to the same value today, so nothing looks wrong,
but the pairing only holds by coincidence and would break the moment either
token moves. Moving the token into the branch makes it track the fill

* fix(ui): drop the last 70% placeholders, still live on the legacy utility

Four inputs spell their placeholder colour with Tailwind's older
placeholder-<colour> utility rather than placeholder:text-<colour>, so the
sweep that dropped the 70% step passed over them. Tailwind 4.3 still emits
that utility, and utilities sit after base in the layer order, so those four
kept overriding the new input::placeholder rule and kept rendering at 70% in
dark mode, which is the contrast failure this PR set out to close

They now spell it the same way as the three placeholders the PR already
converted, which both removes the step and settles on one spelling
This commit is contained in:
yuneng-jiang 2026-08-20 10:58:32 -07:00 committed by GitHub
parent e12833e6b4
commit c794dcb91d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
75 changed files with 248 additions and 232 deletions

View file

@ -40,7 +40,7 @@ const compareRows = (a: CacheLeakageRow, b: CacheLeakageRow, sort: SortState): n
const InfoTooltip = ({ info }: { info: string }) => (
<Tooltip>
<TooltipTrigger render={<span className="inline-flex" aria-label={info} />}>
<Info className="h-3 w-3 text-muted-foreground/70" />
<Info className="h-3 w-3 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent className="max-w-xs">{info}</TooltipContent>
</Tooltip>
@ -72,7 +72,7 @@ const SortableHead = ({
className="inline-flex items-center gap-1 font-medium hover:text-foreground"
>
{label}
<Arrow className={`h-3 w-3 ${active ? "text-foreground" : "text-muted-foreground/70"}`} />
<Arrow className={`h-3 w-3 ${active ? "text-foreground" : "text-muted-foreground"}`} />
</button>
<InfoTooltip info={info} />
</span>

View file

@ -133,7 +133,7 @@ const TierTurnsChart: React.FC<TierTurnsChartProps> = ({ view, autoRouters }) =>
{slice.tier} {Math.round((100 * slice.turns) / total).toLocaleString()}%
</p>
{slice.models.length > 0 && (
<p className="text-xs break-words text-muted-foreground/70">{slice.models.join(", ")}</p>
<p className="text-xs break-words text-muted-foreground">{slice.models.join(", ")}</p>
)}
</div>
</li>

View file

@ -223,7 +223,7 @@ const CostTrackingSettings: React.FC<CostTrackingSettingsProps> = ({ userID, use
) : (
<div className="py-16 px-6 text-center">
<svg
className="mx-auto h-12 w-12 text-muted-foreground/70 mb-4"
className="mx-auto h-12 w-12 text-muted-foreground mb-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
@ -278,7 +278,7 @@ const CostTrackingSettings: React.FC<CostTrackingSettingsProps> = ({ userID, use
) : (
<div className="py-16 px-6 text-center">
<svg
className="mx-auto h-12 w-12 text-muted-foreground/70 mb-4"
className="mx-auto h-12 w-12 text-muted-foreground mb-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"

View file

@ -101,7 +101,7 @@ const SingleModelBreakdown: React.FC<{
)}
{(result.input_cost_per_token || result.output_cost_per_token) && (
<div className="text-xs text-muted-foreground/70 pt-2 border-t border-border">
<div className="text-xs text-muted-foreground pt-2 border-t border-border">
Token Pricing:{" "}
{result.input_cost_per_token && (
<span>Input ${formatNumberWithCommas(result.input_cost_per_token * 1_000_000, 2)}/1M</span>
@ -294,17 +294,17 @@ const MultiCostResults: React.FC<MultiCostResultsProps> = ({ multiResult, timePe
</TableCell>
<TableCell className="text-right">
{record.error ? (
<span className="text-muted-foreground/70">-</span>
<span className="text-muted-foreground">-</span>
) : (
<span className="font-mono text-sm">{formatCost(record.cost_per_request)}</span>
)}
</TableCell>
<TableCell className="text-right">
{record.error ? (
<span className="text-muted-foreground/70">-</span>
<span className="text-muted-foreground">-</span>
) : (
<span
className={`font-mono text-sm ${(record.margin_cost_per_request ?? 0) > 0 ? "text-warning" : "text-muted-foreground/70"}`}
className={`font-mono text-sm ${(record.margin_cost_per_request ?? 0) > 0 ? "text-warning" : "text-muted-foreground"}`}
>
{formatCost(record.margin_cost_per_request)}
</span>
@ -312,7 +312,7 @@ const MultiCostResults: React.FC<MultiCostResultsProps> = ({ multiResult, timePe
</TableCell>
<TableCell className="text-right">
{record.error ? (
<span className="text-muted-foreground/70">-</span>
<span className="text-muted-foreground">-</span>
) : (
<span className="font-mono text-sm">{formatCost(periodCost)}</span>
)}
@ -325,7 +325,7 @@ const MultiCostResults: React.FC<MultiCostResultsProps> = ({ multiResult, timePe
aria-expanded={isExpanded}
aria-label={`${isExpanded ? "Hide" : "Show"} cost breakdown for ${record.model}`}
onClick={() => toggleExpanded(record.id)}
className="text-muted-foreground/70 hover:text-muted-foreground"
className="text-muted-foreground hover:text-foreground"
>
{isExpanded ? <ChevronDown className="size-3" /> : <ChevronRight className="size-3" />}
</Button>

View file

@ -138,7 +138,7 @@ const ProviderMarginTable: React.FC<ProviderMarginTableProps> = ({
autoFocus
/>
<span className="text-muted-foreground">%</span>
<span className="text-muted-foreground/70">+</span>
<span className="text-muted-foreground">+</span>
<span className="text-muted-foreground">$</span>
<Input
value={editFixedAmount}

View file

@ -150,7 +150,7 @@ export function GuardrailsOverview({
<span
className={
row.original.avgLatency == null
? "text-muted-foreground/70"
? "text-muted-foreground"
: row.original.avgLatency > 150
? "text-destructive"
: row.original.avgLatency > 50

View file

@ -358,7 +358,7 @@ function GuardrailCard({
<button
type="button"
onClick={onApprove}
className="text-xs bg-success hover:bg-success/80 text-white px-3 py-1.5 rounded-md transition-colors font-medium"
className="text-xs bg-success hover:bg-success/80 text-success-foreground px-3 py-1.5 rounded-md transition-colors font-medium"
>
Approve
</button>
@ -727,7 +727,7 @@ function DetailPanel({
<button
type="button"
onClick={onApprove}
className="flex-1 flex items-center justify-center gap-1.5 bg-success hover:bg-success/80 text-white text-sm font-medium py-2 rounded-md transition-colors"
className="flex-1 flex items-center justify-center gap-1.5 bg-success hover:bg-success/80 text-success-foreground text-sm font-medium py-2 rounded-md transition-colors"
>
<CheckIcon className="h-4 w-4" />
Approve
@ -792,8 +792,10 @@ function ConfirmDialog({ action, guardrailName, onConfirm, onCancel }: ConfirmDi
<button
type="button"
onClick={onConfirm}
className={`flex-1 text-white text-sm font-medium py-2 rounded-md transition-colors ${
isApprove ? "bg-success hover:bg-success/80" : "bg-destructive hover:bg-destructive/80"
className={`flex-1 text-sm font-medium py-2 rounded-md transition-colors ${
isApprove
? "bg-success text-success-foreground hover:bg-success/80"
: "bg-destructive text-destructive-foreground hover:bg-destructive/80"
}`}
>
{isApprove ? "Approve" : "Reject"}
@ -1015,7 +1017,7 @@ export function TeamGuardrailsTab({ accessToken }: TeamGuardrailsTabProps) {
<button
type="button"
onClick={() => setIsSubmitModalOpen(true)}
className="ml-auto flex items-center gap-2 bg-info hover:bg-info/80 text-white text-sm font-medium px-4 py-2 rounded-md transition-colors"
className="ml-auto flex items-center gap-2 bg-info hover:bg-info/80 text-info-foreground text-sm font-medium px-4 py-2 rounded-md transition-colors"
>
<PlusIcon className="h-4 w-4" />
Add Guardrail

View file

@ -144,7 +144,7 @@ const createEmptyToolPermissionConfig = (): ToolPermissionConfig => ({
});
const getStepIndicatorClass = (isDone: boolean, isCurrent: boolean): string => {
if (isDone) return "bg-info text-white";
if (isDone) return "bg-info text-info-foreground";
if (isCurrent) return "bg-background text-info border-2 border-info";
return "bg-muted text-muted-foreground border border-border";
};

View file

@ -149,7 +149,7 @@ const ScopedValueOrDescription: React.FC<{ index: number }> = ({ index }) => {
<InputGroupInput
{...textControl(control)}
placeholder="e.g. Your DB username"
className="text-muted-foreground/70"
className="text-muted-foreground"
/>
</InputGroup>
)}

View file

@ -107,7 +107,7 @@ function ConfirmDialog({ action, serverName, isCurrentlyActive, onConfirm, onCan
placeholder="Reason for rejection (optional)"
value={reviewNotes}
onChange={(e) => setReviewNotes(e.target.value)}
className="w-full border border-border rounded-md px-3 py-2 text-sm text-foreground placeholder-muted-foreground/70 focus:outline-hidden focus:ring-1 focus:ring-ring mb-4 resize-none"
className="w-full border border-border rounded-md px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-hidden focus:ring-1 focus:ring-ring mb-4 resize-none"
rows={3}
/>
)}
@ -122,8 +122,10 @@ function ConfirmDialog({ action, serverName, isCurrentlyActive, onConfirm, onCan
<button
type="button"
onClick={() => onConfirm(isApprove ? undefined : reviewNotes || undefined)}
className={`flex-1 text-white text-sm font-medium py-2 rounded-md transition-colors ${
isApprove ? "bg-success hover:bg-success/80" : "bg-destructive hover:bg-destructive/80"
className={`flex-1 text-sm font-medium py-2 rounded-md transition-colors ${
isApprove
? "bg-success text-success-foreground hover:bg-success/80"
: "bg-destructive text-destructive-foreground hover:bg-destructive/80"
}`}
>
{isApprove ? "Approve" : "Reject"}
@ -157,14 +159,14 @@ function SubmissionRulesPanel({ requiredFields, onChange, onSave, isSaving }: Su
onClick={() => setExpanded((v) => !v)}
>
<div className="flex items-center gap-2">
<SettingsIcon className="h-4 w-4 text-muted-foreground/70" />
<SettingsIcon className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-semibold text-foreground">Submission Rules</span>
{activeLabels.length > 0 ? (
<span className="text-xs text-muted-foreground">
({activeLabels.length} required field{activeLabels.length !== 1 ? "s" : ""})
</span>
) : (
<span className="text-xs text-muted-foreground/70 italic">no rules set</span>
<span className="text-xs text-muted-foreground italic">no rules set</span>
)}
</div>
<div className="flex items-center gap-3">
@ -183,9 +185,9 @@ function SubmissionRulesPanel({ requiredFields, onChange, onSave, isSaving }: Su
</div>
)}
{expanded ? (
<ChevronUpIcon className="h-4 w-4 text-muted-foreground/70" />
<ChevronUpIcon className="h-4 w-4 text-muted-foreground" />
) : (
<ChevronDownIcon className="h-4 w-4 text-muted-foreground/70" />
<ChevronDownIcon className="h-4 w-4 text-muted-foreground" />
)}
</div>
</div>
@ -218,7 +220,7 @@ function SubmissionRulesPanel({ requiredFields, onChange, onSave, isSaving }: Su
<div className="text-sm font-medium text-foreground group-hover:text-info transition-colors">
{field.label}
</div>
<div className="text-xs text-muted-foreground/70">{field.description}</div>
<div className="text-xs text-muted-foreground">{field.description}</div>
</div>
</label>
);
@ -235,7 +237,7 @@ function SubmissionRulesPanel({ requiredFields, onChange, onSave, isSaving }: Su
await onSave();
setExpanded(false);
}}
className="px-4 py-1.5 text-sm font-medium text-white bg-info hover:bg-info/80 disabled:opacity-50 rounded-md transition-colors"
className="px-4 py-1.5 text-sm font-medium text-info-foreground bg-info hover:bg-info/80 disabled:opacity-50 rounded-md transition-colors"
>
{isSaving ? "Saving…" : "Save Rules"}
</button>
@ -296,11 +298,11 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe
)}
{server.url && (
<div className="flex items-center gap-1.5 mt-1.5">
<ServerIcon className="h-3.5 w-3.5 text-muted-foreground/70 shrink-0" />
<ServerIcon className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
<code className="text-xs text-muted-foreground font-mono truncate">{server.url}</code>
</div>
)}
<div className="flex items-center gap-3 mt-1.5 text-xs text-muted-foreground/70">
<div className="flex items-center gap-3 mt-1.5 text-xs text-muted-foreground">
<span>
Transport: <span className="text-muted-foreground">{server.transport ?? "sse"}</span>
</span>
@ -322,7 +324,7 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe
<button
type="button"
onClick={onApprove}
className="text-xs bg-success hover:bg-success/80 text-white px-3 py-1.5 rounded-md transition-colors font-medium"
className="text-xs bg-success hover:bg-success/80 text-success-foreground px-3 py-1.5 rounded-md transition-colors font-medium"
>
Approve
</button>
@ -341,7 +343,7 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe
<button
type="button"
onClick={onApprove}
className="text-xs bg-success hover:bg-success/80 text-white px-3 py-1.5 rounded-md transition-colors font-medium"
className="text-xs bg-success hover:bg-success/80 text-success-foreground px-3 py-1.5 rounded-md transition-colors font-medium"
>
Re-approve
</button>
@ -367,7 +369,11 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe
allPassed ? "bg-success" : "bg-destructive"
}`}
>
{allPassed ? <CheckIcon className="h-4 w-4 text-white" /> : <XIcon className="h-4 w-4 text-white" />}
{allPassed ? (
<CheckIcon className="h-4 w-4 text-success-foreground" />
) : (
<XIcon className="h-4 w-4 text-destructive-foreground" />
)}
</div>
<div className="flex-1 min-w-0">
<div className={`text-sm font-semibold leading-tight ${allPassed ? "text-success" : "text-destructive"}`}>
@ -383,7 +389,7 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe
<button
type="button"
onClick={onApprove}
className="text-xs bg-success hover:bg-success/80 text-white px-3 py-1.5 rounded-md transition-colors font-medium"
className="text-xs bg-success hover:bg-success/80 text-success-foreground px-3 py-1.5 rounded-md transition-colors font-medium"
>
Approve
</button>
@ -392,7 +398,7 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe
<button
type="button"
onClick={onApprove}
className="text-xs bg-success hover:bg-success/80 text-white px-3 py-1.5 rounded-md transition-colors font-medium"
className="text-xs bg-success hover:bg-success/80 text-success-foreground px-3 py-1.5 rounded-md transition-colors font-medium"
>
Re-approve
</button>
@ -567,13 +573,13 @@ export function MCPSubmissionsTab({ accessToken }: MCPSubmissionsTabProps) {
<div className="flex items-center gap-3 mb-5">
<div className="relative flex-1 max-w-xs">
<SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground/70" />
<SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<input
type="text"
placeholder="Search MCP servers..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="w-full pl-9 pr-4 py-2 border border-border rounded-md text-sm text-foreground placeholder-muted-foreground/70 focus:outline-hidden focus:ring-1 focus:ring-ring focus:border-info"
className="w-full pl-9 pr-4 py-2 border border-border rounded-md text-sm text-foreground placeholder:text-muted-foreground focus:outline-hidden focus:ring-1 focus:ring-ring focus:border-info"
/>
</div>
<select
@ -592,7 +598,7 @@ export function MCPSubmissionsTab({ accessToken }: MCPSubmissionsTabProps) {
{isLoading && <div className="text-center py-12 text-muted-foreground text-sm">Loading submissions</div>}
{error && <div className="text-center py-12 text-destructive text-sm">{error}</div>}
{!isLoading && !error && filtered.length === 0 && (
<div className="text-center py-12 text-muted-foreground/70 text-sm">
<div className="text-center py-12 text-muted-foreground text-sm">
No MCP server submissions match your filters.
</div>
)}

View file

@ -185,7 +185,7 @@ const MCPConnect: React.FC<MCPConnectProps> = ({ currentServerAccessGroups = []
}> = ({ step, title, children }) => (
<div className="flex gap-4">
<div className="shrink-0">
<div className="w-8 h-8 bg-info text-white rounded-full flex items-center justify-center text-sm font-semibold">
<div className="w-8 h-8 bg-info text-info-foreground rounded-full flex items-center justify-center text-sm font-semibold">
{step}
</div>
</div>

View file

@ -161,7 +161,7 @@ const A2AMetrics: React.FC<A2AMetricsProps> = ({ a2aMetadata, timeToFirstToken,
>
<FileText className="size-3" />
Task: {truncateId(taskId)}
<Copy className="size-3 text-muted-foreground/70" />
<Copy className="size-3 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent>Click to copy: {taskId}</TooltipContent>
</Tooltip>
@ -184,7 +184,7 @@ const A2AMetrics: React.FC<A2AMetricsProps> = ({ a2aMetadata, timeToFirstToken,
>
<Link className="size-3" />
Session: {truncateId(contextId)}
<Copy className="size-3 text-muted-foreground/70" />
<Copy className="size-3 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent>Click to copy: {contextId}</TooltipContent>
</Tooltip>
@ -233,7 +233,7 @@ const A2AMetrics: React.FC<A2AMetricsProps> = ({ a2aMetadata, timeToFirstToken,
type="button"
variant="ghost"
size="icon-xs"
className="ml-2 text-muted-foreground/70 hover:text-info"
className="ml-2 text-muted-foreground hover:text-info"
onClick={() => copyToClipboard(taskId)}
aria-label={`Copy task ID ${taskId}`}
>
@ -252,7 +252,7 @@ const A2AMetrics: React.FC<A2AMetricsProps> = ({ a2aMetadata, timeToFirstToken,
type="button"
variant="ghost"
size="icon-xs"
className="ml-2 text-muted-foreground/70 hover:text-info"
className="ml-2 text-muted-foreground hover:text-info"
onClick={() => copyToClipboard(contextId)}
aria-label={`Copy session ID ${contextId}`}
>

View file

@ -101,7 +101,7 @@ const AdditionalModelSettings: React.FC<AdditionalModelSettingsProps> = ({
}
};
const disabledTextColor = useAdvancedParams ? "text-foreground" : "text-muted-foreground/70";
const disabledTextColor = useAdvancedParams ? "text-foreground" : "text-muted-foreground";
return (
<div className="w-80 space-y-4 p-4">
@ -118,7 +118,7 @@ const AdditionalModelSettings: React.FC<AdditionalModelSettingsProps> = ({
</label>
<Tooltip>
<TooltipTrigger aria-label="Help: Stream responses">
<Info className="size-3 shrink-0 cursor-pointer text-muted-foreground/70 hover:text-muted-foreground" />
<Info className="size-3 shrink-0 cursor-pointer text-muted-foreground hover:text-foreground" />
</TooltipTrigger>
<TooltipContent className="max-w-xs">
Streams the answer token by token. Uncheck to send a non-streaming request and render the full response at
@ -155,7 +155,7 @@ const AdditionalModelSettings: React.FC<AdditionalModelSettingsProps> = ({
</label>
<Popover>
<PopoverTrigger aria-label="Help: Simulate failure to test fallbacks">
<Info className="size-3 shrink-0 cursor-pointer text-muted-foreground/70 hover:text-muted-foreground" />
<Info className="size-3 shrink-0 cursor-pointer text-muted-foreground hover:text-foreground" />
</PopoverTrigger>
<PopoverContent side="right" className="max-w-[340px] gap-2 p-3 text-sm">
<p>
@ -221,7 +221,7 @@ const AdditionalModelSettings: React.FC<AdditionalModelSettingsProps> = ({
className="w-full accent-primary disabled:cursor-not-allowed"
onChange={(event) => handleTemperatureChange(Number(event.target.value))}
/>
<div className="mt-1 flex justify-between text-xs text-muted-foreground/70">
<div className="mt-1 flex justify-between text-xs text-muted-foreground">
<span>0</span>
<span>1.0</span>
<span>2.0</span>
@ -267,7 +267,7 @@ const AdditionalModelSettings: React.FC<AdditionalModelSettingsProps> = ({
className="w-full accent-primary disabled:cursor-not-allowed"
onChange={(event) => handleMaxTokensChange(Number(event.target.value))}
/>
<div className="mt-1 flex justify-between text-xs text-muted-foreground/70">
<div className="mt-1 flex justify-between text-xs text-muted-foreground">
<span>1</span>
<span>32768</span>
</div>

View file

@ -492,7 +492,7 @@ export default function AgentBuilderView({
<div className="flex-1 overflow-y-auto p-2">
{loadingAgents ? (
<div className="flex justify-center py-4" aria-busy="true">
<UiLoadingSpinner className="size-4 text-muted-foreground/70" />
<UiLoadingSpinner className="size-4 text-muted-foreground" />
</div>
) : (
<>

View file

@ -56,7 +56,7 @@ const ChatImageUpload: React.FC<ChatImageUploadProps> = ({ chatUploadedImage, on
size="icon-sm"
disabled={disabled}
aria-label="Attach image or PDF"
className="text-muted-foreground/70 hover:text-muted-foreground"
className="text-muted-foreground hover:text-foreground"
onClick={() => inputRef.current?.click()}
/>
}

View file

@ -1395,7 +1395,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
type="button"
variant="ghost"
size="icon-xs"
className="cursor-not-allowed text-muted-foreground/70"
className="cursor-not-allowed text-muted-foreground"
disabled
aria-label="Model Settings unavailable"
/>
@ -1484,7 +1484,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
/>
}
>
<Info className="size-3.5 cursor-pointer text-muted-foreground/70" />
<Info className="size-3.5 cursor-pointer text-muted-foreground" />
</TooltipTrigger>
<TooltipContent className="max-w-xs">
{endpointType === EndpointType.MCP
@ -1615,7 +1615,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
</span>
<button
type="button"
className="text-xs text-muted-foreground/70 underline hover:text-info"
className="text-xs text-muted-foreground underline hover:text-info"
onClick={() => setByokModalServer(server)}
>
Reconnect
@ -1625,7 +1625,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
<Button
type="button"
size="xs"
className="rounded-lg bg-info px-3 py-1 text-xs font-medium text-white hover:bg-info/80"
className="rounded-lg bg-info px-3 py-1 text-xs font-medium text-info-foreground hover:bg-info/80"
onClick={() => setByokModalServer(server)}
>
Connect
@ -1643,7 +1643,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
<Database className="mr-1 size-4" aria-hidden="true" /> Vector Store
<Tooltip>
<TooltipTrigger aria-label="About vector stores">
<Info className="size-3.5 text-muted-foreground/70" />
<Info className="size-3.5 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent className="max-w-xs">
Select vector store(s) to use for this LLM API call. You can set up your vector store{" "}
@ -1667,7 +1667,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
<Shield className="mr-1 size-4" aria-hidden="true" /> Guardrails
<Tooltip>
<TooltipTrigger aria-label="About guardrails">
<Info className="size-3.5 text-muted-foreground/70" />
<Info className="size-3.5 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent className="max-w-xs">
Select guardrail(s) to use for this LLM API call. You can set up your guardrails{" "}
@ -1692,7 +1692,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
<Shield className="mr-1 size-4" aria-hidden="true" /> Policies
<Tooltip>
<TooltipTrigger aria-label="About policies">
<Info className="size-3.5 text-muted-foreground/70" />
<Info className="size-3.5 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent className="max-w-xs">
Select policy/policies to apply to this LLM API call. Policies define which guardrails are
@ -1756,7 +1756,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
</div>
<div className="min-h-0 min-w-0 flex-1 overflow-auto p-3 pb-0 sm:p-4 sm:pb-0">
{chatHistory.length === 0 && (
<div className="flex h-full flex-col items-center justify-center text-muted-foreground/70">
<div className="flex h-full flex-col items-center justify-center text-muted-foreground">
<Bot className="mb-4 size-12" aria-hidden="true" />
<p className="text-sm">Start a conversation, generate an image, or handle audio</p>
</div>

View file

@ -196,7 +196,7 @@ const CodeInterpreterOutput: React.FC<CodeInterpreterOutputProps> = ({ code, ann
</div>
) : (
<div className="flex items-center justify-center bg-muted p-4">
<span className="text-sm text-muted-foreground/70">Image not available</span>
<span className="text-sm text-muted-foreground">Image not available</span>
</div>
)}
</div>
@ -215,7 +215,7 @@ const CodeInterpreterOutput: React.FC<CodeInterpreterOutputProps> = ({ code, ann
>
<FileText className="size-4 text-info" aria-hidden="true" />
<span className="text-sm">{annotation.filename}</span>
<Download className="size-3 text-muted-foreground/70" aria-hidden="true" />
<Download className="size-3 text-muted-foreground" aria-hidden="true" />
</Button>
))}
</div>

View file

@ -53,7 +53,7 @@ const CodeInterpreterTool: React.FC<CodeInterpreterToolProps> = ({
<span className="font-medium text-foreground">Code Interpreter</span>
<Tooltip>
<TooltipTrigger aria-label="About Code Interpreter">
<Info className="size-3 text-muted-foreground/70" />
<Info className="size-3 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent>
Run Python code to generate files, charts, and analyze data. Container is created automatically.

View file

@ -16,7 +16,7 @@ function FilePreviewCard({ file, previewUrl, onRemove }: FilePreviewCardProps) {
<div className="relative inline-block">
{isPdf ? (
<div className="w-10 h-10 rounded-md bg-destructive flex items-center justify-center">
<FileText className="size-4 text-white" aria-hidden="true" />
<FileText className="size-4 text-destructive-foreground" aria-hidden="true" />
</div>
) : (
<img
@ -35,7 +35,7 @@ function FilePreviewCard({ file, previewUrl, onRemove }: FilePreviewCardProps) {
variant="ghost"
size="icon-xs"
aria-label={`Remove ${file.name}`}
className="text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent"
className="text-muted-foreground hover:text-foreground hover:bg-accent"
onClick={onRemove}
>
<X className="size-3" />

View file

@ -404,10 +404,10 @@ const RealtimePlayground: React.FC<RealtimePlaygroundProps> = ({
{/* Messages */}
<div className="flex-1 overflow-y-auto p-4 space-y-3">
{messages.length === 0 && !isConnected && (
<div className="flex flex-col items-center justify-center h-full text-muted-foreground/70 gap-3">
<div className="flex flex-col items-center justify-center h-full text-muted-foreground gap-3">
<Volume2 className="size-12" />
<span className="text-lg text-muted-foreground">Realtime Voice Playground</span>
<p className="text-sm text-muted-foreground/70 text-center max-w-md">
<p className="text-sm text-muted-foreground text-center max-w-md">
Click <b>Connect</b> to start a realtime session. You can speak using your microphone or type messages.
The AI will respond with voice and text.
</p>
@ -419,11 +419,13 @@ const RealtimePlayground: React.FC<RealtimePlaygroundProps> = ({
className={`flex ${msg.role === "user" ? "justify-end" : msg.role === "status" ? "justify-center" : "justify-start"}`}
>
{msg.role === "status" ? (
<div className="text-xs text-muted-foreground/70 italic px-3 py-1">{msg.content}</div>
<div className="text-xs text-muted-foreground italic px-3 py-1">{msg.content}</div>
) : (
<div
className={`max-w-[75%] rounded-2xl px-4 py-2.5 ${
msg.role === "user" ? "bg-info text-white rounded-br-md" : "bg-muted text-foreground rounded-bl-md"
msg.role === "user"
? "bg-info text-info-foreground rounded-br-md"
: "bg-muted text-foreground rounded-bl-md"
}`}
>
<div className="text-xs font-medium mb-0.5 opacity-70">{msg.role === "user" ? "You" : "AI"}</div>

View file

@ -60,7 +60,7 @@ const ResponsesImageUpload: React.FC<ResponsesImageUploadProps> = ({
size="icon-sm"
disabled={disabled}
aria-label="Attach image or PDF"
className="text-muted-foreground/70 hover:text-muted-foreground"
className="text-muted-foreground hover:text-foreground"
onClick={() => inputRef.current?.click()}
/>
}

View file

@ -52,7 +52,7 @@ export function SearchResultsDisplay({ searchResults }: SearchResultsDisplayProp
<div className="text-xs text-muted-foreground mb-2 flex items-center gap-2">
<span className="font-medium">Query:</span>
<span className="italic">&quot;{resultPage.search_query}&quot;</span>
<span className="text-muted-foreground/70"></span>
<span className="text-muted-foreground"></span>
<span className="text-muted-foreground">
{resultPage.data.length} result{resultPage.data.length !== 1 ? "s" : ""}
</span>
@ -72,9 +72,9 @@ export function SearchResultsDisplay({ searchResults }: SearchResultsDisplayProp
<CollapsibleTrigger className="flex w-full items-center justify-between p-2 text-left transition-colors hover:bg-accent">
<div className="flex items-center gap-2 flex-1 min-w-0">
<ChevronRight
className={`size-4 shrink-0 text-muted-foreground/70 transition-transform ${isResultExpanded ? "rotate-90" : ""}`}
className={`size-4 shrink-0 text-muted-foreground transition-transform ${isResultExpanded ? "rotate-90" : ""}`}
/>
<FileText className="size-3 shrink-0 text-muted-foreground/70" />
<FileText className="size-3 shrink-0 text-muted-foreground" />
<span className="text-xs font-medium text-foreground truncate">
{result.filename || result.file_id || `Result ${resultIndex + 1}`}
</span>

View file

@ -64,7 +64,7 @@ const SessionManagement: React.FC<SessionManagementProps> = ({
<span className="text-sm font-medium text-foreground">Session Management</span>
<Tooltip>
<TooltipTrigger aria-label="About session management">
<Info className="size-3 text-muted-foreground/70" />
<Info className="size-3 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent>
Choose between LiteLLM API session management (using previous_response_id) or UI-based session management

View file

@ -819,7 +819,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
<div className="flex items-center gap-3 p-3 bg-muted rounded-lg border border-border">
<div className="relative inline-block">
{isUploadedFilePdf ? (
<div className="w-10 h-10 rounded-md bg-destructive flex items-center justify-center text-white">
<div className="w-10 h-10 rounded-md bg-destructive flex items-center justify-center text-destructive-foreground">
<FileText className="size-4" aria-label="file-pdf" />
</div>
) : (
@ -835,7 +835,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
<div className="text-xs text-muted-foreground">{isUploadedFilePdf ? "PDF" : "Image"}</div>
</div>
<button
className="flex items-center justify-center w-6 h-6 text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent rounded-full transition-colors"
className="flex items-center justify-center w-6 h-6 text-muted-foreground hover:text-foreground hover:bg-accent rounded-full transition-colors"
onClick={handleRemoveFile}
aria-label="Remove attachment"
>

View file

@ -85,7 +85,7 @@ export function ComparisonPanel({
};
const disabledOpacity = comparison.useAdvancedParams ? 1 : 0.4;
const disabledTextColor = comparison.useAdvancedParams ? "text-foreground" : "text-muted-foreground/70";
const disabledTextColor = comparison.useAdvancedParams ? "text-foreground" : "text-muted-foreground";
const handleTogglePopover = () => {
setPopoverVisible((prev) => !prev);

View file

@ -735,7 +735,7 @@ export default function ComplianceUI({
<div className="flex flex-col items-center pt-6 shrink-0">
<div className="w-px h-4 bg-border" />
<span className="text-[10px] font-medium text-muted-foreground/70 my-1">or</span>
<span className="text-[10px] font-medium text-muted-foreground my-1">or</span>
<div className="w-px h-4 bg-border" />
</div>
</>
@ -751,10 +751,10 @@ export default function ComplianceUI({
onClick={() => setShowGuardrailDropdown(!showGuardrailDropdown)}
className="w-full flex items-center justify-between border border-border rounded-lg px-3 py-2 text-sm text-left hover:border-ring transition-colors"
>
<span className={selectedGuardrails.length > 0 ? "text-foreground" : "text-muted-foreground/70"}>
<span className={selectedGuardrails.length > 0 ? "text-foreground" : "text-muted-foreground"}>
{selectedGuardrails.length > 0 ? `${selectedGuardrails.length} selected` : "None selected"}
</span>
<ChevronDown className="w-4 h-4 text-muted-foreground/70" />
<ChevronDown className="w-4 h-4 text-muted-foreground" />
</button>
{showGuardrailDropdown && (
<div className="absolute z-30 top-full left-0 right-0 mt-1 bg-card border border-border rounded-lg shadow-lg py-1 max-h-52 overflow-y-auto">
@ -773,11 +773,11 @@ export default function ComplianceUI({
<div
className={`w-4 h-4 rounded-sm border flex items-center justify-center shrink-0 ${selectedGuardrails.includes(g.id) ? "bg-info border-info" : "border-border"}`}
>
{selectedGuardrails.includes(g.id) && <Check className="w-3 h-3 text-white" />}
{selectedGuardrails.includes(g.id) && <Check className="w-3 h-3 text-info-foreground" />}
</div>
<div className="min-w-0">
<div className="text-foreground">{g.name}</div>
{g.type && <div className="text-[10px] text-muted-foreground/70">{g.type}</div>}
{g.type && <div className="text-[10px] text-muted-foreground">{g.type}</div>}
</div>
</button>
))
@ -815,7 +815,7 @@ export default function ComplianceUI({
<button
type="button"
onClick={() => batchAbortControllerRef.current?.abort()}
className="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap bg-destructive text-white hover:bg-destructive/80"
className="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap bg-destructive text-destructive-foreground hover:bg-destructive/80"
>
<Square className="w-3.5 h-3.5" /> Stop
</button>
@ -824,7 +824,7 @@ export default function ComplianceUI({
type="button"
onClick={runTests}
disabled={selectedPromptIds.size === 0 || disabledPersonalKeyCreation}
className={`flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${selectedPromptIds.size === 0 || disabledPersonalKeyCreation ? "bg-muted text-muted-foreground/70 cursor-not-allowed" : "bg-info text-white hover:bg-info/80"}`}
className={`flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${selectedPromptIds.size === 0 || disabledPersonalKeyCreation ? "bg-muted text-muted-foreground cursor-not-allowed" : "bg-info text-info-foreground hover:bg-info/80"}`}
>
<Play className="w-3.5 h-3.5" /> Simulate ({selectedPromptIds.size})
</button>
@ -858,19 +858,19 @@ export default function ComplianceUI({
<div className="px-4 pt-4 pb-2">
<div className="flex items-center justify-between mb-2.5">
<h3 className="text-sm font-semibold text-foreground">Test Prompts</h3>
<span className="text-[11px] text-muted-foreground/70 tabular-nums">
<span className="text-[11px] text-muted-foreground tabular-nums">
{selectedPromptIds.size}/{totalPromptCount}
</span>
</div>
<div className="relative mb-2.5">
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground/70" />
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" />
<input
type="text"
value={searchPrompt}
onChange={(e) => setSearchPrompt(e.target.value)}
placeholder="Search prompts..."
className="w-full border border-border rounded-lg pl-8 pr-3 py-1.5 text-xs placeholder:text-muted-foreground/70 focus:outline-hidden focus:ring-2 focus:ring-blue-500/20 focus:border-info"
className="w-full border border-border rounded-lg pl-8 pr-3 py-1.5 text-xs placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-blue-500/20 focus:border-info"
/>
</div>
@ -883,7 +883,7 @@ export default function ComplianceUI({
>
Select All
</button>
<span className="text-muted-foreground/70 text-[10px]">·</span>
<span className="text-muted-foreground text-[10px]">·</span>
<button
type="button"
onClick={deselectAll}
@ -924,7 +924,7 @@ export default function ComplianceUI({
onChange={(e) => setNewPromptText(e.target.value)}
placeholder="Enter your test prompt..."
rows={2}
className="w-full border border-border rounded-sm px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted-foreground/70 focus:outline-hidden focus:ring-2 focus:ring-blue-500/20 focus:border-info resize-none bg-card"
className="w-full border border-border rounded-sm px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-blue-500/20 focus:border-info resize-none bg-card"
/>
<div className="flex items-center justify-between mt-2">
<div className="flex items-center gap-2">
@ -958,7 +958,7 @@ export default function ComplianceUI({
type="button"
onClick={addCustomPrompt}
disabled={!newPromptText.trim()}
className={`text-[11px] font-medium px-2.5 py-1 rounded-sm ${newPromptText.trim() ? "bg-info text-white" : "bg-muted text-muted-foreground/70"}`}
className={`text-[11px] font-medium px-2.5 py-1 rounded-sm ${newPromptText.trim() ? "bg-info text-info-foreground" : "bg-muted text-muted-foreground"}`}
>
Add
</button>
@ -985,7 +985,7 @@ export default function ComplianceUI({
<span className="font-semibold text-muted-foreground">Required columns:</span>{" "}
<code className="bg-muted px-1 rounded-sm text-[10px]">prompt</code>,{" "}
<code className="bg-muted px-1 rounded-sm text-[10px]">expected_result</code>{" "}
<span className="text-muted-foreground/70">(fail or pass)</span>
<span className="text-muted-foreground">(fail or pass)</span>
</p>
<p className="text-[10px] text-muted-foreground leading-relaxed mt-0.5">
<span className="font-semibold text-muted-foreground">Optional columns:</span>{" "}
@ -1049,14 +1049,14 @@ export default function ComplianceUI({
className="w-full flex items-center gap-2 px-3 py-2.5 text-left bg-muted hover:bg-accent transition-colors rounded-lg border border-border"
>
{isExpanded ? (
<ChevronDown className="w-4 h-4 text-muted-foreground/70 shrink-0" />
<ChevronDown className="w-4 h-4 text-muted-foreground shrink-0" />
) : (
<ChevronRight className="w-4 h-4 text-muted-foreground/70 shrink-0" />
<ChevronRight className="w-4 h-4 text-muted-foreground shrink-0" />
)}
<CategoryIcon iconKey={fw.icon} className="w-4 h-4 text-muted-foreground shrink-0" />
<div className="flex-1 min-w-0">
<span className="text-xs font-semibold text-foreground">{fw.name}</span>
<span className="text-[10px] text-muted-foreground/70 ml-1.5">{fwPromptCount} prompts</span>
<span className="text-[10px] text-muted-foreground ml-1.5">{fwPromptCount} prompts</span>
</div>
{fwSelectedCount > 0 && (
<span className="text-[10px] font-medium bg-info/15 text-info px-1.5 py-0.5 rounded-full">
@ -1092,9 +1092,9 @@ export default function ComplianceUI({
className="w-full flex items-center gap-1.5 px-2.5 py-2 text-left hover:bg-accent transition-colors"
>
{isCatExpanded ? (
<ChevronDown className="w-3.5 h-3.5 text-muted-foreground/70 shrink-0" />
<ChevronDown className="w-3.5 h-3.5 text-muted-foreground shrink-0" />
) : (
<ChevronRight className="w-3.5 h-3.5 text-muted-foreground/70 shrink-0" />
<ChevronRight className="w-3.5 h-3.5 text-muted-foreground shrink-0" />
)}
<span className="text-sm shrink-0">
<CategoryIcon
@ -1105,7 +1105,7 @@ export default function ComplianceUI({
<span className="text-[11px] font-medium text-foreground flex-1 min-w-0 truncate">
{category.name}
</span>
<span className="text-[10px] text-muted-foreground/70 shrink-0">
<span className="text-[10px] text-muted-foreground shrink-0">
{category.prompts.length}
</span>
{selectedInCat > 0 && (
@ -1118,7 +1118,7 @@ export default function ComplianceUI({
{isCatExpanded && (
<div>
<div className="px-2.5 py-1 flex items-center justify-between">
<p className="text-[10px] text-muted-foreground/70 leading-relaxed flex-1 mr-2 line-clamp-2">
<p className="text-[10px] text-muted-foreground leading-relaxed flex-1 mr-2 line-clamp-2">
{category.description}
</p>
<button
@ -1156,7 +1156,7 @@ export default function ComplianceUI({
e.stopPropagation();
deleteCustomPrompt(prompt.id);
}}
className="opacity-0 group-hover:opacity-100 p-0.5 text-muted-foreground/70 hover:text-destructive transition-all shrink-0"
className="opacity-0 group-hover:opacity-100 p-0.5 text-muted-foreground hover:text-destructive transition-all shrink-0"
aria-label="Delete"
>
<Trash2 className="w-3 h-3" />
@ -1234,7 +1234,7 @@ export default function ComplianceUI({
})}
</div>
) : (
<p className="text-[11px] text-muted-foreground/70">
<p className="text-[11px] text-muted-foreground">
No policies or guardrails selected select above to test against specific rules.
</p>
)}
@ -1245,7 +1245,7 @@ export default function ComplianceUI({
<div className="flex items-center justify-center h-full min-h-[120px]">
<div className="text-center">
<div className="w-10 h-10 bg-muted rounded-xl flex items-center justify-center mx-auto mb-3">
<MessageSquare className="w-5 h-5 text-muted-foreground/70" />
<MessageSquare className="w-5 h-5 text-muted-foreground" />
</div>
<p className="text-xs text-muted-foreground">Type a prompt below to quickly test it.</p>
</div>
@ -1254,10 +1254,10 @@ export default function ComplianceUI({
{quickTestMessages.map((msg) => (
<div key={msg.id} className={`flex ${msg.type === "user" ? "justify-end" : "justify-start"}`}>
<div
className={`max-w-[85%] rounded-lg px-3 py-2 ${msg.type === "user" ? "bg-info text-white" : msg.result === "blocked" ? "bg-destructive/10 border border-destructive/15" : "bg-success/10 border border-success/15"}`}
className={`max-w-[85%] rounded-lg px-3 py-2 ${msg.type === "user" ? "bg-info text-info-foreground" : msg.result === "blocked" ? "bg-destructive/10 border border-destructive/15" : "bg-success/10 border border-success/15"}`}
>
<p
className={`text-xs leading-relaxed ${msg.type === "user" ? "text-white" : msg.result === "blocked" ? "text-destructive" : "text-success"}`}
className={`text-xs leading-relaxed ${msg.type === "user" ? "text-info-foreground" : msg.result === "blocked" ? "text-destructive" : "text-success"}`}
>
{msg.type === "system" && (
<span className="inline-flex items-center gap-1 font-semibold mr-1">
@ -1284,7 +1284,7 @@ export default function ComplianceUI({
{isQuickTesting && (
<div className="flex justify-start">
<div className="bg-muted rounded-lg px-3 py-2">
<Loader2 className="w-3.5 h-3.5 text-muted-foreground/70 animate-spin" />
<Loader2 className="w-3.5 h-3.5 text-muted-foreground animate-spin" />
</div>
</div>
)}
@ -1300,23 +1300,23 @@ export default function ComplianceUI({
onKeyDown={handleQuickTestKeyDown}
placeholder="Enter text to test..."
rows={3}
className="w-full px-3 pt-3 pb-1 text-sm text-foreground placeholder:text-muted-foreground/70 focus:outline-hidden resize-none"
className="w-full px-3 pt-3 pb-1 text-sm text-foreground placeholder:text-muted-foreground focus:outline-hidden resize-none"
/>
<div className="flex items-center justify-between px-3 pb-2">
<span className="text-[10px] text-muted-foreground/70">
<span className="text-[10px] text-muted-foreground">
Press <kbd className="px-1 py-0.5 bg-muted rounded-sm text-[10px] font-mono">Enter</kbd> to
submit ·{" "}
<kbd className="px-1 py-0.5 bg-muted rounded-sm text-[10px] font-mono">Shift+Enter</kbd> for new
line
</span>
<span className="text-[10px] text-muted-foreground/70 tabular-nums">{quickTestInput.length}</span>
<span className="text-[10px] text-muted-foreground tabular-nums">{quickTestInput.length}</span>
</div>
</div>
<button
type="button"
onClick={runQuickTest}
disabled={!quickTestInput.trim() || isQuickTesting || disabledPersonalKeyCreation}
className={`w-full mt-2 flex items-center justify-center gap-1.5 py-2.5 rounded-lg text-sm font-medium transition-colors ${!quickTestInput.trim() || isQuickTesting || disabledPersonalKeyCreation ? "bg-muted text-muted-foreground/70 cursor-not-allowed" : "bg-info text-white hover:bg-info/80"}`}
className={`w-full mt-2 flex items-center justify-center gap-1.5 py-2.5 rounded-lg text-sm font-medium transition-colors ${!quickTestInput.trim() || isQuickTesting || disabledPersonalKeyCreation ? "bg-muted text-muted-foreground cursor-not-allowed" : "bg-info text-info-foreground hover:bg-info/80"}`}
>
{isQuickTesting ? <Loader2 className="w-4 h-4 animate-spin" /> : <Send className="w-4 h-4" />}{" "}
{testButtonLabel}
@ -1400,7 +1400,7 @@ export default function ComplianceUI({
<div className="flex items-center justify-center h-full min-h-[120px]">
<div className="text-center">
<div className="w-12 h-12 bg-muted rounded-xl flex items-center justify-center mx-auto mb-3">
<FlaskConical className="w-6 h-6 text-muted-foreground/70" />
<FlaskConical className="w-6 h-6 text-muted-foreground" />
</div>
<p className="text-xs text-muted-foreground max-w-[240px]">
Select prompts and click Simulate to run batch compliance tests.
@ -1458,7 +1458,7 @@ export default function ComplianceUI({
<div className="flex items-start gap-2">
<div className="shrink-0 mt-0.5">
{result.status !== "complete" ? (
<Loader2 className="w-3.5 h-3.5 text-muted-foreground/70 animate-spin" />
<Loader2 className="w-3.5 h-3.5 text-muted-foreground animate-spin" />
) : result.isMatch ? (
<CheckCircle2 className="w-3.5 h-3.5 text-success" />
) : (
@ -1468,7 +1468,7 @@ export default function ComplianceUI({
<div className="flex-1 min-w-0">
<p className="text-[11px] text-foreground leading-relaxed mb-1.5">{result.prompt}</p>
<div className="flex items-center gap-1.5 flex-wrap">
<span className="text-[9px] text-muted-foreground/70 inline-flex items-center gap-0.5">
<span className="text-[9px] text-muted-foreground inline-flex items-center gap-0.5">
<CategoryIcon iconKey={result.categoryIcon} className="w-3 h-3" />
{result.category}
</span>
@ -1497,7 +1497,7 @@ export default function ComplianceUI({
return next;
});
}}
className="shrink-0 p-0.5 text-muted-foreground/70 hover:text-muted-foreground"
className="shrink-0 p-0.5 text-muted-foreground hover:text-foreground"
aria-label={isExpanded ? "Collapse" : "Expand"}
>
{isExpanded ? (
@ -1512,14 +1512,14 @@ export default function ComplianceUI({
<div className="mt-2 pt-2 border-t border-border text-[11px] space-y-1">
{result.triggeredBy && (
<div>
<span className="text-muted-foreground/70">Triggered by:</span>{" "}
<span className="text-muted-foreground">Triggered by:</span>{" "}
<span className="font-medium text-foreground bg-muted px-1.5 py-0.5 rounded-sm">
{result.triggeredBy}
</span>
</div>
)}
<div>
<span className="text-muted-foreground/70">Verdict:</span>{" "}
<span className="text-muted-foreground">Verdict:</span>{" "}
<span className={result.isMatch ? "text-success" : "text-destructive"}>
{result.isMatch
? "Correctly handled"
@ -1530,7 +1530,7 @@ export default function ComplianceUI({
</div>
{result.returnedText != null && result.returnedText !== "" && (
<div className="mt-1.5">
<span className="text-muted-foreground/70 block mb-0.5">LLM response:</span>
<span className="text-muted-foreground block mb-0.5">LLM response:</span>
<div className="text-foreground bg-muted rounded-sm px-2 py-1.5 border border-border max-h-32 overflow-y-auto whitespace-pre-wrap wrap-break-word">
{result.returnedText}
</div>

View file

@ -393,7 +393,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
return (
<div className="text-center py-12 text-muted-foreground">
<svg
className="w-12 h-12 mx-auto mb-3 text-muted-foreground/70"
className="w-12 h-12 mx-auto mb-3 text-muted-foreground"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
@ -478,7 +478,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
</span>
))}
{template.guardrails && template.guardrails.length > 4 && (
<span className="text-[10px] text-muted-foreground/70">
<span className="text-[10px] text-muted-foreground">
+{template.guardrails.length - 4} more
</span>
)}
@ -528,7 +528,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
setTestResults(null);
setTestOverallAction(null);
}}
className="text-muted-foreground/70 hover:text-muted-foreground"
className="text-muted-foreground hover:text-foreground"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
@ -853,7 +853,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
{attackExamples.map((example, index) => (
<div key={index} className="relative group">
<textarea
className="w-full rounded-lg border border-border px-3.5 py-2.5 pr-9 text-sm text-foreground placeholder-muted-foreground/70 focus:border-info focus:ring-1 focus:ring-ring overflow-hidden"
className="w-full rounded-lg border border-border px-3.5 py-2.5 pr-9 text-sm text-foreground placeholder:text-muted-foreground focus:border-info focus:ring-1 focus:ring-ring overflow-hidden"
rows={1}
style={{ minHeight: "40px", resize: "none" }}
placeholder={
@ -879,7 +879,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
{attackExamples.length > 1 && (
<button
onClick={() => handleRemoveExample(index)}
className="absolute top-2.5 right-2.5 text-muted-foreground/70 hover:text-destructive transition-colors opacity-0 group-hover:opacity-100"
className="absolute top-2.5 right-2.5 text-muted-foreground hover:text-destructive transition-colors opacity-0 group-hover:opacity-100"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
@ -902,7 +902,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
Description of what you want to block
</label>
<textarea
className="w-full rounded-lg border border-border px-3.5 py-2.5 text-sm text-foreground placeholder-muted-foreground/70 focus:border-info focus:ring-1 focus:ring-ring overflow-hidden"
className="w-full rounded-lg border border-border px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-info focus:ring-1 focus:ring-ring overflow-hidden"
rows={1}
style={{ minHeight: "60px", resize: "none" }}
placeholder="e.g. Block PII leakage and prompt injection in our customer support chatbot"

View file

@ -402,7 +402,7 @@ const PromptInfoView: React.FC<PromptInfoProps> = ({ promptId, onClose, accessTo
</TableBody>
</Table>
) : (
<p className="text-muted-foreground/70">No versions found in {selectedEnv}</p>
<p className="text-muted-foreground">No versions found in {selectedEnv}</p>
)}
</Card>
</TabsContent>

View file

@ -156,7 +156,7 @@ export const PromptCachingPanel: React.FC<{
{ttlSetting && (
<div className="mt-6 flex items-start justify-between gap-8">
<div className="min-w-0 max-w-2xl">
<p className={`font-medium ${enabled ? "" : "text-muted-foreground/70"}`}>Cache lifetime (TTL)</p>
<p className={`font-medium ${enabled ? "" : "text-muted-foreground"}`}>Cache lifetime (TTL)</p>
<p className="mt-1 break-words text-xs text-muted-foreground">{ttlSetting.field_description}</p>
</div>
<Select

View file

@ -64,7 +64,7 @@ const EndpointUsageTable: React.FC<EndpointUsageTableProps> = ({ endpointData })
</div>
<div className="flex items-center space-x-2 text-sm min-w-[100px]">
<span className="text-success font-medium">{record.successful_requests.toLocaleString()}</span>
<span className="text-muted-foreground/70">/</span>
<span className="text-muted-foreground">/</span>
<span className="text-destructive font-medium">{record.failed_requests.toLocaleString()}</span>
</div>
</div>

View file

@ -351,7 +351,7 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
[],
);
const chev = "size-3 text-muted-foreground/70";
const chev = "size-3 text-muted-foreground";
const expandIcon = showCostBreakdown ? <ChevronDown className={chev} /> : <ChevronRight className={chev} />;
const renderSummaryTile = ({ title, value, className, tooltip, expandable }: SummaryTile) => (
@ -365,9 +365,7 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
<h3 className="text-lg font-medium text-foreground">{title}</h3>
{tooltip ? (
<Tooltip>
<TooltipTrigger
render={<Info className="size-4 text-muted-foreground/70 hover:text-muted-foreground" />}
/>
<TooltipTrigger render={<Info className="size-4 text-muted-foreground hover:text-foreground" />} />
<TooltipContent>{tooltip}</TooltipContent>
</Tooltip>
) : null}

View file

@ -97,9 +97,7 @@ const SpendByProvider: React.FC<SpendByProviderProps> = ({ loading, isDateChangi
<div className="flex items-center gap-1">
<label className="text-sm text-foreground">Show Unknown</label>
<Tooltip>
<TooltipTrigger
render={<Info className="size-4 text-muted-foreground/70 hover:text-muted-foreground" />}
/>
<TooltipTrigger render={<Info className="size-4 text-muted-foreground hover:text-foreground" />} />
<TooltipContent>Requests that failed to route to a provider</TooltipContent>
</Tooltip>
</div>

View file

@ -255,7 +255,7 @@ const UsageAIChatPanel: React.FC<UsageAIChatPanelProps> = ({ open, onClose, acce
</div>
<button
onClick={handleClose}
className="text-muted-foreground/70 hover:text-muted-foreground transition-colors p-1 rounded-md hover:bg-accent"
className="text-muted-foreground hover:text-foreground transition-colors p-1 rounded-md hover:bg-accent"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
@ -295,7 +295,7 @@ const UsageAIChatPanel: React.FC<UsageAIChatPanelProps> = ({ open, onClose, acce
{/* Chat messages */}
<div className="flex-1 overflow-y-auto p-4 space-y-3 bg-muted">
{messages.length === 0 && !streamingContent && !isLoading && (
<div className="flex flex-col items-center justify-center h-full text-muted-foreground/70">
<div className="flex flex-col items-center justify-center h-full text-muted-foreground">
<svg className="w-8 h-8 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
@ -313,7 +313,7 @@ const UsageAIChatPanel: React.FC<UsageAIChatPanelProps> = ({ open, onClose, acce
<div key={idx}>
{msg.role === "user" ? (
<div className="flex justify-end">
<div className="max-w-[88%] rounded-xl px-3.5 py-2 text-sm leading-relaxed bg-info text-white">
<div className="max-w-[88%] rounded-xl px-3.5 py-2 text-sm leading-relaxed bg-info text-info-foreground">
{msg.content}
</div>
</div>
@ -383,12 +383,12 @@ const UsageAIChatPanel: React.FC<UsageAIChatPanelProps> = ({ open, onClose, acce
<div className="flex justify-between items-center mt-2">
<button
onClick={handleClear}
className="text-xs text-muted-foreground/70 hover:text-muted-foreground transition-colors"
className="text-xs text-muted-foreground hover:text-foreground transition-colors"
disabled={messages.length === 0}
>
Clear chat
</button>
<span className="text-xs text-muted-foreground/70">Enter to send</span>
<span className="text-xs text-muted-foreground">Enter to send</span>
</div>
</div>
</div>

View file

@ -593,9 +593,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
{gatewayActivity && (
<Tooltip>
<TooltipTrigger
render={
<Info className="size-4 text-muted-foreground/70 hover:text-muted-foreground" />
}
render={<Info className="size-4 text-muted-foreground hover:text-foreground" />}
/>
<TooltipContent>
Counted by the gateway when it answers a request, independent of spend logging.
@ -624,9 +622,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
<h3 className="text-lg font-medium text-foreground">Failed Requests</h3>
<Tooltip>
<TooltipTrigger
render={
<Info className="size-4 text-muted-foreground/70 hover:text-muted-foreground" />
}
render={<Info className="size-4 text-muted-foreground hover:text-foreground" />}
/>
<TooltipContent>
{gatewayActivity
@ -665,9 +661,9 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
<div className="flex items-center gap-2">
<h3 className="text-lg font-medium text-foreground">Total Tokens</h3>
{showTokenBreakdown ? (
<ChevronDown className="size-3 text-muted-foreground/70" />
<ChevronDown className="size-3 text-muted-foreground" />
) : (
<ChevronRight className="size-3 text-muted-foreground/70" />
<ChevronRight className="size-3 text-muted-foreground" />
)}
</div>
<p className="text-2xl font-bold mt-2">
@ -765,7 +761,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
<Tooltip>
<TooltipTrigger
render={
<Info className="ml-2 inline size-4 text-muted-foreground/70 hover:text-muted-foreground" />
<Info className="ml-2 inline size-4 text-muted-foreground hover:text-foreground" />
}
/>
<TooltipContent>

View file

@ -92,9 +92,13 @@
--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);
@ -130,9 +134,13 @@
--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);
@ -172,9 +180,13 @@
--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);
@ -244,7 +256,7 @@
input::placeholder,
textarea::placeholder {
color: color-mix(in oklab, var(--color-muted-foreground) 70%, transparent);
color: var(--color-muted-foreground);
}
body {

View file

@ -280,7 +280,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
<button
onClick={handleAddLink}
disabled={!newLink.url || !newLink.displayName}
className={`flex items-center px-4 py-2 rounded-md text-sm ${!newLink.url || !newLink.displayName ? "bg-border text-muted-foreground cursor-not-allowed" : "bg-success text-white hover:bg-success/80"}`}
className={`flex items-center px-4 py-2 rounded-md text-sm ${!newLink.url || !newLink.displayName ? "bg-border text-muted-foreground cursor-not-allowed" : "bg-success text-success-foreground hover:bg-success/80"}`}
>
<PlusCircleIcon className="w-4 h-4 mr-1" />
Add Link
@ -312,7 +312,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
<div className="flex space-x-2">
<button
onClick={handleSaveRearranging}
className="text-xs bg-success text-white px-3 py-1.5 rounded-sm hover:bg-success/80"
className="text-xs bg-success text-success-foreground px-3 py-1.5 rounded-sm hover:bg-success/80"
>
Save Order
</button>

View file

@ -183,15 +183,15 @@ export function LogViewer({
>
{config.label}
</span>
<span className="text-xs text-muted-foreground/70">{log.timestamp}</span>
<span className="text-xs text-muted-foreground/70">·</span>
<span className="text-xs text-muted-foreground">{log.timestamp}</span>
<span className="text-xs text-muted-foreground">·</span>
{log.model && (
<span className="min-w-0 text-xs break-words text-muted-foreground">{log.model}</span>
)}
</div>
<p className="text-sm text-foreground truncate">{log.input_snippet ?? log.input ?? "—"}</p>
</div>
<ChevronDown className="w-4 h-4 text-muted-foreground/70 shrink-0 mt-1" />
<ChevronDown className="w-4 h-4 text-muted-foreground shrink-0 mt-1" />
</button>
);
})}

View file

@ -13,7 +13,7 @@ export function MetricCard({ label, value, valueColor = "text-foreground", icon,
<div className="h-full bg-card border border-border rounded-lg p-5 flex flex-col">
<div className="flex items-center justify-between mb-1">
<span className="text-sm font-medium text-muted-foreground">{label}</span>
{icon && <span className="text-muted-foreground/70">{icon}</span>}
{icon && <span className="text-muted-foreground">{icon}</span>}
</div>
<div className={`text-3xl font-semibold ${valueColor} tracking-tight`}>{value}</div>
{subtitle && <p className="text-xs text-muted-foreground mt-1">{subtitle}</p>}

View file

@ -88,7 +88,7 @@ export const HelpIcon: React.FC<HelpIconProps> = ({ content, learnMoreHref, lear
<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/70 hover:text-muted-foreground transition-colors cursor-help focus:outline-hidden focus:ring-2 focus:ring-ring rounded-full"
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)}
@ -189,7 +189,7 @@ export const DocsMenu: React.FC<DocsMenuProps> = ({ items, children = "Docs", cl
onClick={() => setIsOpen(false)}
>
<span>{item.label}</span>
<ExternalLink className="h-3.5 w-3.5 text-muted-foreground/70 shrink-0 ml-2" aria-hidden="true" />
<ExternalLink className="h-3.5 w-3.5 text-muted-foreground shrink-0 ml-2" aria-hidden="true" />
</a>
))}
</div>

View file

@ -247,7 +247,7 @@ const UserDropdown: React.FC<UserDropdownProps> = ({ onLogout, variant = "navbar
<span className="hidden min-w-0 truncate text-left text-sm font-medium leading-none text-foreground md:inline">
{displayName}
</span>
<ChevronDown className="hidden size-2.5 shrink-0 text-muted-foreground/70 md:inline" aria-hidden />
<ChevronDown className="hidden size-2.5 shrink-0 text-muted-foreground md:inline" aria-hidden />
</PopoverTrigger>
)}
<PopoverContent

View file

@ -40,7 +40,7 @@ export default function RoleMappings({ roleMappings }: { roleMappings: RoleMappi
))}
</div>
) : (
<span className="text-muted-foreground/70 italic">No groups mapped</span>
<span className="text-muted-foreground italic">No groups mapped</span>
),
},
];
@ -48,7 +48,7 @@ export default function RoleMappings({ roleMappings }: { roleMappings: RoleMappi
<Card>
<CardContent>
<div className="flex items-center gap-3">
<Users className="w-6 h-6 text-muted-foreground/70 mb-2" />
<Users className="w-6 h-6 text-muted-foreground mb-2" />
<h3 className="mb-2 text-2xl font-semibold text-foreground">Role Mappings</h3>
</div>
<div className="space-y-8">

View file

@ -134,7 +134,7 @@ export function FallbackGroupConfig({
{/* Fallback List */}
<div className="space-y-2 min-h-[100px]">
{group.fallbackModels.length === 0 ? (
<div className="h-32 border-2 border-dashed border-border rounded-lg flex flex-col items-center justify-center text-muted-foreground/70">
<div className="h-32 border-2 border-dashed border-border rounded-lg flex flex-col items-center justify-center text-muted-foreground">
<span className="text-sm">No fallback models selected</span>
<span className="text-xs mt-1">Add models from the dropdown above</span>
</div>
@ -146,7 +146,7 @@ export function FallbackGroupConfig({
className="group flex items-center justify-between p-3 bg-card rounded-lg border border-border hover:border-indigo-300 hover:shadow-xs transition-all"
>
<div className="flex items-center gap-3">
<div className="flex items-center justify-center w-6 h-6 rounded-sm bg-muted text-muted-foreground/70 group-hover:text-indigo-500 group-hover:bg-indigo-50">
<div className="flex items-center justify-center w-6 h-6 rounded-sm bg-muted text-muted-foreground group-hover:text-indigo-500 group-hover:bg-indigo-50">
<span className="text-xs font-bold">{index + 1}</span>
</div>
<div>
@ -158,7 +158,7 @@ export function FallbackGroupConfig({
type="button"
aria-label={`Remove ${modelValue}`}
onClick={() => removeFallback(index)}
className="opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/70 hover:text-destructive p-1"
className="opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive p-1"
>
<X className="w-4 h-4" />
</button>

View file

@ -56,7 +56,7 @@ function renderFallbacksChain(
{list.map((model, i) => (
<React.Fragment key={model}>
{i > 0 && (
<span className={`${iconWrapperClass} text-muted-foreground/70`}>
<span className={`${iconWrapperClass} text-muted-foreground`}>
<ArrowRight className="h-3 w-3 shrink-0" />
</span>
)}

View file

@ -122,10 +122,10 @@ const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = fals
content={
<div>
<div>
<span className="text-muted-foreground/70">Tag Name:</span> {tag.tag}
<span className="text-muted-foreground">Tag Name:</span> {tag.tag}
</div>
<div>
<span className="text-muted-foreground/70">Spend:</span>{" "}
<span className="text-muted-foreground">Spend:</span>{" "}
{tag.usage > 0 && tag.usage < 0.01 ? "<$0.01" : `$${formatNumberWithCommas(tag.usage, 2)}`}
</div>
</div>
@ -224,15 +224,15 @@ const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = fals
<div className="relative z-50 p-3 bg-black/90 shadow-lg rounded-lg text-white max-w-xs">
<div className="space-y-1.5">
<div className="text-sm">
<span className="text-muted-foreground/70">Key Alias: </span>
<span className="text-muted-foreground">Key Alias: </span>
<span className="font-mono text-gray-100 break-all">{item?.key_alias}</span>
</div>
<div className="text-sm">
<span className="text-muted-foreground/70">Key ID: </span>
<span className="text-muted-foreground">Key ID: </span>
<span className="font-mono text-gray-100 break-all">{item?.api_key}</span>
</div>
<div className="text-sm">
<span className="text-muted-foreground/70">Spend: </span>
<span className="text-muted-foreground">Spend: </span>
<span className="text-white font-medium">${formatNumberWithCommas(item?.spend, 2)}</span>
</div>
</div>

View file

@ -76,7 +76,7 @@ const UserPopoverCell = ({
{ label: "User ID", value: userId },
].map(({ label, value }) => (
<div key={label} className="flex flex-col min-w-0">
<span className="text-muted-foreground/70">{label}</span>
<span className="text-muted-foreground">{label}</span>
{value ? (
<IdCell value={value} variant="plain" copyable className="max-w-full" />
) : (
@ -119,7 +119,7 @@ const InfoHeader = ({ label, tooltip }: { label: string; tooltip: string }) => (
<span className="flex items-center gap-1">
{label}
<HoverCard>
<HoverCardTrigger render={<Info className="size-3 text-muted-foreground/70 cursor-help" />} />
<HoverCardTrigger render={<Info className="size-3 text-muted-foreground cursor-help" />} />
<HoverCardContent className="w-auto">{tooltip}</HoverCardContent>
</HoverCard>
</span>

View file

@ -234,7 +234,7 @@ const ModelCollapsible = ({
>
<CollapsibleTrigger className="flex w-full items-center gap-2 px-4 py-3 text-left">
<ChevronDown
className={`size-4 shrink-0 text-muted-foreground/70 transition-transform ${open ? "" : "-rotate-90"}`}
className={`size-4 shrink-0 text-muted-foreground transition-transform ${open ? "" : "-rotate-90"}`}
/>
{header}
</CollapsibleTrigger>

View file

@ -310,7 +310,7 @@ const ClassificationMethodConfig: React.FC<ClassificationMethodConfigProps> = ({
<div className="flex items-center gap-2 mb-1">
<strong className="font-semibold">Classification Rubric</strong>
<SimpleTooltip content="Every rubric uses the same four tiers and the same tier definitions. They differ only in the worked examples that show the classifier where the boundary between tiers sits.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<SimpleTooltip
@ -433,7 +433,7 @@ const ClassificationMethodConfig: React.FC<ClassificationMethodConfigProps> = ({
/>
<strong className="font-semibold">Include Assistant Turns</strong>
<SimpleTooltip content="Off by default. Enabling it changes tier decisions, and therefore spend, for an existing router, and sends assistant text to the classifier model, which may be a different provider than the routed model.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<span className="text-xs text-muted-foreground">
@ -451,7 +451,7 @@ const ClassificationMethodConfig: React.FC<ClassificationMethodConfigProps> = ({
<div className="flex items-center gap-2 mb-1">
<strong className="font-semibold">Custom Technical Keywords</strong>
<SimpleTooltip content="Domain-specific terms appended to the built-in technical keyword list. Prompts containing these terms score higher on the technical dimension and route to more capable models.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<span className="block mb-2 text-xs text-muted-foreground">

View file

@ -262,7 +262,7 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
<div className="inline-flex items-center gap-2 mb-4">
<h4 className="m-0 text-xl font-semibold text-foreground">Complexity Tier Configuration</h4>
<SimpleTooltip content="Map each complexity tier to one or more models. Simple queries use cheaper/faster models, complex queries use more capable models.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
@ -291,7 +291,7 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
<div className="flex items-center gap-2 mb-2">
<strong className="text-base font-semibold">{label} Tier</strong>
<SimpleTooltip content={tierInfo.description}>
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
<span className="text-xs text-muted-foreground">
Tier {index + 1} of {TIER_KEYS.length} &middot; {tier}
@ -342,7 +342,7 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
<div className="flex items-center gap-2 mb-2">
<strong className="text-base font-semibold">Default Model</strong>
<SimpleTooltip content="Leave empty to follow the tiers. A model chosen here is pinned: it stays the default however the tiers change.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<SearchSelect

View file

@ -16,7 +16,7 @@ const EscalationKeywords: React.FC<EscalationKeywordsProps> = ({ keywords, onCha
<div className="flex items-center gap-2 mb-1">
<h4 className="m-0 text-xl font-semibold text-foreground">Escalation Keywords</h4>
<SimpleTooltip content="Case-sensitive phrases a user can include in their message to force a bump to the next-higher complexity tier when they aren't happy with results. They can force a stronger model, but not choose which one.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<span className="mb-2 block text-xs text-muted-foreground">

View file

@ -51,7 +51,7 @@ const KeywordTierRules: React.FC<KeywordTierRulesProps> = ({ rules, onChange, ti
<div className="flex items-center gap-2">
<h4 className="m-0 text-xl font-semibold text-foreground">Keyword Tier Overrides</h4>
<SimpleTooltip content="Match known terms and force the request straight to a chosen complexity tier, bypassing rule-based scoring.">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<Button variant="outline" onClick={addRule}>

View file

@ -43,7 +43,7 @@ const SemanticKeywordMatching: React.FC<SemanticKeywordMatchingProps> = ({
<div className="flex items-center gap-2">
<span className="font-medium">Semantic keyword matching</span>
<SimpleTooltip content="Recognize related phrasing beyond exact keyword matches by comparing embeddings instead of plain text. Overrides direct keyword matching">
<Info className="size-4 text-muted-foreground/70" />
<Info className="size-4 text-muted-foreground" />
</SimpleTooltip>
</div>
<span className="text-muted-foreground text-sm">

View file

@ -525,7 +525,9 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
{parsedData.length === 0 ? (
<div className="mb-6">
<div className="flex items-center mb-4">
<div className="w-8 h-8 rounded-full bg-info text-white flex items-center justify-center mr-3">1</div>
<div className="w-8 h-8 rounded-full bg-info text-info-foreground flex items-center justify-center mr-3">
1
</div>
<h3 className="text-lg font-medium">Download and fill the template</h3>
</div>
@ -604,7 +606,9 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
</div>
<div className="flex items-center mb-4">
<div className="w-8 h-8 rounded-full bg-info text-white flex items-center justify-center mr-3">2</div>
<div className="w-8 h-8 rounded-full bg-info text-info-foreground flex items-center justify-center mr-3">
2
</div>
<h3 className="text-lg font-medium">Upload your completed CSV</h3>
</div>
@ -669,7 +673,7 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
className="sr-only"
onChange={handleFileInputChange}
/>
<Upload className="size-[30px] text-muted-foreground/70 mb-2" />
<Upload className="size-[30px] text-muted-foreground mb-2" />
<p className="mb-1">Drag and drop your CSV file here</p>
<p className="text-sm text-muted-foreground mb-3">or</p>
<span className={buttonVariants({ variant: "outline", size: "sm" })}>Browse files</span>
@ -697,7 +701,9 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
) : (
<div className="mb-6">
<div className="flex items-center mb-4">
<div className="w-8 h-8 rounded-full bg-info text-white flex items-center justify-center mr-3">3</div>
<div className="w-8 h-8 rounded-full bg-info text-info-foreground flex items-center justify-center mr-3">
3
</div>
<h3 className="text-lg font-medium">
{parsedData.some((user) => user.status === "success" || user.status === "failed")
? "User Creation Results"

View file

@ -190,7 +190,7 @@ const ConversationRow: React.FC<ConversationRowProps> = ({ conv, isActive, onSel
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={() => onDelete(conv.id)}
className="bg-destructive text-white hover:bg-destructive/90"
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
Delete
</AlertDialogAction>

View file

@ -161,10 +161,10 @@ interface MCPEventPanelProps {
function MCPEventPanel({ title, open, onOpenChange, children }: MCPEventPanelProps) {
return (
<Collapsible open={open} onOpenChange={onOpenChange}>
<CollapsibleTrigger className="relative flex min-h-5 w-full items-center gap-1 pl-5 text-left text-sm font-normal leading-5 text-muted-foreground/70 hover:text-muted-foreground">
<CollapsibleTrigger className="relative flex min-h-5 w-full items-center gap-1 pl-5 text-left text-sm font-normal leading-5 text-muted-foreground hover:text-foreground">
<ChevronRight
className={cn(
"absolute left-0.5 top-0.5 size-4 text-muted-foreground/70 transition-transform",
"absolute left-0.5 top-0.5 size-4 text-muted-foreground transition-transform",
open && "rotate-90",
)}
aria-hidden="true"

View file

@ -45,7 +45,7 @@ const AutoRotationView: React.FC<AutoRotationViewProps> = ({
<StatusBadge tone={autoRotate ? "success" : "neutral"} label={autoRotate ? "Enabled" : "Disabled"} />
{autoRotate && rotationInterval && (
<>
<p className="text-sm text-muted-foreground/70"></p>
<p className="text-sm text-muted-foreground"></p>
<p className="text-sm text-muted-foreground">Every {rotationInterval}</p>
</>
)}
@ -87,7 +87,7 @@ const AutoRotationView: React.FC<AutoRotationViewProps> = ({
{!autoRotate && !lastRotationAt && !keyRotationAt && !nextRotationAt && (
<div className="flex items-center gap-2 rounded-md border border-border bg-muted p-3">
<RefreshIcon className="h-4 w-4 text-muted-foreground/70" />
<RefreshIcon className="h-4 w-4 text-muted-foreground" />
<p className="text-sm text-muted-foreground">Auto-rotation is not enabled for this key</p>
</div>
)}

View file

@ -18,7 +18,7 @@ export default function RouterSettingsSummary({
emptyText = "No router settings configured",
}: RouterSettingsSummaryProps) {
if (!hasRouterSettings(routerSettings)) {
return <div className="text-muted-foreground/70">{emptyText}</div>;
return <div className="text-muted-foreground">{emptyText}</div>;
}
const settings = routerSettings as Record<string, unknown>;
@ -44,7 +44,7 @@ export default function RouterSettingsSummary({
{fallbacks.map(([model, targets]) => (
<div key={model} className="text-xs text-muted-foreground">
<span className="font-medium">{model}</span>
<span className="mx-1 text-muted-foreground/70">-&gt;</span>
<span className="mx-1 text-muted-foreground">-&gt;</span>
{Array.isArray(targets) ? targets.join(", ") : String(targets)}
</div>
))}

View file

@ -87,7 +87,7 @@ export function BudgetFallbacksEditor({ value, onChange, availableModels }: Budg
<button
type="button"
onClick={() => removeEntry(entry.id)}
className="absolute top-2 right-2 text-muted-foreground/70 hover:text-destructive transition-colors p-1"
className="absolute top-2 right-2 text-muted-foreground hover:text-destructive transition-colors p-1"
>
<X className="w-4 h-4" />
</button>
@ -125,7 +125,7 @@ export function BudgetFallbacksEditor({ value, onChange, availableModels }: Budg
className="w-full"
/>
{entry.fallbackModels.length > 1 && (
<div className="text-[10px] text-muted-foreground/70 mt-1 ml-1">
<div className="text-[10px] text-muted-foreground mt-1 ml-1">
Tried in order; first model still within its own budget is used
</div>
)}

View file

@ -97,7 +97,7 @@ export function LoggingSettingsView({
</div>
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-muted border border-border">
<CogIcon className="h-4 w-4 text-muted-foreground/70" />
<CogIcon className="h-4 w-4 text-muted-foreground" />
<span className="text-muted-foreground text-sm">No logging integrations configured</span>
</div>
)}
@ -140,7 +140,7 @@ export function LoggingSettingsView({
</div>
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-muted border border-border">
<BanIcon className="h-4 w-4 text-muted-foreground/70" />
<BanIcon className="h-4 w-4 text-muted-foreground" />
<span className="text-muted-foreground text-sm">No callbacks disabled</span>
</div>
)}

View file

@ -87,7 +87,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
<div className={`w-2 h-2 rounded-full ${step === 1 ? "bg-info" : "bg-border"}`} />
<div className={`w-2 h-2 rounded-full ${step === 2 ? "bg-info" : "bg-border"}`} />
</div>
<button onClick={handleClose} className="text-muted-foreground/70 hover:text-muted-foreground">
<button onClick={handleClose} className="text-muted-foreground hover:text-foreground">
<X className="size-4" />
</button>
</div>
@ -99,7 +99,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
<div className="w-14 h-14 rounded-xl bg-linear-to-br from-teal-400 to-cyan-600 flex items-center justify-center text-white font-bold text-xl shadow-sm">
L
</div>
<ArrowRight className="size-4.5 text-muted-foreground/70" />
<ArrowRight className="size-4.5 text-muted-foreground" />
<div className="w-14 h-14 rounded-xl bg-linear-to-br from-blue-600 to-indigo-800 flex items-center justify-center text-white font-bold text-xl shadow-sm">
{firstLetter}
</div>
@ -158,7 +158,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
</button>
<button
onClick={handleClose}
className="mt-3 w-full text-muted-foreground/70 hover:text-muted-foreground text-sm py-2"
className="mt-3 w-full text-muted-foreground hover:text-foreground text-sm py-2"
>
Cancel
</button>
@ -223,7 +223,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
<button
onClick={handleAuthorize}
disabled={loading}
className="w-full bg-info hover:bg-info/80 disabled:opacity-60 text-white font-medium py-3 px-6 rounded-xl flex items-center justify-center gap-2 transition-colors"
className="w-full bg-info hover:bg-info/80 disabled:opacity-60 text-info-foreground font-medium py-3 px-6 rounded-xl flex items-center justify-center gap-2 transition-colors"
>
<Lock className="size-4" /> Connect &amp; Authorize
</button>

View file

@ -135,7 +135,7 @@ function RunHealthCheckButton({
className={cn(
"rounded-md p-2 transition-colors",
isLoading
? "cursor-not-allowed bg-muted text-muted-foreground/70"
? "cursor-not-allowed bg-muted text-muted-foreground"
: "text-indigo-600 hover:bg-indigo-50 hover:text-indigo-700",
)}
>

View file

@ -206,7 +206,7 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
<button
onClick={handleAddAlias}
disabled={!newAlias.aliasName || !newAlias.targetModelGroup}
className={`flex items-center px-4 py-2 rounded-md text-sm ${!newAlias.aliasName || !newAlias.targetModelGroup ? "bg-border text-muted-foreground cursor-not-allowed" : "bg-success text-white hover:bg-success/80"}`}
className={`flex items-center px-4 py-2 rounded-md text-sm ${!newAlias.aliasName || !newAlias.targetModelGroup ? "bg-border text-muted-foreground cursor-not-allowed" : "bg-success text-success-foreground hover:bg-success/80"}`}
>
<PlusCircleIcon className="w-4 h-4 mr-1" />
Add Alias

View file

@ -96,7 +96,7 @@ export function AgentPermissions({ agents, agentAccessGroups = [], accessToken }
</div>
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-muted border border-border">
<UserGroupIcon className="h-4 w-4 text-muted-foreground/70" />
<UserGroupIcon className="h-4 w-4 text-muted-foreground" />
<p className="text-muted-foreground text-sm">No agents or access groups configured</p>
</div>
)}

View file

@ -173,9 +173,9 @@ export function MCPServerPermissions({
{toolsForServer.length === 1 ? "tool" : "tools"}
</span>
{isExpanded ? (
<ChevronDownIcon className="h-3.5 w-3.5 text-muted-foreground/70 ml-0.5" />
<ChevronDownIcon className="h-3.5 w-3.5 text-muted-foreground ml-0.5" />
) : (
<ChevronRightIcon className="h-3.5 w-3.5 text-muted-foreground/70 ml-0.5" />
<ChevronRightIcon className="h-3.5 w-3.5 text-muted-foreground ml-0.5" />
)}
</div>
)}
@ -229,9 +229,9 @@ export function MCPServerPermissions({
<span className="text-xs font-medium text-muted-foreground">{toolCount}</span>
<span className="text-xs text-muted-foreground">{toolCount === 1 ? "tool" : "tools"}</span>
{isExpanded ? (
<ChevronDownIcon className="h-3.5 w-3.5 text-muted-foreground/70 ml-0.5" />
<ChevronDownIcon className="h-3.5 w-3.5 text-muted-foreground ml-0.5" />
) : (
<ChevronRightIcon className="h-3.5 w-3.5 text-muted-foreground/70 ml-0.5" />
<ChevronRightIcon className="h-3.5 w-3.5 text-muted-foreground ml-0.5" />
)}
</div>
)}
@ -258,7 +258,7 @@ export function MCPServerPermissions({
</div>
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-muted border border-border">
<ServerIcon className="h-4 w-4 text-muted-foreground/70" />
<ServerIcon className="h-4 w-4 text-muted-foreground" />
<p className="text-muted-foreground text-sm">No MCP servers, access groups, or toolsets configured</p>
</div>
)}

View file

@ -69,7 +69,7 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor
</div>
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-muted border border-border">
<DatabaseIcon className="h-4 w-4 text-muted-foreground/70" />
<DatabaseIcon className="h-4 w-4 text-muted-foreground" />
<p className="text-muted-foreground text-sm">No vector stores configured</p>
</div>
)}

View file

@ -597,7 +597,7 @@ const PublicModelHub: React.FC<PublicModelHubProps> = ({ accessToken, isEmbedded
<div className="flex items-center space-x-2 mb-3">
<p className="text-sm font-medium text-foreground">Search Models:</p>
<Tooltip>
<TooltipTrigger render={<Info className="w-4 h-4 text-muted-foreground/70 cursor-help" />} />
<TooltipTrigger render={<Info className="w-4 h-4 text-muted-foreground cursor-help" />} />
<TooltipContent side="top">
Smart search with relevance ranking - finds models containing your search terms, ranked by
relevance. Try searching &apos;xai grok-4&apos;, &apos;claude-4&apos;, &apos;gpt-4&apos;, or
@ -606,7 +606,7 @@ const PublicModelHub: React.FC<PublicModelHubProps> = ({ accessToken, isEmbedded
</Tooltip>
</div>
<div className="relative">
<SearchIcon className="w-4 h-4 text-muted-foreground/70 absolute left-3 top-1/2 transform -translate-y-1/2" />
<SearchIcon className="w-4 h-4 text-muted-foreground absolute left-3 top-1/2 transform -translate-y-1/2" />
<input
type="text"
placeholder="Search model names... (smart search enabled)"
@ -731,14 +731,12 @@ const PublicModelHub: React.FC<PublicModelHubProps> = ({ accessToken, isEmbedded
<div className="flex items-center space-x-2 mb-3">
<p className="text-sm font-medium text-foreground">Search Agents:</p>
<Tooltip>
<TooltipTrigger
render={<Info className="w-4 h-4 text-muted-foreground/70 cursor-help" />}
/>
<TooltipTrigger render={<Info className="w-4 h-4 text-muted-foreground cursor-help" />} />
<TooltipContent side="top">Search agents by name or description</TooltipContent>
</Tooltip>
</div>
<div className="relative">
<SearchIcon className="w-4 h-4 text-muted-foreground/70 absolute left-3 top-1/2 transform -translate-y-1/2" />
<SearchIcon className="w-4 h-4 text-muted-foreground absolute left-3 top-1/2 transform -translate-y-1/2" />
<input
type="text"
placeholder="Search agent names or descriptions..."
@ -799,14 +797,12 @@ const PublicModelHub: React.FC<PublicModelHubProps> = ({ accessToken, isEmbedded
<div className="flex items-center space-x-2 mb-3">
<p className="text-sm font-medium text-foreground">Search MCP Servers:</p>
<Tooltip>
<TooltipTrigger
render={<Info className="w-4 h-4 text-muted-foreground/70 cursor-help" />}
/>
<TooltipTrigger render={<Info className="w-4 h-4 text-muted-foreground cursor-help" />} />
<TooltipContent side="top">Search MCP servers by name or description</TooltipContent>
</Tooltip>
</div>
<div className="relative">
<SearchIcon className="w-4 h-4 text-muted-foreground/70 absolute left-3 top-1/2 transform -translate-y-1/2" />
<SearchIcon className="w-4 h-4 text-muted-foreground absolute left-3 top-1/2 transform -translate-y-1/2" />
<input
type="text"
placeholder="Search MCP server names or descriptions..."

View file

@ -295,7 +295,7 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
<span className="text-foreground">{formatDisplayRange(value.from, value.to)}</span>
</span>
<svg
className={`w-4 h-4 text-muted-foreground/70 transition-transform ${isOpen ? "rotate-180" : ""}`}
className={`w-4 h-4 text-muted-foreground transition-transform ${isOpen ? "rotate-180" : ""}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"

View file

@ -13,7 +13,7 @@ export const ChartLoader: React.FC<ChartLoaderProps> = ({ isDateChanging = false
<span className="text-muted-foreground text-sm font-medium">
{isDateChanging ? "Processing date selection..." : "Loading chart data..."}
</span>
<span className="text-muted-foreground/70 text-xs mt-1">
<span className="text-muted-foreground text-xs mt-1">
{isDateChanging ? "This will only take a moment" : "Fetching your data"}
</span>
</div>

View file

@ -1048,7 +1048,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
<div key={index} className="space-y-2">
<div className="flex items-center gap-2">
<Badge variant="secondary">{policy}</Badge>
{loadingPolicies && <p className="text-xs text-muted-foreground/70">Loading guardrails...</p>}
{loadingPolicies && <p className="text-xs text-muted-foreground">Loading guardrails...</p>}
</div>
{!loadingPolicies && policyGuardrails[policy] && policyGuardrails[policy].length > 0 && (
<div className="ml-4 pl-3 border-l-2 border-border">
@ -1743,14 +1743,14 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
{(() => {
const aliasEntries = Object.entries(info.litellm_model_table?.model_aliases ?? {});
if (aliasEntries.length === 0) {
return <div className="text-muted-foreground/70">No model aliases configured</div>;
return <div className="text-muted-foreground">No model aliases configured</div>;
}
return (
<div className="mt-1 space-y-1">
{aliasEntries.map(([alias, target]) => (
<div key={alias} className="text-sm">
<span className="font-mono">{alias}</span>
<span className="text-muted-foreground/70">{" -> "}</span>
<span className="text-muted-foreground">{" -> "}</span>
<span className="font-mono">{target}</span>
</div>
))}
@ -1850,7 +1850,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
{info.router_settings.enable_tag_filtering && <div>Tag Filtering: Enabled</div>}
</div>
) : (
<div className="text-muted-foreground/70">No router settings configured</div>
<div className="text-muted-foreground">No router settings configured</div>
)}
</div>
<div>

View file

@ -100,7 +100,7 @@ function UserField({ userAlias, userEmail, userId }: { userAlias?: string | null
{ label: "User ID", value: userId || null },
].map(({ label, value }) => (
<div key={label} className="flex flex-col min-w-0">
<span className="text-muted-foreground/70">{label}</span>
<span className="text-muted-foreground">{label}</span>
{value ? (
<div className="flex min-w-0 items-center gap-1">
<span className="min-w-0 flex-1 truncate font-mono text-xs" title={value}>

View file

@ -695,7 +695,7 @@ export default function KeyInfoView({
<Badge variant="secondary" className="min-w-0 break-words">
{policy}
</Badge>
{loadingPolicies && <p className="text-xs text-muted-foreground/70">Loading guardrails...</p>}
{loadingPolicies && <p className="text-xs text-muted-foreground">Loading guardrails...</p>}
</div>
{!loadingPolicies && policyGuardrails[policy] && policyGuardrails[policy].length > 0 && (
<div className="ml-4 pl-3 border-l-2 border-border">
@ -883,7 +883,7 @@ export default function KeyInfoView({
{Object.entries(currentKeyData.budget_fallbacks).map(([model, fallbacks]) => (
<div key={model} className="text-xs text-muted-foreground">
<span className="font-medium">{model}</span>
<span className="mx-1 text-muted-foreground/70">-&gt;</span>
<span className="mx-1 text-muted-foreground">-&gt;</span>
{fallbacks.join(", ")}
</div>
))}

View file

@ -68,7 +68,7 @@ const ComplianceCard = ({
) : error ? (
<TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="text-muted-foreground/70 text-sm" />}>--</TooltipTrigger>
<TooltipTrigger render={<span className="text-muted-foreground text-sm" />}>--</TooltipTrigger>
<TooltipContent>{error}</TooltipContent>
</Tooltip>
</TooltipProvider>
@ -120,7 +120,7 @@ const ComplianceCard = ({
<div className="min-w-0">
<div className="flex items-center gap-2">
<span className="text-sm font-medium text-foreground">{check.check_name}</span>
<span className="text-[10px] font-mono text-muted-foreground/70">{check.article}</span>
<span className="text-[10px] font-mono text-muted-foreground">{check.article}</span>
</div>
<p className="text-xs text-muted-foreground mt-0.5">{check.detail}</p>
</div>

View file

@ -430,7 +430,7 @@ const RequestLifecycle = ({ entries }: { entries: GuardrailInformation[] }) => {
{item.status}
</span>
)}
<span className="text-xs text-muted-foreground/70 font-mono ml-auto shrink-0">T+{item.offsetMs}ms</span>
<span className="text-xs text-muted-foreground font-mono ml-auto shrink-0">T+{item.offsetMs}ms</span>
</div>
</div>
</div>
@ -670,7 +670,7 @@ const GuardrailViewer = ({ data, accessToken, logEntry }: GuardrailViewerProps)
<span className="text-sm text-muted-foreground">
{guardrailEntries.length} guardrail{guardrailEntries.length !== 1 ? "s" : ""} evaluated
</span>
<span className="text-muted-foreground/70">|</span>
<span className="text-muted-foreground">|</span>
<span
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold ${
allPassed

View file

@ -346,7 +346,7 @@ export function LogDetailsDrawer({
<button
type="button"
onClick={handleCopyLeftPanelId}
className="text-muted-foreground/70 hover:text-muted-foreground"
className="text-muted-foreground hover:text-foreground"
aria-label="Copy trace id"
>
{copiedLeftPanelId ? <Check className="size-3" /> : <Copy className="size-3" />}

View file

@ -143,7 +143,7 @@ export const getRequestLogsTableColumns = ({
return (
<div className="flex flex-col items-end">
{spend ? <CellTooltip content={`$${String(spend)}`} trigger={money} /> : money}
{isMultiCallSession && <span className="text-[10px] text-muted-foreground/70">session total</span>}
{isMultiCallSession && <span className="text-[10px] text-muted-foreground">session total</span>}
{mcpCount > 0 && mcpSpend > 0 && (
<span className="text-[10px] text-warning">
incl. {getSpendString(mcpSpend)} from {mcpCount} MCP
@ -253,7 +253,7 @@ export const getRequestLogsTableColumns = ({
return (
<span className="text-sm">
{String(log.total_tokens || "0")}
<span className="text-muted-foreground/70 text-xs ml-1">
<span className="text-muted-foreground text-xs ml-1">
({String(log.prompt_tokens || "0")}+{String(log.completion_tokens || "0")})
</span>
</span>

View file

@ -13,7 +13,7 @@ export const SparkleIcon = ({ size = 12 }: { size?: number }) => (
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="shrink-0 text-muted-foreground/70"
className="shrink-0 text-muted-foreground"
>
<path d="M12 3l1.912 5.813a2 2 0 0 0 1.275 1.275L21 12l-5.813 1.912a2 2 0 0 0-1.275 1.275L12 21l-1.912-5.813a2 2 0 0 0-1.275-1.275L3 12l5.813-1.912a2 2 0 0 0 1.275-1.275L12 3z" />
</svg>