refactor: migrate remaining alert banners and error states to tokens

Migrate the last banners to the Alert component: ResetPassword success,
MessageContent connection error, and MemoryInfo storage-full errors. Tokenize
the Agents ErrorDisplay error state in place (icon badge, headings, message,
retry button) since it's a full error state, not a compact callout. Also
tokenize ResetPassword field-validation errors to text-text-destructive
(fixes the low-contrast dark:text-red-900).
This commit is contained in:
Marco Beretta 2026-06-19 23:39:18 +02:00
parent 95f7717329
commit 115a968f13
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
4 changed files with 20 additions and 26 deletions

View file

@ -181,11 +181,11 @@ export const ErrorDisplay: React.FC<ErrorDisplayProps> = ({ error, onRetry, cont
<div
className={cn(
'flex h-12 w-12 items-center justify-center rounded-full',
'bg-red-100 dark:bg-red-900/20',
'bg-status-error-subtle',
)}
>
<svg
className="h-6 w-6 text-red-600 dark:text-red-400"
className="h-6 w-6 text-status-error"
fill="none"
viewBox="0 0 24 24"
strokeWidth={2}
@ -205,18 +205,18 @@ export const ErrorDisplay: React.FC<ErrorDisplayProps> = ({ error, onRetry, cont
{/* Error content with proper headings and structure */}
<div className="space-y-3">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white" id="error-title">
<h3 className="text-lg font-semibold text-text-primary" id="error-title">
{title}
</h3>
<p
className="text-gray-600 dark:text-gray-400"
className="text-text-secondary"
id="error-message"
aria-describedby="error-title"
>
{message}
</p>
<p
className="text-sm text-gray-500 dark:text-gray-500"
className="text-sm text-text-tertiary"
id="error-suggestion"
role="note"
aria-label={`Suggestion: ${suggestion}`}
@ -233,8 +233,7 @@ export const ErrorDisplay: React.FC<ErrorDisplayProps> = ({ error, onRetry, cont
variant="outline"
size="sm"
className={cn(
'border-red-300 text-red-700 hover:bg-red-50 focus:ring-2 focus:ring-red-500',
'dark:border-red-600 dark:text-red-400 dark:hover:bg-red-900/20 dark:focus:ring-red-400',
'border-status-error text-status-error hover:bg-status-error-subtle',
)}
aria-describedby="error-message error-suggestion"
aria-label={`Retry action. ${message}`}

View file

@ -1,5 +1,5 @@
import { useForm } from 'react-hook-form';
import { Spinner, Button, SecretInput } from '@librechat/client';
import { Spinner, Button, SecretInput, Alert } from '@librechat/client';
import { useOutletContext } from 'react-router-dom';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useResetPasswordMutation } from 'librechat-data-provider/react-query';
@ -41,10 +41,7 @@ function ResetPassword() {
if (resetPassword.isSuccess) {
return (
<>
<div
className="relative mt-6 rounded-xl border border-green-500/20 bg-green-50/50 px-6 py-4 text-green-700 shadow-sm transition-all dark:bg-green-950/30 dark:text-green-100"
role="alert"
>
<Alert variant="success" icon={false} className="mt-6 px-6 py-4 shadow-sm transition-all">
<div className="flex flex-col space-y-4">
<p>{localize('com_auth_login_with_new_password')}</p>
<Button
@ -55,7 +52,7 @@ function ResetPassword() {
{localize('com_auth_continue')}
</Button>
</div>
</div>
</Alert>
</>
);
}
@ -107,7 +104,7 @@ function ResetPassword() {
</div>
{errors.password && (
<span role="alert" className="mt-1 text-sm text-red-500 dark:text-red-900">
<span role="alert" className="mt-1 text-sm text-text-destructive">
{errors.password.message}
</span>
)}
@ -130,17 +127,17 @@ function ResetPassword() {
/>
</div>
{errors.confirm_password && (
<span role="alert" className="mt-1 text-sm text-red-500 dark:text-red-900">
<span role="alert" className="mt-1 text-sm text-text-destructive">
{errors.confirm_password.message}
</span>
)}
{errors.token && (
<span role="alert" className="mt-1 text-sm text-red-500 dark:text-red-900">
<span role="alert" className="mt-1 text-sm text-text-destructive">
{errors.token.message}
</span>
)}
{errors.userId && (
<span role="alert" className="mt-1 text-sm text-red-500 dark:text-red-900">
<span role="alert" className="mt-1 text-sm text-text-destructive">
{errors.userId.message}
</span>
)}

View file

@ -1,5 +1,6 @@
import type { MemoryArtifact } from 'librechat-data-provider';
import { useMemo } from 'react';
import { Alert } from '@librechat/client';
import { useLocalize } from '~/hooks';
export default function MemoryInfo({ memoryArtifacts }: { memoryArtifacts: MemoryArtifact[] }) {
@ -89,17 +90,14 @@ export default function MemoryInfo({ memoryArtifacts }: { memoryArtifacts: Memor
{errorMessages.length > 0 && (
<div>
<h4 className="mb-2 text-sm font-semibold text-red-500">
<h4 className="mb-2 text-sm font-semibold text-text-destructive">
{localize('com_ui_memory_storage_full')}
</h4>
<div className="space-y-2">
{errorMessages.map((errorMessage) => (
<div
key={errorMessage}
className="rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400"
>
<Alert key={errorMessage} variant="error" icon={false} className="rounded-md p-3">
{errorMessage}
</div>
</Alert>
))}
</div>
</div>

View file

@ -1,6 +1,6 @@
import { memo, Suspense, useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { DelayedRender } from '@librechat/client';
import { Alert, DelayedRender } from '@librechat/client';
import type { TMessage } from 'librechat-data-provider';
import type { TMessageContentProps, TDisplayProps } from '~/common';
import Error from '~/components/Messages/Content/Error';
@ -64,9 +64,9 @@ const ConnectionError = ({ message }: { message?: TMessage }) => {
<Suspense fallback={<LoadingFallback />}>
<DelayedRender delay={DELAYED_ERROR_TIMEOUT}>
<Container message={message}>
<div className="mt-2 rounded-xl border border-red-500/20 bg-red-50/50 px-4 py-3 text-sm text-red-700 shadow-sm transition-all dark:bg-red-950/30 dark:text-red-100">
<Alert variant="error" icon={false} className="mt-2 shadow-sm transition-all">
{localize('com_ui_error_connection')}
</div>
</Alert>
</Container>
</DelayedRender>
</Suspense>