mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-08 02:24:24 +01:00
* chore: add i18n localization comment for AlwaysMakeProd component * feat: enhance accessibility by adding aria-label and aria-labelledby to Switch component * feat: add aria-labels for accessibility in Agent and Assistant avatar buttons * fix: add switch aria-labels for accessibility in various components * feat: add aria-labels and localization keys for accessibility in DataTable, DataTableColumnHeader, and OGDialogTemplate components * chore: refactor out nested ternary * feat: add aria-label to DataTable filter button for My Files modal * feat: add aria-labels for Buttons and localization strings * feat: add aria-labels to Checkboxes in Agent Builder * feat: enhance accessibility by adding aria-label and aria-labelledby to Checkbox component * feat: add aria-label to FileSearchCheckbox in Agent Builder * feat: add aria-label to Prompts text input area * feat: enhance accessibility by adding aria-label and aria-labelledby to TextAreaAutosize component * feat: remove improper role: "list" prop from List in Conversations.tsx to enhance accessibility and stop aria rules conflicting within react-virtualized component * feat: enhance accessibility by allowing tab navigation and adding ring highlights for conversation title editing accept/reject buttons * feat: add aria-label to Copy Link button in the conversation share modal * feat: add title to QR code svg in conversation share modal to describe the image content * feat: enhance accessibility by making Agent Avatar upload keyboard navigable and round out highlight border on focus * feat: enhance accessibility by adding aria attributes around alerting users with screen readers to invalid email address inputs in the Agent Builder * feat: add aria-labels to buttons in Advanced panel of Agent Builder * feat: enhance accessibility by making FileUpload and Clear All buttons in PresetItems keyboard navigable * feat: enchance accessiblity by indexing view and delete button aria-labels in shared links management modal to their specific chat titles * feat: add border highlighting on focus for AnimatedSearchInput * feat: add category description to aria-labels for prompts in ListCard * feat: add proper scoping to rows and columns in table headers * feat: add localized aria-labelling to EditTextPart's TextAreaAutosize component and base dynamic paramters panel components and their supporting translation keys * feat: add localized aria-labels and aria-labelledBy to Checkbox components without them * feat: add localized aria-labeledBy for endpoint settings Sliders * feat: add localized aria-labels for TextareaAutosize components * chore: remove unused i18n string * feat: add localized aria-label for BookmarkForm Checkbox * fix: add stopPropagation onKeyDown for Preview and Edit menu items in prompts that was causing the prompts to inadvertently be sent when triggered with keyboard navigation when Auto-send Prompts was toggled on * fix: switch TableCell to TableHead for title cells according to harvard issue #789 * fix: add more descriptive localization key for file filter button in DataTable * chore: remove self-explanatory code comment from RenameForm * fix: remove stray bg-yellow highlight that was left in during debugging * fix: add aria-label to model configurator panel back button * fix: undo incorrect hoist of tool name split for aria-label and span in MCPInput --------- Co-authored-by: Danny Avila <danny@librechat.ai>
79 lines
3.2 KiB
TypeScript
79 lines
3.2 KiB
TypeScript
import React from 'react';
|
|
import { Search } from 'lucide-react';
|
|
import { cn } from '~/utils';
|
|
|
|
const AnimatedSearchInput = ({
|
|
value,
|
|
onChange,
|
|
isSearching: searching,
|
|
placeholder,
|
|
}: {
|
|
value?: string;
|
|
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
isSearching?: boolean;
|
|
placeholder: string;
|
|
}) => {
|
|
const isSearching = searching === true;
|
|
const hasValue = value != null && value.length > 0;
|
|
|
|
return (
|
|
<div className="relative w-full">
|
|
<div className="relative rounded-lg transition-all duration-500 ease-in-out">
|
|
<div className="relative">
|
|
{/* Icon on the left */}
|
|
<div className="absolute left-3 top-1/2 z-50 -translate-y-1/2">
|
|
<Search
|
|
className={cn(
|
|
`h-4 w-4 transition-all duration-500 ease-in-out`,
|
|
isSearching && hasValue ? 'text-blue-400' : 'text-gray-400',
|
|
)}
|
|
/>
|
|
</div>
|
|
|
|
{/* Input field */}
|
|
<input
|
|
type="text"
|
|
value={value}
|
|
onChange={onChange}
|
|
placeholder={placeholder}
|
|
className={`peer relative z-20 w-full rounded-lg bg-surface-secondary px-10 py-2 outline-none backdrop-blur-sm transition-all duration-500 ease-in-out placeholder:text-gray-400 focus:ring-ring`}
|
|
/>
|
|
|
|
{/* Gradient overlay */}
|
|
<div
|
|
className={`pointer-events-none absolute inset-0 z-20 rounded-lg bg-gradient-to-r from-blue-500/20 via-purple-500/20 to-blue-500/20 transition-all duration-500 ease-in-out ${isSearching && hasValue ? 'opacity-100 blur-sm' : 'opacity-0 blur-none'} `}
|
|
/>
|
|
|
|
{/* Animated loading indicator */}
|
|
<div
|
|
className={`absolute right-3 top-1/2 z-20 -translate-y-1/2 transition-all duration-500 ease-in-out ${isSearching && hasValue ? 'scale-100 opacity-100' : 'scale-0 opacity-0'} `}
|
|
>
|
|
<div className="relative h-2 w-2">
|
|
<div className="absolute inset-0 animate-ping rounded-full bg-blue-500/60" />
|
|
<div className="absolute inset-0 rounded-full bg-blue-500" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Outer glow effect */}
|
|
<div
|
|
className={`absolute -inset-8 -z-10 transition-all duration-700 ease-in-out ${isSearching && hasValue ? 'scale-105 opacity-100' : 'scale-100 opacity-0'} `}
|
|
>
|
|
<div className="absolute inset-0">
|
|
<div
|
|
className={`bg-gradient-radial absolute inset-0 from-blue-500/10 to-transparent transition-opacity duration-700 ease-in-out ${isSearching && hasValue ? 'animate-pulse-slow opacity-100' : 'opacity-0'} `}
|
|
/>
|
|
<div
|
|
className={`absolute inset-0 bg-gradient-to-r from-purple-500/5 via-blue-500/5 to-purple-500/5 blur-xl transition-all duration-700 ease-in-out ${isSearching && hasValue ? 'animate-gradient-x opacity-100' : 'opacity-0'} `}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={`absolute inset-0 -z-20 scale-100 bg-gradient-to-r from-blue-500/10 via-purple-500/10 to-blue-500/10 opacity-0 blur-xl transition-all duration-500 ease-in-out peer-focus:scale-105 peer-focus:opacity-100`}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AnimatedSearchInput;
|