mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-07-02 04:12:36 +00:00
feat: add semantic status-color tokens; migrate MCP status badge
Add a status-color layer (status-{success|info|warning|error|neutral} plus
-subtle variants) to style.css and the unified createTailwindColors map, with a
blue palette for the info hue. Migrate MCPStatusBadge (badges + dots) and
MCPCardActions to the new tokens, removing all hardcoded status colors and
dark: twins. Status colors are now themeable like the rest of the system.
This commit is contained in:
parent
daeb899859
commit
b126d2ed0b
4 changed files with 51 additions and 15 deletions
|
|
@ -92,7 +92,7 @@ export default function MCPCardActions({
|
|||
>
|
||||
<div className="relative size-4">
|
||||
<Spinner className="size-4 group-hover:opacity-0" />
|
||||
<X className="absolute inset-0 size-4 text-red-500 opacity-0 group-hover:opacity-100" />
|
||||
<X className="absolute inset-0 size-4 text-text-destructive opacity-0 group-hover:opacity-100" />
|
||||
</div>
|
||||
</TooltipAnchor>
|
||||
) : (
|
||||
|
|
@ -171,7 +171,7 @@ export default function MCPCardActions({
|
|||
<TooltipAnchor
|
||||
description={localize('com_ui_revoke')}
|
||||
side="top"
|
||||
className={cn(buttonBaseClass, 'text-red-500 hover:text-red-600')}
|
||||
className={cn(buttonBaseClass, 'text-text-destructive')}
|
||||
aria-label={localize('com_ui_revoke')}
|
||||
role="button"
|
||||
onClick={onRevoke}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export default function MCPStatusBadge({
|
|||
aria-live="polite"
|
||||
className={cn(
|
||||
badgeBaseClass,
|
||||
'bg-blue-50 text-blue-600 dark:bg-blue-950 dark:text-blue-400',
|
||||
'bg-status-info-subtle text-status-info',
|
||||
)}
|
||||
>
|
||||
<Spinner className="size-3" />
|
||||
|
|
@ -63,7 +63,7 @@ export default function MCPStatusBadge({
|
|||
aria-live="polite"
|
||||
className={cn(
|
||||
badgeBaseClass,
|
||||
'bg-blue-50 text-blue-600 dark:bg-blue-950 dark:text-blue-400',
|
||||
'bg-status-info-subtle text-status-info',
|
||||
)}
|
||||
>
|
||||
<Spinner className="size-3" />
|
||||
|
|
@ -81,7 +81,7 @@ export default function MCPStatusBadge({
|
|||
role="status"
|
||||
className={cn(
|
||||
badgeBaseClass,
|
||||
'bg-amber-50 text-amber-600 dark:bg-amber-950 dark:text-amber-400',
|
||||
'bg-status-warning-subtle text-status-warning',
|
||||
)}
|
||||
>
|
||||
<PlugZap className="size-3" aria-hidden="true" />
|
||||
|
|
@ -95,7 +95,7 @@ export default function MCPStatusBadge({
|
|||
role="status"
|
||||
className={cn(
|
||||
badgeBaseClass,
|
||||
'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400',
|
||||
'bg-status-neutral-subtle text-status-neutral',
|
||||
)}
|
||||
>
|
||||
<span>{localize('com_nav_mcp_status_disconnected')}</span>
|
||||
|
|
@ -108,7 +108,7 @@ export default function MCPStatusBadge({
|
|||
return (
|
||||
<div
|
||||
role="status"
|
||||
className={cn(badgeBaseClass, 'bg-red-50 text-red-600 dark:bg-red-950 dark:text-red-400')}
|
||||
className={cn(badgeBaseClass, 'bg-status-error-subtle text-status-error')}
|
||||
>
|
||||
<span>{localize('com_nav_mcp_status_error')}</span>
|
||||
</div>
|
||||
|
|
@ -122,7 +122,7 @@ export default function MCPStatusBadge({
|
|||
role="status"
|
||||
className={cn(
|
||||
badgeBaseClass,
|
||||
'bg-green-50 text-green-600 dark:bg-green-950 dark:text-green-400',
|
||||
'bg-status-success-subtle text-status-success',
|
||||
)}
|
||||
>
|
||||
<Check className="size-3" aria-hidden="true" />
|
||||
|
|
@ -149,31 +149,31 @@ export function getStatusDotColor(
|
|||
isInitializing?: boolean,
|
||||
): string {
|
||||
if (isInitializing) {
|
||||
return 'bg-blue-500';
|
||||
return 'bg-status-info';
|
||||
}
|
||||
|
||||
if (!serverStatus) {
|
||||
return 'bg-gray-400';
|
||||
return 'bg-status-neutral';
|
||||
}
|
||||
|
||||
const { connectionState, requiresOAuth } = serverStatus;
|
||||
|
||||
if (connectionState === 'connecting') {
|
||||
return 'bg-blue-500';
|
||||
return 'bg-status-info';
|
||||
}
|
||||
|
||||
if (connectionState === 'connected') {
|
||||
return 'bg-green-500';
|
||||
return 'bg-status-success';
|
||||
}
|
||||
|
||||
if (connectionState === 'error') {
|
||||
return 'bg-red-500';
|
||||
return 'bg-status-error';
|
||||
}
|
||||
|
||||
if (connectionState === 'disconnected') {
|
||||
// Needs OAuth = amber, otherwise gray
|
||||
return requiresOAuth ? 'bg-amber-500' : 'bg-gray-400';
|
||||
return requiresOAuth ? 'bg-status-warning' : 'bg-status-neutral';
|
||||
}
|
||||
|
||||
return 'bg-gray-400';
|
||||
return 'bg-status-neutral';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@
|
|||
--amber-800: #92400e;
|
||||
--amber-900: #78350f;
|
||||
--amber-950: #451a03;
|
||||
--blue-50: #eff6ff;
|
||||
--blue-400: #60a5fa;
|
||||
--blue-500: #3b82f6;
|
||||
--blue-600: #2563eb;
|
||||
--blue-950: #172554;
|
||||
--brand-purple: #ab68ff;
|
||||
--gizmo-gray-500: #999;
|
||||
--gizmo-gray-600: #666;
|
||||
|
|
@ -102,6 +107,16 @@ html {
|
|||
--border-heavy: var(--gray-400);
|
||||
--border-xheavy: var(--gray-500);
|
||||
--border-destructive: var(--red-600);
|
||||
--status-success: var(--green-600);
|
||||
--status-success-subtle: var(--green-50);
|
||||
--status-info: var(--blue-600);
|
||||
--status-info-subtle: var(--blue-50);
|
||||
--status-warning: var(--amber-600);
|
||||
--status-warning-subtle: var(--amber-50);
|
||||
--status-error: var(--red-600);
|
||||
--status-error-subtle: var(--red-50);
|
||||
--status-neutral: var(--gray-600);
|
||||
--status-neutral-subtle: var(--gray-100);
|
||||
/* These are test styles */
|
||||
|
||||
--background: 0 0% 100%;
|
||||
|
|
@ -164,6 +179,16 @@ html {
|
|||
--border-heavy: var(--gray-500);
|
||||
--border-xheavy: var(--gray-400);
|
||||
--border-destructive: var(--red-500);
|
||||
--status-success: var(--green-400);
|
||||
--status-success-subtle: var(--green-950);
|
||||
--status-info: var(--blue-400);
|
||||
--status-info-subtle: var(--blue-950);
|
||||
--status-warning: var(--amber-400);
|
||||
--status-warning-subtle: var(--amber-950);
|
||||
--status-error: var(--red-400);
|
||||
--status-error-subtle: var(--red-950);
|
||||
--status-neutral: var(--gray-400);
|
||||
--status-neutral-subtle: var(--gray-800);
|
||||
/* These are test styles */
|
||||
|
||||
--background: 0 0% 7%;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,17 @@ function createTailwindColors() {
|
|||
'border-xheavy': cssVar('--border-xheavy'),
|
||||
'border-destructive': cssVar('--border-destructive'),
|
||||
|
||||
'status-success': cssVar('--status-success'),
|
||||
'status-success-subtle': cssVar('--status-success-subtle'),
|
||||
'status-info': cssVar('--status-info'),
|
||||
'status-info-subtle': cssVar('--status-info-subtle'),
|
||||
'status-warning': cssVar('--status-warning'),
|
||||
'status-warning-subtle': cssVar('--status-warning-subtle'),
|
||||
'status-error': cssVar('--status-error'),
|
||||
'status-error-subtle': cssVar('--status-error-subtle'),
|
||||
'status-neutral': cssVar('--status-neutral'),
|
||||
'status-neutral-subtle': cssVar('--status-neutral-subtle'),
|
||||
|
||||
border: hslVar('--border'),
|
||||
input: hslVar('--input'),
|
||||
'switch-unchecked': hslVar('--switch-unchecked'),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue