SearchGuide appends and refines a search query. They appear under SearchField after user submits a search input.
also known as Search filters, Pivots, Vanilla guides
Props
Usage guidelines
- To refine the original search query with more accurate and targeted keywords.
Best practices
Place SearchGuides at the start of the screen, and scroll horizontally to reveal additional guides.
Note: Be aware that off-screen guides have significantly lower engagement.
Truncate search queries to fit within a viewport.
SearchGuides are serial and appear in multiples.
SearchGuides should not be used as a single SearchGuide.
Show high quality SearchGuides that are relevant to the user’s search query.
When a query doesn’t produce enough guides of sufficient quality, they shouldn’t be shown
Limit the number of SearchGuides to 9 per search query.
Do not show more than 9 SearchGuides per search query.
Limiting vertical scrolling helps to enhance the user experience by reducing the effort required to navigate and locate content.
Do not use vertical scrolling for SearchGuides.
Accessibility
ARIA attributes
When SearchGuide text does not provide sufficient context about the SearchGuide’s behavior, supply a short, descriptive label for screen-readers using accessibilityLabel
.
If SearchGuide is used as a control SearchGuide to show/hide a Popover-based component, we recommend passing the following ARIA attributes to assist screen readers:
accessibilityLabel
: if present, read by screen readers read instead of thetext
prop.accessibilityControls
: informs the screen reader that SearchGuide controls the display of an anchored Popover-based component. It populates aria-controls.accessibilityHaspopup
: informs the screen reader that there’s a Popover-based component attached to SearchGuide. It populates aria-haspopup.accessibilityExpanded
: informs the screen reader whether the searchguide-anchored Popover-based component is currently open or closed. It populates aria-expanded.
Also consider:
- Ensure that each SearchGuide uses the correct markup for lists. Typically screen readers announce the number of items in a list and announce each item.
- Limit the number of SearchGuides to 9 per search query. Horizontal scrolling can be challenging to users with mobility issues, or users of assistive devices such as screen readers.
Localization
Be sure to localize all text strings. Note that localization can lengthen text by 20 to 30 percent.
Avoid truncating SearchGuide text whenever possible. Refer to the SearchGuide usage guidelines for more information
Variants
Colors
Use the color
prop to change the background color of the SearchGuide. The color prop can be one of the following values:
import { Box, Flex, SearchGuide, Text } from 'gestalt'; export default function Example() { return ( <Box padding={4}> <Flex gap={6} height="100%" width="100%" wrap> {['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11'].map( (color) => { const colorCopy = color; return ( <Flex key={colorCopy} direction="column" gap={2}> <Box alignItems="center" borderStyle="sm" color="default" display="flex" height={200} justifyContent="center" rounding={4} width={200} > <SearchGuide color={colorCopy} text={`Color ${color}`} /> </Box> <Text size="200" weight="bold"> color="{colorCopy}" </Text> </Flex> ); } )} </Flex> </Box> ); }
Thumbnail
Use the thumbnail
prop to display an image to the left of the text. The thumbnail
prop can be an
Avatar,
AvatarGroup,
Image, or
Icon.
import { useRef, useState } from 'react'; import { Box, Flex, Icon, Popover, SearchGuide } from 'gestalt'; export default function Example() { const ideasRef = useRef(null); const boardsRef = useRef(null); const [showIdeas, setshowIdeas] = useState(false); const [showBoards, setshowBoards] = useState(false); return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex gap={2} width="100%" wrap> <SearchGuide accessibilityLabel="Search" color="02" text="Search" thumbnail={{ icon: <Icon accessibilityLabel="search" icon="search" />, }} /> <SearchGuide ref={ideasRef} accessibilityControls="popover" accessibilityExpanded={showIdeas} accessibilityHaspopup accessibilityLabel="Ideas" color="03" expandable onClick={() => setshowIdeas((showing) => !showing)} selected={showIdeas} text="Ideas" thumbnail={{ icon: <Icon accessibilityLabel="ideas" icon="sparkle" />, }} /> <SearchGuide ref={boardsRef} accessibilityLabel="Search" color="04" expandable onClick={() => setshowBoards((showing) => !showing)} selected={showBoards} text="" thumbnail={{ icon: <Icon accessibilityLabel="search" icon="search" />, }} /> </Flex> {showIdeas && ( <Popover anchor={ideasRef.current} id="popover" idealDirection="down" onDismiss={() => setshowIdeas(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} {showBoards && ( <Popover anchor={boardsRef.current} id="popover" idealDirection="down" onDismiss={() => setshowBoards(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} </Flex> ); }
import { useRef, useState } from 'react'; import { Box, Flex, Image, Popover, SearchGuide } from 'gestalt'; export default function Example() { const vintageRef = useRef(null); const outfitRef = useRef(null); const [showVintage, setShowVintage] = useState(false); const [showOutfit, setShowOutfit] = useState(false); return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex gap={2} width="100%" wrap> <SearchGuide accessibilityLabel="Design" color="01" text="Design" thumbnail={{ image: ( <Image alt="Design" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/3CT3Xnp/image.png" /> ), }} /> <SearchGuide ref={vintageRef} accessibilityControls="popover" accessibilityExpanded={showVintage} accessibilityHaspopup accessibilityLabel="Vintage" color="02" expandable onClick={() => setShowVintage((showing) => !showing)} selected={showVintage} text="Vintage" thumbnail={{ image: ( <Image alt="Vintage" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/dWQ7HHg/image.png" /> ), }} /> <SearchGuide ref={outfitRef} accessibilityControls="popover" accessibilityExpanded={showOutfit} accessibilityHaspopup accessibilityLabel="Outfit" color="03" expandable onClick={() => setShowOutfit((showing) => !showing)} selected={showOutfit} text="" thumbnail={{ image: ( <Image alt="Outfit" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/bBXC23j/fashion.jpg" /> ), }} /> </Flex> {showVintage && ( <Popover anchor={vintageRef.current} id="popover" idealDirection="down" onDismiss={() => setShowVintage(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} {showOutfit && ( <Popover anchor={outfitRef.current} id="popover" idealDirection="down" onDismiss={() => setShowOutfit(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Casual" /> <SearchGuide color="02" text="Formal" /> <SearchGuide color="03" text="Athletic" /> </Flex> </Box> </Popover> )} </Flex> ); }
import { useRef, useState } from 'react'; import { AvatarGroup, Box, Flex, Popover, SearchGuide } from 'gestalt'; export default function Example() { const pinsRef = useRef(null); const creatorsRef = useRef(null); const [showPins, setShowPins] = useState(false); const [showCreators, setShowCreators] = useState(false); return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex gap={2} width="100%" wrap> <SearchGuide accessibilityLabel="Pins" color="04" text="Pins" thumbnail={{ avatarGroup: ( <AvatarGroup accessibilityLabel="Fatima, Sora." collaborators={[ { name: 'Fatima', src: 'https://i.pinimg.com/originals/bf/bc/27/bfbc27685d81eb9a8f65c201ea661f0e.jpg', }, { name: 'Sora', src: 'https://i.pinimg.com/originals/ab/c5/4a/abc54abd85df131e90ca6b372368b738.jpg', }, ]} size="md" /> ), }} /> <SearchGuide ref={pinsRef} accessibilityControls="popover" accessibilityExpanded={showPins} accessibilityHaspopup accessibilityLabel="Pins" color="01" expandable onClick={() => setShowPins((showing) => !showing)} selected={showPins} text="Pins" thumbnail={{ avatarGroup: ( <AvatarGroup accessibilityLabel="Fatima, Sora." collaborators={[ { name: 'Sora', src: 'https://i.pinimg.com/originals/ab/c5/4a/abc54abd85df131e90ca6b372368b738.jpg', }, { name: 'Ayesha', src: 'https://i.pinimg.com/originals/c5/5c/ac/c55caca43a7c16766215ec165b649c1c.jpg', }, ]} size="md" /> ), }} /> <SearchGuide ref={creatorsRef} accessibilityControls="popover" accessibilityExpanded={showCreators} accessibilityHaspopup accessibilityLabel="Pins" color="05" expandable onClick={() => setShowCreators((showing) => !showing)} selected={showCreators} text="" thumbnail={{ avatarGroup: ( <AvatarGroup accessibilityLabel="Fatima, Sora." collaborators={[ { name: 'Ayesha', src: 'https://i.pinimg.com/originals/c5/5c/ac/c55caca43a7c16766215ec165b649c1c.jpg', }, { name: 'Fatima', src: 'https://i.pinimg.com/originals/bf/bc/27/bfbc27685d81eb9a8f65c201ea661f0e.jpg', }, { name: 'Sora', src: 'https://i.pinimg.com/originals/ab/c5/4a/abc54abd85df131e90ca6b372368b738.jpg', }, ]} size="md" /> ), }} /> </Flex> {showPins && ( <Popover anchor={pinsRef.current} id="popover" idealDirection="down" onDismiss={() => setShowPins(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} {showCreators && ( <Popover anchor={creatorsRef.current} id="popover" idealDirection="down" onDismiss={() => setShowCreators(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} </Flex> ); }
import { useRef, useState } from 'react'; import { Avatar, Box, Flex, Popover, SearchGuide } from 'gestalt'; export default function Example() { const enioRef = useRef(null); const keerthiRef = useRef(null); const [showEnio, setShowEnio] = useState(false); const [showKeerthi, setShowKeerthi] = useState(false); return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex gap={2} width="100%" wrap> <SearchGuide accessibilityLabel="Fatima" color="02" text="Fatima" thumbnail={{ avatar: ( <Avatar name="Fatima" src="https://i.pinimg.com/originals/bf/bc/27/bfbc27685d81eb9a8f65c201ea661f0e.jpg" /> ), }} /> <SearchGuide ref={enioRef} accessibilityControls="popover" accessibilityExpanded={showEnio} accessibilityHaspopup accessibilityLabel="Sora" color="03" expandable onClick={() => setShowEnio((showing) => !showing)} selected={showEnio} text="Sora" thumbnail={{ avatar: ( <Avatar name="Sora" src="https://i.pinimg.com/originals/ab/c5/4a/abc54abd85df131e90ca6b372368b738.jpg" /> ), }} /> <SearchGuide ref={keerthiRef} accessibilityControls="popover" accessibilityExpanded={showKeerthi} accessibilityHaspopup accessibilityLabel="Ayesha" color="04" expandable onClick={() => setShowKeerthi((showing) => !showing)} selected={showKeerthi} text="" thumbnail={{ avatar: ( <Avatar name="Ayesha" src="https://i.pinimg.com/originals/c5/5c/ac/c55caca43a7c16766215ec165b649c1c.jpg" /> ), }} /> </Flex> {showEnio && ( <Popover anchor={enioRef.current} id="popover" idealDirection="down" onDismiss={() => setShowEnio(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} {showKeerthi && ( <Popover anchor={keerthiRef.current} id="popover" idealDirection="down" onDismiss={() => setShowKeerthi(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Boards" /> <SearchGuide color="02" text="Pins" /> </Flex> </Box> </Popover> )} </Flex> ); }
States
Use the selected
prop to indicate that the SearchGuide is in a selected state.
import { useState } from 'react'; import { Flex, Image, SearchGuide } from 'gestalt'; export default function Example() { const [design, setDesign] = useState(false); const [outfit, setOutfit] = useState(true); const [vintage, setVintage] = useState(false); return ( <Flex alignItems="center" gap={2} height="100%" justifyContent="center" width="100%" > <SearchGuide accessibilityLabel="Designs" color="03" onClick={() => { setDesign((value) => !value); setOutfit(false); setVintage(false); }} selected={design} text="Designs" thumbnail={{ image: ( <Image alt="Image" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/3CT3Xnp/image.png" /> ), }} /> <SearchGuide accessibilityLabel="Outfit" color="04" onClick={() => { setDesign(false); setOutfit((value) => !value); setVintage(false); }} selected={outfit} text="Outfit" thumbnail={{ image: ( <Image alt="Image" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/bBXC23j/fashion.jpg" /> ), }} /> <SearchGuide accessibilityLabel="Vintage" color="05" onClick={() => { setDesign(false); setOutfit(false); setVintage((value) => !value); }} selected={vintage} text="Vintage" thumbnail={{ image: ( <Image alt="Image" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/dWQ7HHg/image.png" /> ), }} /> </Flex> ); }
Expandable
import { Fragment, useRef, useState } from 'react'; import { Box, Flex, Popover, SearchGuide } from 'gestalt'; export default function Example() { const [showOutfits, setShowOutfits] = useState(false); const anchorRef = useRef(null); return ( <Fragment> <Flex alignContent="stretch" alignItems="center" gap={2} justifyContent="center" width="100%" > <SearchGuide ref={anchorRef} accessibilityControls="popover" accessibilityExpanded={showOutfits} accessibilityHaspopup accessibilityLabel="Outfits" color="02" expandable onClick={() => setShowOutfits((showing) => !showing)} selected={showOutfits} text="Outfits" /> </Flex> {showOutfits && ( <Popover anchor={anchorRef.current} id="popover" idealDirection="down" onDismiss={() => setShowOutfits(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Casual" /> <SearchGuide color="02" text="Formal" /> <SearchGuide color="03" text="Athletic" /> </Flex> </Box> </Popover> )} </Fragment> ); }
import { Fragment, useRef, useState } from 'react'; import { Avatar, AvatarGroup, Box, Flex, Icon, Image, Layer, Popover, SearchGuide, } from 'gestalt'; export default function Example() { const [showDefault, setShowDefault] = useState(false); const [showTextless, setShowTextless] = useState(false); const [showImage, setShowImage] = useState(false); const [showAvatar, setShowAvatar] = useState(false); const [showAvatarGroup, setShowAvatarGroup] = useState(false); const defaultRef = useRef(null); const textlessRef = useRef(null); const imageRef = useRef(null); const avatarRef = useRef(null); const avatarGroupRef = useRef(null); return ( <Fragment> <Flex alignContent="stretch" alignItems="center" gap={2} justifyContent="center" width="100%" > <SearchGuide ref={defaultRef} accessibilityControls="popover" accessibilityExpanded={showDefault} accessibilityLabel="SearchGuide with text" color="01" expandable onClick={() => setShowDefault((showing) => !showing)} selected={showDefault} text="Text" /> <SearchGuide ref={textlessRef} accessibilityControls="popover" accessibilityExpanded={showTextless} accessibilityLabel="SearchGuide with Icon" color="02" expandable onClick={() => setShowTextless((showing) => !showing)} selected={showTextless} text="Icon" thumbnail={{ icon: <Icon accessibilityLabel="Icon" icon="sparkle" />, }} /> <SearchGuide ref={imageRef} accessibilityControls="popover" accessibilityExpanded={showImage} accessibilityLabel="SearchGuide with Image" color="03" expandable onClick={() => setShowImage((showing) => !showing)} selected={showImage} text="Image" thumbnail={{ image: ( <Image alt="Image" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/bBXC23j/fashion.jpg" /> ), }} /> <SearchGuide ref={avatarRef} accessibilityControls="popover" accessibilityExpanded={showAvatar} accessibilityLabel="SearchGuide with Avatar" color="04" expandable onClick={() => setShowAvatar((showing) => !showing)} selected={showAvatar} text="Avatar" thumbnail={{ avatar: ( <Avatar name="Keerthi" src="https://i.ibb.co/ZfCZrY8/keerthi.jpg" /> ), }} /> <SearchGuide ref={avatarGroupRef} accessibilityControls="popover" accessibilityExpanded={showAvatarGroup} accessibilityLabel="SearchGuide with AvatarGroup" color="05" expandable onClick={() => setShowAvatarGroup((showing) => !showing)} selected={showAvatarGroup} text="AvatarGroup" thumbnail={{ avatarGroup: ( <AvatarGroup accessibilityLabel="Collaborators: Keerthi, Alberto, Enio." collaborators={[ { name: 'Keerthi', src: 'https://i.ibb.co/ZfCZrY8/keerthi.jpg', }, { name: 'Alberto', src: 'https://i.ibb.co/NsK2w5y/Alberto.jpg', }, { name: 'Enio', }, ]} size="md" /> ), }} /> </Flex> <Layer> {showDefault && ( <Popover anchor={defaultRef.current} id="popover" idealDirection="down" onDismiss={() => setShowDefault(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Default 1" /> <SearchGuide color="02" text="Default 2" /> <SearchGuide color="03" text="Default 3" /> </Flex> </Box> </Popover> )} {showTextless && ( <Popover anchor={textlessRef.current} id="popover" idealDirection="down" onDismiss={() => setShowTextless(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Textless 1" /> <SearchGuide color="02" text="Textless 2" /> <SearchGuide color="03" text="Textless 3" /> </Flex> </Box> </Popover> )} {showImage && ( <Popover anchor={imageRef.current} id="popover" idealDirection="down" onDismiss={() => setShowImage(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Image 1" /> <SearchGuide color="02" text="Image 2" /> <SearchGuide color="03" text="Image 3" /> </Flex> </Box> </Popover> )} {showAvatar && ( <Popover anchor={avatarRef.current} id="popover" idealDirection="down" onDismiss={() => setShowAvatar(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="Avatar 1" /> <SearchGuide color="02" text="Avatar 2" /> <SearchGuide color="03" text="Avatar 3" /> </Flex> </Box> </Popover> )} {showAvatarGroup && ( <Popover anchor={avatarGroupRef.current} id="popover" idealDirection="down" onDismiss={() => setShowAvatarGroup(false)} size="flexible" > <Box height={120} overflow="scrollX" padding={4}> <Flex direction="row" gap={2} wrap> <SearchGuide color="01" text="AvatarGroup 1" /> <SearchGuide color="02" text="AvatarGroup 2" /> <SearchGuide color="03" text="AvatarGroup 3" /> </Flex> </Box> </Popover> )} </Layer> </Fragment> ); }
Writing
- Use short, meaningful labels that succinctly describe the search queries
- Use the variants available as a guide to determine how specific the search query append should be
Component quality checklist
Quality item | Status | Status description |
---|---|---|
Figma Library | Partially ready | Component is live in Figma, however may not be available for all platforms. |
Responsive Web | Ready | Component responds to changing viewport sizes in web and mobile web. |
Internal documentation
Related
SearchGuideLink
Use SearchGuideLink when a link is needed instead of an action.
SearchField
If the input is used for searching content, use SearchField.