Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/components/auth/AuthSuccessPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useEffect, useRef } from "react";
import { CircleCheck } from "lucide-react";
import { Button } from "@/components/ui/button";
import { STATUS_ICON } from "@/lib/status";

/**
* Shared success state for ResetPassword / PasswordChangeRequired: a
* CircleCheck heading (focus-managed for screen-reader/keyboard users),
* success-icon heading (focus-managed for screen-reader/keyboard users),
* body copy, and a single CTA. Not used by ForgotPassword, which shows its
* success state as an InlineNotification instead of this pattern.
*/
Expand Down Expand Up @@ -37,10 +37,7 @@ export function AuthSuccessPanel({
tabIndex={-1}
className="flex items-center gap-2 text-base font-semibold leading-6 text-neutral-900 dark:text-neutral-100 outline-none"
>
<CircleCheck
className="size-6 shrink-0 text-emerald-500 dark:text-emerald-400"
aria-hidden="true"
/>
<STATUS_ICON.success className="size-6 shrink-0 text-success" aria-hidden="true" />
{title}
</h1>
<p className="text-[13px] leading-4 text-neutral-500 dark:text-neutral-400">{body}</p>
Expand Down
4 changes: 2 additions & 2 deletions src/components/dashboard/StatusDot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { cn } from "@/lib/utils";
export type StatusTone = "success" | "error" | "warning" | "muted";

const TONE_CLASS: Record<StatusTone, string> = {
success: "bg-green-500",
success: "bg-success",
error: "bg-destructive",
warning: "bg-yellow-500",
warning: "bg-warning",
muted: "bg-muted-foreground",
};

Expand Down
10 changes: 7 additions & 3 deletions src/components/dashboard/StatusHeadline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,23 @@
* `action` are slots the fuller #5847 / default-state content fills in.
*/

import { Activity, AlertTriangle, Info } from "lucide-react";
import { Activity, Info } from "lucide-react";
import type { ComponentType, ReactNode } from "react";
import { useIntl } from "react-intl";

import { cn } from "@/lib/utils";
import { STATUS_ICON } from "@/lib/status";
import type { Severity } from "./homeStates";
import { resolveHeadline, type HeadlineCondition } from "./resolveHeadline";

// success/info keep their own dashboard-specific glyphs (a pulse for "all
// active", not a generic checkmark); warning/error consume the shared
// severity icons so the two no longer render identically.
const SEVERITY_ICON: Record<Severity, ComponentType<{ className?: string }>> = {
success: Activity,
info: Info,
warning: AlertTriangle,
error: AlertTriangle,
warning: STATUS_ICON.warning,
error: STATUS_ICON.error,
};

// Severity is conveyed by the icon shape and the message, not by colour: the
Expand Down
5 changes: 3 additions & 2 deletions src/components/gateways/CreateServerForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, type ReactNode } from "react";
import { useIntl } from "react-intl";
import { ChevronRight, CircleAlert, Server } from "lucide-react";
import { ChevronRight, Server } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { TagInput } from "@/components/ui/tag-input";
Expand All @@ -15,6 +15,7 @@ import { MAX_TAGS } from "@/utils/tags";
import type { CreateServerDetails } from "@/components/gateways/types";
import type { Visibility } from "@/types/server";
import { VisibilityInfoPopover } from "@/components/common/VisibilityInfoPopover";
import { STATUS_ICON } from "@/lib/status";

const visibilityOptions: Array<{
value: Visibility;
Expand Down Expand Up @@ -111,7 +112,7 @@ export function CreateServerForm({
role="alert"
aria-live="assertive"
>
<CircleAlert className="mt-0.5 size-4 shrink-0" aria-hidden="true" />
<STATUS_ICON.error className="mt-0.5 size-4 shrink-0" aria-hidden="true" />
<p>{displayedSubmitError}</p>
</div>
)}
Expand Down
4 changes: 2 additions & 2 deletions src/components/gateways/SourceSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ function getStatusConfig(status: ServerStatus) {
return {
Icon: Activity,
labelId: "gateways.source.status.active",
className: "text-emerald-400",
className: "text-success",
};
case "warning":
return {
Icon: TriangleAlert,
labelId: "gateways.source.status.warning",
className: "text-amber-400",
className: "text-warning",
};
case "offline":
return {
Expand Down
2 changes: 1 addition & 1 deletion src/components/mcp-servers/AdvancedSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ export function AdvancedSettings({
</div>
{oneTimeAuth && (
<div className="mt-3 flex items-start gap-3 rounded-md bg-neutral-50 p-3 dark:bg-neutral-800">
<TriangleAlert className="text-yellow-300 mt-0.5 h-4 w-4 shrink-0" />
<TriangleAlert className="text-warning mt-0.5 h-4 w-4 shrink-0" />
<p className="text-sm text-neutral-600 dark:text-neutral-400">
{intl.formatMessage({ id: "mcpServer.advanced.oneTimeAuthWarning" })}
</p>
Expand Down
23 changes: 12 additions & 11 deletions src/components/mcp-servers/MCPServerForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useState, type ReactNode } from "react";
import { useIntl } from "react-intl";
import { ChevronDown, CircleAlert } from "lucide-react";
import { ChevronDown } from "lucide-react";
import { Button } from "@/components/ui/button";
import { InlineNotification } from "@/components/ui/inline-notification";
import { Input } from "@/components/ui/input";
Expand All @@ -10,6 +10,7 @@ import { AdvancedSettings } from "@/components/mcp-servers/AdvancedSettings";
import { ExposeComponentsForm } from "@/components/gateways/ExposeComponentsForm";
import { useRouter } from "@/router";
import { useMCPServerForm, type TransportType } from "@/hooks/useMCPServerForm";
import { STATUS_ICON } from "@/lib/status";

interface MCPServerFormProps {
isOpen: boolean;
Expand Down Expand Up @@ -192,8 +193,8 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
</div>

{fetchError && serverId && (
<div className="rounded-md border border-red-200 bg-red-50 p-3 dark:border-red-900/50 dark:bg-red-950/50">
<p className="text-sm text-red-600 dark:text-red-400">
<div className="rounded-md border border-destructive/30 bg-destructive/10 p-3">
<p className="text-sm text-destructive">
{intl.formatMessage({ id: "mcpServer.form.fetchError" }, { error: fetchError })}
</p>
</div>
Expand Down Expand Up @@ -240,7 +241,7 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
className="inline-flex items-center gap-0.5 text-sm font-medium text-neutral-900 dark:text-neutral-100"
>
{intl.formatMessage({ id: "mcpServer.form.nameLabel" })}
<span className="text-red-500">*</span>
<span className="text-destructive">*</span>
<span className="sr-only">
{intl.formatMessage({ id: "mcpServer.form.required" })}
</span>
Expand All @@ -255,7 +256,7 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
aria-describedby={errors.name ? "name-error" : undefined}
/>
{errors.name && (
<p id="name-error" className="text-sm text-red-500">
<p id="name-error" className="text-sm text-destructive">
{errors.name}
</p>
)}
Expand All @@ -267,11 +268,11 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
className="inline-flex items-center gap-0.5 text-sm font-medium text-neutral-900 dark:text-neutral-100"
>
{intl.formatMessage({ id: "mcpServer.form.urlLabel" })}
<span className="text-red-500">*</span>
<span className="text-destructive">*</span>
<span className="sr-only">
{intl.formatMessage({ id: "mcpServer.form.required" })}
</span>
<CircleAlert className="h-4 w-4 text-neutral-400 dark:text-neutral-500" />
<STATUS_ICON.info className="h-4 w-4 text-neutral-400 dark:text-neutral-500" />
</label>
<Input
id="server-url"
Expand All @@ -283,7 +284,7 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
aria-describedby={errors.url ? "url-error" : undefined}
/>
{errors.url && (
<p id="url-error" className="text-sm text-red-500">
<p id="url-error" className="text-sm text-destructive">
{errors.url}
</p>
)}
Expand All @@ -303,7 +304,7 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
aria-describedby={errors.description ? "description-error" : undefined}
/>
{errors.description && (
<p id="description-error" className="text-sm text-red-500">
<p id="description-error" className="text-sm text-destructive">
{errors.description}
</p>
)}
Expand Down Expand Up @@ -380,8 +381,8 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ
)}

{errors.submit && (
<div className="rounded-md border border-red-200 bg-red-50 p-3 dark:border-red-900/50 dark:bg-red-950/50">
<p className="text-sm text-red-600 dark:text-red-400">{errors.submit}</p>
<div className="rounded-md border border-destructive/30 bg-destructive/10 p-3">
<p className="text-sm text-destructive">{errors.submit}</p>
</div>
)}

Expand Down
8 changes: 4 additions & 4 deletions src/components/mcp-servers/QueryParameterAuth.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AlertTriangle } from "lucide-react";
import { useIntl } from "react-intl";
import type { ReactNode } from "react";
import { Input } from "@/components/ui/input";
import { STATUS_ICON } from "@/lib/status";

interface QueryParameterAuthProps {
parameterName: string;
Expand All @@ -22,7 +22,7 @@ export function QueryParameterAuth({
<div className="space-y-4">
{/* Security Warning */}
<div className="flex items-center gap-3 rounded-md bg-neutral-50 px-3 py-5 dark:bg-neutral-800">
<AlertTriangle className="h-5 w-5 shrink-0 text-yellow-600 dark:text-yellow-500" />
<STATUS_ICON.warning className="h-5 w-5 shrink-0 text-warning" />
<p className="text-sm text-neutral-700 dark:text-neutral-300">
{intl.formatMessage(
{ id: "mcpServer.auth.query.warning" },
Expand All @@ -40,7 +40,7 @@ export function QueryParameterAuth({
className="inline-flex items-center gap-0.5 text-sm font-medium text-neutral-900 dark:text-neutral-100"
>
{intl.formatMessage({ id: "mcpServer.auth.query.nameLabel" })}
<span className="text-red-500">*</span>
<span className="text-destructive">*</span>
<span className="sr-only">{intl.formatMessage({ id: "mcpServer.form.required" })}</span>
</label>
<Input
Expand All @@ -60,7 +60,7 @@ export function QueryParameterAuth({
className="inline-flex items-center gap-0.5 text-sm font-medium text-neutral-900 dark:text-neutral-100"
>
{intl.formatMessage({ id: "mcpServer.auth.query.apiKeyLabel" })}
<span className="text-red-500">*</span>
<span className="text-destructive">*</span>
<span className="sr-only">{intl.formatMessage({ id: "mcpServer.form.required" })}</span>
</label>
<Input
Expand Down
5 changes: 3 additions & 2 deletions src/components/prompts/PromptForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useRef } from "react";
import { useIntl } from "react-intl";
import { CircleAlert, Info, MessageSquareCode } from "lucide-react";
import { Info, MessageSquareCode } from "lucide-react";
import { STATUS_ICON } from "@/lib/status";
import { BackButton } from "@/components/ui/back-button";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
Expand Down Expand Up @@ -116,7 +117,7 @@ export function PromptForm({ isOpen, onToggle, onSuccess, prompt }: PromptFormPr
role="alert"
aria-live="assertive"
>
<CircleAlert className="mt-0.5 size-4 shrink-0" aria-hidden="true" />
<STATUS_ICON.error className="mt-0.5 size-4 shrink-0" aria-hidden="true" />
<p>{form.errors.submit}</p>
</div>
)}
Expand Down
6 changes: 3 additions & 3 deletions src/components/prompts/PromptPreviewResult.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useIntl } from "react-intl";
import { AlertCircle, CheckCircle2 } from "lucide-react";

import { CodeBlock } from "@/components/ui/code-block";
import { cn } from "@/lib/utils";
import { STATUS_ICON } from "@/lib/status";
import type { PromptPreviewState } from "@/hooks/usePromptPreview";

export interface PromptPreviewResultProps {
Expand Down Expand Up @@ -39,9 +39,9 @@ export function PromptPreviewResult({ preview }: PromptPreviewResultProps) {
className="flex flex-wrap items-center gap-x-2 gap-y-1 text-[13px]"
>
{succeeded ? (
<CheckCircle2 className="size-4 text-emerald-500" />
<STATUS_ICON.success className="size-4 text-success" />
) : (
<AlertCircle className="size-4 text-destructive" />
<STATUS_ICON.error className="size-4 text-destructive" />
)}
<span className={cn("font-medium", succeeded ? "text-foreground" : "text-destructive")}>
{statusLabel}
Expand Down
5 changes: 3 additions & 2 deletions src/components/server-catalog/CatalogResults.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useEffect, useId, useRef, useState } from "react";
import type { ReactNode } from "react";
import { CircleCheck, EllipsisVertical, FileText, Plus } from "lucide-react";
import { EllipsisVertical, FileText, Plus } from "lucide-react";
import { useIntl } from "react-intl";
import { STATUS_ICON } from "@/lib/status";

import { EmptyStatePlaceholder } from "@/components/dashboard/EmptyStatePlaceholder";
import { ServerIcon } from "@/components/servers/ServerIcon";
Expand Down Expand Up @@ -118,7 +119,7 @@ function CatalogCard({
{server.is_registered ? (
<>
<span className="inline-flex items-center gap-1.5 text-sm font-medium text-foreground">
<CircleCheck className="size-4 text-green-500" aria-hidden="true" />
<STATUS_ICON.success className="size-4 text-success" aria-hidden="true" />
{intl.formatMessage({ id: "mcpServer.catalog.connected" })}
</span>
<DropdownMenu>
Expand Down
9 changes: 5 additions & 4 deletions src/components/servers/ServerStatusBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { memo } from "react";
import { CheckCircle2, XCircle, AlertCircle, FileText } from "lucide-react";
import { FileText } from "lucide-react";
import { Badge } from "../ui/badge";
import { STATUS_ICON } from "@/lib/status";
import type { MCPServer, ServerStatus } from "../../types/server";

// Warning threshold: 5 minutes in milliseconds
Expand Down Expand Up @@ -41,17 +42,17 @@ const STATUS_CONFIG: Record<ServerStatus, StatusConfig> = {
},
active: {
label: "Active",
icon: CheckCircle2,
icon: STATUS_ICON.success,
variant: BadgeVariant.Success,
},
offline: {
label: "Offline",
icon: XCircle,
icon: STATUS_ICON.error,
variant: BadgeVariant.Destructive,
},
warning: {
label: "Warning",
icon: AlertCircle,
icon: STATUS_ICON.warning,
variant: BadgeVariant.Warning,
},
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/servers/ServersTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ function getStatusConfig(status: ServerStatus) {
return {
labelId: "mcpServer.status.active",
Icon: Activity,
className: "text-emerald-600 dark:text-emerald-400",
className: "text-success",
};
case "warning":
return {
labelId: "mcpServer.status.warning",
Icon: TriangleAlert,
className: "text-amber-600 dark:text-amber-400",
className: "text-warning",
};
case "offline":
return {
Expand Down
Loading
Loading