diff --git a/client/src/components/Agents/SearchBar.tsx b/client/src/components/Agents/SearchBar.tsx index 652fae974d..e67745293d 100644 --- a/client/src/components/Agents/SearchBar.tsx +++ b/client/src/components/Agents/SearchBar.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { Search, X } from 'lucide-react'; -import { Input } from '@librechat/client'; +import { Button, Input } from '@librechat/client'; import { useDebounce, useLocalize } from '~/hooks'; /** @@ -89,7 +89,9 @@ const SearchBar: React.FC = ({ value, onSearch, className = '' } {/* Show clear button only when search has value - Google style */} {searchTerm && ( - + )} ); diff --git a/client/src/components/Auth/LoginForm.tsx b/client/src/components/Auth/LoginForm.tsx index f4ebad56e2..ace05eff20 100644 --- a/client/src/components/Auth/LoginForm.tsx +++ b/client/src/components/Auth/LoginForm.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect, useContext } from 'react'; import { useForm } from 'react-hook-form'; import { Turnstile } from '@marsidev/react-turnstile'; -import { ThemeContext, SecretInput, Spinner, Button, isDark } from '@librechat/client'; +import { ThemeContext, SecretInput, Spinner, Button, Input, isDark } from '@librechat/client'; import type { TLoginUser, TStartupConfig } from 'librechat-data-provider'; import type { TAuthContext } from '~/common'; import { useResendVerificationEmail, useGetStartupConfig } from '~/data-provider'; @@ -96,7 +96,7 @@ const LoginForm: React.FC = ({ onSubmit, startupConfig, error, >
- { /> ) : ( <> - = ({ children }) => { @@ -84,7 +84,7 @@ function RequestPasswordReset() { >
- {
)}
- +
{!useBackup ? ( - + ) : ( - + )}
diff --git a/client/src/components/Auth/VerifyEmail.tsx b/client/src/components/Auth/VerifyEmail.tsx index 1d28384857..bba11455a7 100644 --- a/client/src/components/Auth/VerifyEmail.tsx +++ b/client/src/components/Auth/VerifyEmail.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useMemo, useCallback } from 'react'; -import { Spinner, ThemeSelector } from '@librechat/client'; import { useSearchParams, useNavigate } from 'react-router-dom'; +import { Button, Spinner, ThemeSelector } from '@librechat/client'; import { useVerifyEmailMutation, useResendVerificationEmail } from '~/data-provider'; import { useLocalize } from '~/hooks'; @@ -87,13 +87,15 @@ function RequestPasswordReset() { {showResendLink && countdown === 0 && (

{localize('com_auth_email_verification_resend_prompt')} - +

)}
diff --git a/client/src/components/Chat/Input/Files/FileUpload.tsx b/client/src/components/Chat/Input/Files/FileUpload.tsx index 9937319700..ce89ae0828 100644 --- a/client/src/components/Chat/Input/Files/FileUpload.tsx +++ b/client/src/components/Chat/Input/Files/FileUpload.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; import { FileUp } from 'lucide-react'; -import { cn } from '~/utils/'; +import { Button } from '@librechat/client'; import { useLocalize } from '~/hooks'; +import { cn } from '~/utils/'; type FileUploadProps = { onFileSelected: (jsonData: Record) => void; @@ -71,8 +72,10 @@ const FileUpload: React.FC = ({ return ( <> - + { + const localize = useLocalize(); const [isModalOpen, setIsModalOpen] = useState(false); const [isHovered, setIsHovered] = useState(false); const triggerRef = useRef(null); @@ -179,8 +181,9 @@ const ImagePreview = ({ ref={closeButtonRef} onClick={() => handleOpenChange(false)} variant="ghost" - className="absolute right-4 top-4 z-20 h-10 w-10 p-0 text-white hover:bg-white/10" - aria-label="Close" + size="icon" + className="absolute right-4 top-4 z-20 text-white hover:bg-white/10" + aria-label={localize('com_ui_close')} >
} - selection={{ - selectHandler: submitPreset, - selectClasses: 'bg-surface-submit hover:bg-surface-submit-hover text-white', - selectText: localize('com_ui_save'), - }} + buttons={ + + } /> ); diff --git a/client/src/components/Input/ModelSelect/MultiSelectPop.tsx b/client/src/components/Input/ModelSelect/MultiSelectPop.tsx index f72c84a45b..b41b4fac63 100644 --- a/client/src/components/Input/ModelSelect/MultiSelectPop.tsx +++ b/client/src/components/Input/ModelSelect/MultiSelectPop.tsx @@ -3,6 +3,7 @@ import { useMultiSearch } from '@librechat/client'; import { Root, Trigger, Content, Portal } from '@radix-ui/react-popover'; import type { TPlugin } from 'librechat-data-provider'; import MenuItem from '~/components/Chat/Menus/UI/MenuItem'; +import { useLocalize } from '~/hooks'; import { cn } from '~/utils/'; type SelectDropDownProps = { @@ -32,6 +33,7 @@ function MultiSelectPop({ optionValueKey = 'value', searchPlaceholder, }: SelectDropDownProps) { + const localize = useLocalize(); const title = _title; const excludeIds = ['select-plugin', 'plugins-label', 'selected-plugins']; @@ -71,7 +73,7 @@ function MultiSelectPop({ )} */}
- {value.length === 0 && 'None selected'} + {value.length === 0 && localize('com_ui_none_selected')} {value.map((v, i) => (
{v.icon ? ( diff --git a/client/src/components/Input/ModelSelect/SelectDropDownPop.tsx b/client/src/components/Input/ModelSelect/SelectDropDownPop.tsx index 1009dde2cf..a926e5c725 100644 --- a/client/src/components/Input/ModelSelect/SelectDropDownPop.tsx +++ b/client/src/components/Input/ModelSelect/SelectDropDownPop.tsx @@ -72,7 +72,7 @@ function SelectDropDownPop({ 'hover:bg-surface-hover radix-state-open:bg-surface-hover', 'min-w-[200px] max-w-[215px] sm:min-w-full sm:max-w-full', )} - aria-label={`Select ${title}`} + aria-label={localize('com_ui_select_var', { 0: title })} aria-haspopup="false" > {' '} diff --git a/client/src/components/Messages/Content/Mermaid/Mermaid.tsx b/client/src/components/Messages/Content/Mermaid/Mermaid.tsx index 92cbe59e6d..e8e561633c 100644 --- a/client/src/components/Messages/Content/Mermaid/Mermaid.tsx +++ b/client/src/components/Messages/Content/Mermaid/Mermaid.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState, useRef, useCallback, memo } from 'react'; import { RefreshCw } from 'lucide-react'; -import { Spinner } from '@librechat/client'; +import { Button, Spinner } from '@librechat/client'; import useSvgProcessing from './useSvgProcessing'; import useMermaidZoom from './useMermaidZoom'; import MermaidDialog from './MermaidDialog'; @@ -178,14 +178,15 @@ const Mermaid: React.FC = memo(({ children, id, theme }) => { {localize('com_ui_mermaid_failed')} - +
{error.message}
{showCode && ( diff --git a/client/src/components/Nav/Settings/Dialog.tsx b/client/src/components/Nav/Settings/Dialog.tsx index cccf355847..358314f3e9 100644 --- a/client/src/components/Nav/Settings/Dialog.tsx +++ b/client/src/components/Nav/Settings/Dialog.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import * as Tabs from '@radix-ui/react-tabs'; import { X, ChevronLeft } from 'lucide-react'; -import { useMediaQuery } from '@librechat/client'; +import { Button, useMediaQuery } from '@librechat/client'; import { SettingsTabValues } from 'librechat-data-provider'; import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react'; import type { TDialogProps } from '~/common'; @@ -88,14 +88,15 @@ export default function SettingsDialog({ open, onOpenChange }: TDialogProps) { {localize('com_nav_settings')} )} - + { )}
- +
)} diff --git a/client/src/components/Nav/SettingsTabs/Account/TwoFactorPhases/DisablePhase.tsx b/client/src/components/Nav/SettingsTabs/Account/TwoFactorPhases/DisablePhase.tsx index d3fea1cd89..2056ba5860 100644 --- a/client/src/components/Nav/SettingsTabs/Account/TwoFactorPhases/DisablePhase.tsx +++ b/client/src/components/Nav/SettingsTabs/Account/TwoFactorPhases/DisablePhase.tsx @@ -77,12 +77,14 @@ export const DisablePhase: React.FC = ({ onDisable, isDisabli {isDisabling && } {isDisabling ? localize('com_ui_disabling') : localize('com_ui_2fa_disable')} - + ); }; diff --git a/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx b/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx index 7e3e0b6136..6a9ed82bd9 100644 --- a/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx +++ b/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx @@ -258,7 +258,6 @@ export default function ArchivedChatsTable({ isArchived: false, }) } - title={localize('com_ui_unarchive_conversation')} aria-label={localize('com_ui_unarchive_conversation')} disabled={isUnarchiving} > @@ -276,7 +275,6 @@ export default function ArchivedChatsTable({ setDeleteConversation(row.original); setIsDeleteOpen(true); }} - title={localize('com_ui_delete_conversation_tooltip')} aria-label={localize('com_ui_delete_conversation_tooltip')} > @@ -333,7 +331,11 @@ export default function ArchivedChatsTable({
- + {localize('com_ui_close_window')} +
); diff --git a/client/src/components/Prompts/fields/PromptName.tsx b/client/src/components/Prompts/fields/PromptName.tsx index 8e22bc3126..703993a760 100644 --- a/client/src/components/Prompts/fields/PromptName.tsx +++ b/client/src/components/Prompts/fields/PromptName.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState, useRef, useCallback } from 'react'; import { Pencil, Check, Loader2, X } from 'lucide-react'; +import { Input, TooltipAnchor } from '@librechat/client'; import { useLocalize } from '~/hooks'; type Props = { @@ -98,10 +99,31 @@ const PromptName: React.FC = ({ name, isLoading = false, isError = false, }; }, []); + const displayButton = ( + + ); + + const readView = newName ? ( + + ) : ( + displayButton + ); + return (
{isEditing ? ( - = ({ name, isLoading = false, isError = false, aria-label={localize('com_ui_name')} /> ) : ( - + readView )}
{saveStatus === 'saving' && ( diff --git a/client/src/components/Prompts/forms/CreatePromptForm.tsx b/client/src/components/Prompts/forms/CreatePromptForm.tsx index 8231aadf57..ef7614c84f 100644 --- a/client/src/components/Prompts/forms/CreatePromptForm.tsx +++ b/client/src/components/Prompts/forms/CreatePromptForm.tsx @@ -214,6 +214,7 @@ const CreatePromptForm = ({ methods.setValue('command', value)} tabIndex={0} />
+
- +
{preset && ( diff --git a/client/src/components/Skills/dialogs/CreateSkillDialog.tsx b/client/src/components/Skills/dialogs/CreateSkillDialog.tsx index aa46d2cf24..4898c01fb3 100644 --- a/client/src/components/Skills/dialogs/CreateSkillDialog.tsx +++ b/client/src/components/Skills/dialogs/CreateSkillDialog.tsx @@ -1,17 +1,19 @@ import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import { + SKILL_NAME_PATTERN, + SKILL_NAME_MAX_LENGTH, + SKILL_DESCRIPTION_MAX_LENGTH, +} from 'librechat-data-provider'; +import { + Input, + Label, Button, OGDialog, OGDialogContent, TextareaAutosize, useToastContext, } from '@librechat/client'; -import { - SKILL_NAME_PATTERN, - SKILL_NAME_MAX_LENGTH, - SKILL_DESCRIPTION_MAX_LENGTH, -} from 'librechat-data-provider'; import type { TSkill } from 'librechat-data-provider'; import type { FormEvent } from 'react'; import { useCreateSkillMutation } from '~/data-provider'; @@ -124,10 +126,10 @@ export default function CreateSkillDialog({ {/* Skill name */}
-
{!isInstalled ? ( -
- + ) : ( -
- + )} diff --git a/client/src/components/Web/SourceHovercard.tsx b/client/src/components/Web/SourceHovercard.tsx index 126140bfdf..30ba20f272 100644 --- a/client/src/components/Web/SourceHovercard.tsx +++ b/client/src/components/Web/SourceHovercard.tsx @@ -1,7 +1,8 @@ import React, { ReactNode } from 'react'; import * as Ariakit from '@ariakit/react'; -import { ChevronDown, FileText } from 'lucide-react'; +import { Button } from '@librechat/client'; import { VisuallyHidden } from '@ariakit/react'; +import { ChevronDown, FileText } from 'lucide-react'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; @@ -70,12 +71,13 @@ function FileHovercardContent({ <>
{(fileRelevance != null || (filePages && filePages.length > 0)) && (
diff --git a/client/src/components/Web/Sources.tsx b/client/src/components/Web/Sources.tsx index 5705d300a6..385c03eb22 100644 --- a/client/src/components/Web/Sources.tsx +++ b/client/src/components/Web/Sources.tsx @@ -5,6 +5,7 @@ import { VisuallyHidden } from '@ariakit/react'; import { Tools } from 'librechat-data-provider'; import { X, Globe, Newspaper, Image, ChevronDown, File, Download } from 'lucide-react'; import { + Button, OGDialog, AnimatedTabs, OGDialogClose, @@ -752,13 +753,15 @@ export default function Sources(props: SourcesProps) {
{localize('com_sources_error_fallback')}
- +
); diff --git a/client/src/components/Web/SourcesErrorBoundary.tsx b/client/src/components/Web/SourcesErrorBoundary.tsx index d39f8e8bdb..3abb7c8c85 100644 --- a/client/src/components/Web/SourcesErrorBoundary.tsx +++ b/client/src/components/Web/SourcesErrorBoundary.tsx @@ -1,4 +1,6 @@ import React, { Component, ReactNode } from 'react'; +import { Button } from '@librechat/client'; +import { useLocalize } from '~/hooks'; interface Props { children: ReactNode; @@ -11,6 +13,28 @@ interface State { hasError: boolean; } +function DefaultFallback() { + const localize = useLocalize(); + return ( +
+ {/* eslint-disable-next-line i18next/no-literal-string */} +
Sources temporarily unavailable
+ +
+ ); +} + class SourcesErrorBoundary extends Component { state = { hasError: false }; @@ -30,25 +54,7 @@ class SourcesErrorBoundary extends Component { return this.props.fallback; } - // Default simple error UI (using localized strings from Sources.tsx fallback) - /* eslint-disable i18next/no-literal-string */ - return ( -
-
Sources temporarily unavailable
- -
- ); - /* eslint-enable i18next/no-literal-string */ + return ; } return this.props.children; diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index dfdfa5eedb..9a5c753ea4 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -1616,6 +1616,7 @@ "com_ui_reject": "Reject", "com_ui_reject_reason_placeholder": "Optional: reason for rejecting (shared with the agent)", "com_ui_relevance": "Relevance", + "com_ui_reload_page": "Reload the page", "com_ui_remote_access": "Remote Access", "com_ui_remote_agent_role_editor": "Editor", "com_ui_remote_agent_role_editor_desc": "Can view and modify the agent via API",