diff --git a/examples/vite/src/ChatLayout/Panels.tsx b/examples/vite/src/ChatLayout/Panels.tsx index 491d62c3a..ada0ac2b3 100644 --- a/examples/vite/src/ChatLayout/Panels.tsx +++ b/examples/vite/src/ChatLayout/Panels.tsx @@ -7,6 +7,7 @@ import { ChannelAvatar, ChannelHeader, ChannelList, + ChannelSearchProps, ChatView, MessageInput, MessageList, @@ -42,6 +43,10 @@ const ChannelThreadPanel = () => { ); }; +const CustomChannelSearch = (props: ChannelSearchProps) => ( + +); + export const ChannelsPanels = ({ filters, initialChannelId, @@ -65,7 +70,7 @@ export const ChannelsPanels = ({ ref={channelsLayoutRef} > ({ isActive: nextValue.isActive }); export type SearchProps = { + /** The type of channel to create on user result select, defaults to `messaging` */ directMessagingChannelType?: string; /** Sets the input element into disabled state */ disabled?: boolean; - /** Clear search state / results on every click outside the search input, defaults to false */ + /** Clear the search state/results on every click outside the search input, defaults to `false` */ exitSearchOnInputBlur?: boolean; /** Custom placeholder text to be displayed in the search input */ placeholder?: string; @@ -29,11 +30,13 @@ export type SearchProps = { export const Search = ({ directMessagingChannelType = 'messaging', disabled, - exitSearchOnInputBlur, + exitSearchOnInputBlur = false, placeholder, }: SearchProps) => { const { SearchBar = DefaultSearchBar, SearchResults = DefaultSearchResults } = useComponentContext(); + const containerRef = useRef(null); + const filterButtonsContainerRef = useRef(null); const { searchController } = useChatContext(); @@ -45,9 +48,11 @@ export const Search = ({ return ( diff --git a/src/experimental/Search/SearchBar/SearchBar.tsx b/src/experimental/Search/SearchBar/SearchBar.tsx index 6dd140fd2..3b66b75f9 100644 --- a/src/experimental/Search/SearchBar/SearchBar.tsx +++ b/src/experimental/Search/SearchBar/SearchBar.tsx @@ -16,9 +16,15 @@ const searchControllerStateSelector = (nextValue: SearchControllerState) => ({ export const SearchBar = () => { const { t } = useTranslationContext(); - const { disabled, exitSearchOnInputBlur, placeholder, searchController } = - useSearchContext(); + const { + disabled, + exitSearchOnInputBlur, + filterButtonsContainerRef, + placeholder, + searchController, + } = useSearchContext(); const queriesInProgress = useSearchQueriesInProgress(searchController); + const clearButtonRef = React.useRef(null); const [input, setInput] = useState(null); const { isActive, searchQuery } = useStateStore( @@ -53,8 +59,18 @@ export const SearchBar = () => { className='str-chat__search-bar__input' data-testid='search-input' disabled={disabled} - onBlur={() => { - if (exitSearchOnInputBlur) searchController.exit(); + onBlur={({ currentTarget, relatedTarget }) => { + if ( + exitSearchOnInputBlur && + // input is empty + !currentTarget.value && + // clicking on filter buttons or clear button shouldn't trigger exit search on blur + !filterButtonsContainerRef.current?.contains(relatedTarget) && + // clicking clear button shouldn't trigger exit search on blur + (!clearButtonRef.current || relatedTarget !== clearButtonRef.current) + ) { + searchController.exit(); + } }} onChange={(event: React.ChangeEvent) => { if (event.target.value) { @@ -80,6 +96,7 @@ export const SearchBar = () => { searchController.clear(); input?.focus(); }} + ref={clearButtonRef} size='xs' variant='secondary' > @@ -87,7 +104,6 @@ export const SearchBar = () => { )} - {/* TODO: return button once designs are in */} {isActive && (