mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +01:00
* BIG UI UPDATE * fix: search bar, dialog template, new chat icon, convo icon and delete/rename button * moved some color config and a lot of files * small text fixes and tailwind config refactor * Update localization and UI styles * Update styles and add user-select:none to Tooltip component * Update mobile.css styles for navigation mask and background color * Update component imports and styles * Update DeleteButton imports and references * Update UI components * Update tooltip delay duration * Fix styling and update text in various components * fixed assistant style * minor style fixes * revert: removed CreationHeader & CreationPanel * style: match new styling for SidePanel * style: match bg-gray-800 to ChatGPT (#212121) * style: remove slate for gray where applicable to match new light theme --------- Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
import { forwardRef, useState, useCallback, useMemo, Ref } from 'react';
|
|
import { Search, X } from 'lucide-react';
|
|
import { useSetRecoilState } from 'recoil';
|
|
import debounce from 'lodash/debounce';
|
|
import { useLocalize } from '~/hooks';
|
|
import { cn } from '~/utils';
|
|
import store from '~/store';
|
|
|
|
type SearchBarProps = {
|
|
clearSearch: () => void;
|
|
};
|
|
|
|
const SearchBar = forwardRef((props: SearchBarProps, ref: Ref<HTMLDivElement>) => {
|
|
const { clearSearch } = props;
|
|
const setSearchQuery = useSetRecoilState(store.searchQuery);
|
|
const [showClearIcon, setShowClearIcon] = useState(false);
|
|
const [text, setText] = useState('');
|
|
const localize = useLocalize();
|
|
|
|
const clearText = useCallback(() => {
|
|
setShowClearIcon(false);
|
|
setSearchQuery('');
|
|
clearSearch();
|
|
setText('');
|
|
}, [setSearchQuery, clearSearch]);
|
|
|
|
const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
const { value } = e.target as HTMLInputElement;
|
|
if (e.key === 'Backspace' && value === '') {
|
|
clearText();
|
|
}
|
|
};
|
|
|
|
const sendRequest = useCallback((value: string) => setSearchQuery(value), [setSearchQuery]);
|
|
const debouncedSendRequest = useMemo(() => debounce(sendRequest, 350), [sendRequest]);
|
|
|
|
const onChange = (e: React.FormEvent<HTMLInputElement>) => {
|
|
const { value } = e.target as HTMLInputElement;
|
|
setShowClearIcon(value.length > 0);
|
|
setText(value);
|
|
debouncedSendRequest(value);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className="relative mt-1 flex flex h-10 cursor-pointer items-center gap-3 rounded-lg border-white bg-gray-50 px-2 px-3 py-2 text-black transition-colors duration-200 hover:bg-gray-200 focus:bg-gray-800 dark:bg-gray-900 dark:text-white dark:hover:bg-gray-800"
|
|
>
|
|
{<Search className="absolute left-3 h-4 w-4" />}
|
|
<input
|
|
type="text"
|
|
className="m-0 mr-0 w-full border-none bg-transparent p-0 pl-7 text-sm leading-tight outline-none"
|
|
value={text}
|
|
onChange={onChange}
|
|
onKeyDown={(e) => {
|
|
e.code === 'Space' ? e.stopPropagation() : null;
|
|
}}
|
|
placeholder={localize('com_nav_search_placeholder')}
|
|
onKeyUp={handleKeyUp}
|
|
/>
|
|
<X
|
|
className={cn(
|
|
'absolute right-[7px] h-5 w-5 cursor-pointer transition-opacity duration-1000',
|
|
showClearIcon ? 'opacity-100' : 'opacity-0',
|
|
)}
|
|
onClick={clearText}
|
|
/>
|
|
</div>
|
|
);
|
|
});
|
|
|
|
export default SearchBar;
|