Create ChatSearchInput component
This commit is contained in:
parent
46d309ae45
commit
fa919c217b
2 changed files with 53 additions and 22 deletions
|
@ -1,14 +1,14 @@
|
||||||
import sumBy from 'lodash/sumBy';
|
import sumBy from 'lodash/sumBy';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
|
||||||
|
|
||||||
import { Icon, Input, Stack } from 'soapbox/components/ui';
|
import { Stack } from 'soapbox/components/ui';
|
||||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||||
import { useDebounce } from 'soapbox/hooks';
|
import { useDebounce } from 'soapbox/hooks';
|
||||||
import { IChat, useChats } from 'soapbox/queries/chats';
|
import { IChat, useChats } from 'soapbox/queries/chats';
|
||||||
|
|
||||||
import ChatList from '../chat-list';
|
import ChatList from '../chat-list';
|
||||||
import ChatPaneHeader from '../chat-pane-header';
|
import ChatPaneHeader from '../chat-pane-header';
|
||||||
|
import ChatSearchInput from '../chat-search-input';
|
||||||
import ChatSearch from '../chat-search/chat-search';
|
import ChatSearch from '../chat-search/chat-search';
|
||||||
import EmptyResultsBlankslate from '../chat-search/empty-results-blankslate';
|
import EmptyResultsBlankslate from '../chat-search/empty-results-blankslate';
|
||||||
import ChatWindow from '../chat-window';
|
import ChatWindow from '../chat-window';
|
||||||
|
@ -16,12 +16,7 @@ import { Pane } from '../ui';
|
||||||
|
|
||||||
import Blankslate from './blankslate';
|
import Blankslate from './blankslate';
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
searchPlaceholder: { id: 'chats.search_placeholder', defaultMessage: 'Search inbox' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const ChatPane = () => {
|
const ChatPane = () => {
|
||||||
const intl = useIntl();
|
|
||||||
const debounce = useDebounce;
|
const debounce = useDebounce;
|
||||||
|
|
||||||
const [value, setValue] = useState<string>();
|
const [value, setValue] = useState<string>();
|
||||||
|
@ -50,23 +45,10 @@ const ChatPane = () => {
|
||||||
return (
|
return (
|
||||||
<Stack space={4} className='flex-grow h-full'>
|
<Stack space={4} className='flex-grow h-full'>
|
||||||
<div className='px-4'>
|
<div className='px-4'>
|
||||||
<Input
|
<ChatSearchInput
|
||||||
type='text'
|
|
||||||
autoFocus
|
|
||||||
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
|
||||||
className='rounded-full'
|
|
||||||
value={value || ''}
|
value={value || ''}
|
||||||
onChange={(event) => setValue(event.target.value)}
|
onChange={(event) => setValue(event.target.value)}
|
||||||
isSearch
|
onClear={clearValue}
|
||||||
append={
|
|
||||||
<button onClick={clearValue}>
|
|
||||||
<Icon
|
|
||||||
src={hasSearchValue ? require('@tabler/icons/x.svg') : require('@tabler/icons/search.svg')}
|
|
||||||
className='h-4 w-4 text-gray-700 dark:text-gray-600'
|
|
||||||
aria-hidden='true'
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
49
app/soapbox/features/chats/components/chat-search-input.tsx
Normal file
49
app/soapbox/features/chats/components/chat-search-input.tsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { Icon, Input } from 'soapbox/components/ui';
|
||||||
|
import { useDebounce } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
searchPlaceholder: { id: 'chats.search_placeholder', defaultMessage: 'Search inbox' },
|
||||||
|
});
|
||||||
|
|
||||||
|
interface IChatSearchInput {
|
||||||
|
/** Search term. */
|
||||||
|
value: string,
|
||||||
|
/** Callback when the search value changes. */
|
||||||
|
onChange: React.ChangeEventHandler<HTMLInputElement>,
|
||||||
|
/** Callback when the input is cleared. */
|
||||||
|
onClear: React.MouseEventHandler<HTMLButtonElement>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search input for filtering chats. */
|
||||||
|
const ChatSearchInput: React.FC<IChatSearchInput> = ({ value, onChange, onClear }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const debouncedValue = useDebounce(value, 300);
|
||||||
|
const hasSearchValue = Number(debouncedValue?.length) > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
type='text'
|
||||||
|
autoFocus
|
||||||
|
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
||||||
|
className='rounded-full'
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
isSearch
|
||||||
|
append={
|
||||||
|
<button onClick={onClear}>
|
||||||
|
<Icon
|
||||||
|
src={hasSearchValue ? require('@tabler/icons/x.svg') : require('@tabler/icons/search.svg')}
|
||||||
|
className='h-4 w-4 text-gray-700 dark:text-gray-600'
|
||||||
|
aria-hidden='true'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ChatSearchInput;
|
Loading…
Reference in a new issue