pretty UI for zone search suggestions

This commit is contained in:
Emi Matchu 2020-09-01 19:40:53 -07:00
parent 10563629ef
commit 479f43ed22
3 changed files with 52 additions and 9 deletions

View file

@ -4,7 +4,6 @@ import { Box, Flex } from "@chakra-ui/core";
import ItemsPanel from "./ItemsPanel"; import ItemsPanel from "./ItemsPanel";
import SearchToolbar from "./SearchToolbar"; import SearchToolbar from "./SearchToolbar";
import SearchPanel from "./SearchPanel"; import SearchPanel from "./SearchPanel";
import { isNullableType } from "graphql";
const emptyQuery = { value: "", filterToZoneLabel: null }; const emptyQuery = { value: "", filterToZoneLabel: null };
@ -39,7 +38,7 @@ function ItemsAndSearchPanels({ loading, outfitState, dispatchToOutfit }) {
query={searchQuery} query={searchQuery}
searchQueryRef={searchQueryRef} searchQueryRef={searchQueryRef}
firstSearchResultRef={firstSearchResultRef} firstSearchResultRef={firstSearchResultRef}
onChange={setSearchQuery} onChange={onChange}
/> />
</Box> </Box>
{searchQuery.value || searchQuery.filterToZoneLabel ? ( {searchQuery.value || searchQuery.filterToZoneLabel ? (
@ -50,7 +49,7 @@ function ItemsAndSearchPanels({ loading, outfitState, dispatchToOutfit }) {
overflow="auto" overflow="auto"
ref={scrollContainerRef} ref={scrollContainerRef}
> >
<Box px="4" py="5"> <Box px="4" py="2">
<SearchPanel <SearchPanel
query={searchQuery.value} query={searchQuery.value}
outfitState={outfitState} outfitState={outfitState}
@ -68,7 +67,7 @@ function ItemsAndSearchPanels({ loading, outfitState, dispatchToOutfit }) {
overflow="auto" overflow="auto"
key="items-panel" key="items-panel"
> >
<Box px="4" py="5"> <Box px="4" py="2">
<ItemsPanel <ItemsPanel
loading={loading} loading={loading}
outfitState={outfitState} outfitState={outfitState}

View file

@ -3,7 +3,7 @@ import gql from "graphql-tag";
import { Box, Text, VisuallyHidden } from "@chakra-ui/core"; import { Box, Text, VisuallyHidden } from "@chakra-ui/core";
import { useQuery } from "@apollo/client"; import { useQuery } from "@apollo/client";
import { Delay, Heading1, useDebounce } from "../util"; import { Delay, useDebounce } from "../util";
import Item, { ItemListContainer, ItemListSkeleton } from "./Item"; import Item, { ItemListContainer, ItemListSkeleton } from "./Item";
import { itemAppearanceFragment } from "../components/useOutfitAppearance"; import { itemAppearanceFragment } from "../components/useOutfitAppearance";
@ -47,7 +47,6 @@ function SearchPanel({
} }
}} }}
> >
<Heading1 mb="4">Searching for "{query}"</Heading1>
<SearchResults <SearchResults
query={query} query={query}
outfitState={outfitState} outfitState={outfitState}

View file

@ -12,7 +12,7 @@ import {
useColorModeValue, useColorModeValue,
} from "@chakra-ui/core"; } from "@chakra-ui/core";
import { CloseIcon, SearchIcon } from "@chakra-ui/icons"; import { CloseIcon, SearchIcon } from "@chakra-ui/icons";
import { css } from "emotion"; import { css, cx } from "emotion";
import Autosuggest from "react-autosuggest"; import Autosuggest from "react-autosuggest";
/** /**
@ -57,13 +57,55 @@ function SearchToolbar({
} }
}; };
const suggestionBgColor = useColorModeValue("transparent", "whiteAlpha.100");
const highlightedBgColor = useColorModeValue("gray.100", "whiteAlpha.300");
const renderSuggestion = React.useCallback( const renderSuggestion = React.useCallback(
(zoneLabel, { isHighlighted }) => ( (zoneLabel, { isHighlighted }) => (
<Box fontWeight={isHighlighted ? "bold" : "normal"}>{zoneLabel}</Box> <Box
fontWeight={isHighlighted ? "bold" : "normal"}
background={isHighlighted ? highlightedBgColor : suggestionBgColor}
padding="2"
paddingLeft="2.5rem"
fontSize="sm"
>
{zoneLabel}
</Box>
), ),
[suggestionBgColor, highlightedBgColor]
);
const renderSuggestionsContainer = React.useCallback(
({ containerProps, children }) => {
const { className, ...otherContainerProps } = containerProps;
return (
<Box
{...otherContainerProps}
borderBottomRadius="md"
boxShadow="md"
overflow="hidden"
transition="all 0.4s"
className={cx(
className,
css`
li {
list-style: none;
}
`
)}
>
{children}
</Box>
);
},
[] []
); );
// When we change the filter zone, clear out the suggestions.
React.useEffect(() => {
setSuggestions([]);
}, [query.filterToZoneLabel]);
const focusBorderColor = useColorModeValue("green.600", "green.400"); const focusBorderColor = useColorModeValue("green.600", "green.400");
return ( return (
@ -83,7 +125,9 @@ function SearchToolbar({
}} }}
getSuggestionValue={(zl) => zl} getSuggestionValue={(zl) => zl}
shouldRenderSuggestions={() => query.filterToZoneLabel == null} shouldRenderSuggestions={() => query.filterToZoneLabel == null}
highlightFirstSuggestion={true}
renderSuggestion={renderSuggestion} renderSuggestion={renderSuggestion}
renderSuggestionsContainer={renderSuggestionsContainer}
renderInputComponent={(props) => ( renderInputComponent={(props) => (
<InputGroup> <InputGroup>
{query.filterToZoneLabel ? ( {query.filterToZoneLabel ? (
@ -97,7 +141,7 @@ function SearchToolbar({
</InputLeftElement> </InputLeftElement>
)} )}
<Input {...props} /> <Input {...props} />
{query && ( {(query.value || query.filterToZoneLabel) && (
<InputRightElement> <InputRightElement>
<IconButton <IconButton
icon={<CloseIcon />} icon={<CloseIcon />}
@ -123,6 +167,7 @@ function SearchToolbar({
value: query.value || "", value: query.value || "",
ref: searchQueryRef, ref: searchQueryRef,
minWidth: 0, minWidth: 0,
borderBottomRadius: suggestions.length > 0 ? "0" : "md",
// HACK: Chakra isn't noticing the InputLeftElement swapping out // HACK: Chakra isn't noticing the InputLeftElement swapping out
// for the InputLeftAddon, so the styles aren't updating... // for the InputLeftAddon, so the styles aren't updating...
// Hard override! // Hard override!