Facets | Yext Hitchhikers Platform
The <Facets />
component gives the end user the ability to further refine search results. Depending on the results that are returned, the user will see facets with a series of options they can select. If no results are returned in the query for a given facet option, that option will not appear.
Users can toggle a facet option checkbox on to further refine the search results. Within a single facet, if multiple options are selected (let’s call them option A and option B) the results will display any entities that contain either option A OR option B.
For more information about what facets are, take a look at the Facets and Filters reference doc.
Here’s what what the <Facets />
component looks like in the UI:
Basic Example
To make a field eligible as a facet, we need to make sure it’s set as a facet in the searchableFields
attribute in the search configuration. This exposes the field in the API response and allows facets to be applied on that field. For example:
{
"verticals": {
"products": {
"entityTypes": ["product"],
"searchableFields": {
"c_color": {
"facet": true
},
"c_size": {
"facet": true
}
}
}
}
}
Once that’s done, you can use the <Facets />
component.
<Facets />
are typically placed next to <VerticalResults />
. You’ll notice that some additional styling was applied to align the facets next to the results:
import { useSearchActions } from "@yext/search-headless-react";
import {
SearchBar,
StandardCard,
Facets,
VerticalResults,
} from "@yext/search-ui-react";
import { useEffect } from "react";
function App() {
const searchActions = useSearchActions();
useEffect(() => {
searchActions.setVertical("products");
}, []);
return (
<div className="flex justify-center px-4 py-6">
<div className="w-full max-w-5xl">
<SearchBar />
<div className="flex">
<Facets
customCssClasses={{ facetsContainer: "mr-10" }}
/>
<VerticalResults
CardComponent={StandardCard}
/>
</div>
</div>
</div>
);
}
export default App;
Overriding Specific Facets
The Facets
component will render all configured facets by default. However you might want to edit certain facets and not others. Take the following example:
<Facets>
<StandardFacet fieldId="c_size" label="Dimensions"/>
<Facets />
This renders all of the configured facets, but changes the label of the size
facet to Dimensions
.
We distinguish between three different kinds of facets in our platform: Standard Facets , Numerical Facets , and Hierarchical Facets . Each of these types is represented by its own component. For any facet that we want to override, we have to determine which component type to use.
Restricting Facets to Render
We can also restrict which facets render on the frontend. If we only care about a subset of facets for a specific vertical, we can update the above code to only render the relevant facets. We do that by adding the onlyRenderChildren
prop. Take the following example:
<Facets onlyRenderChildren={true}>
<StandardFacet fieldId="c_size" label="Dimensions"/>
<Facets />
The above code will only render the size
facet, and no others.
Changing Default Behavior
By default, the searchOnChange
prop is true
, which means when a user clicks on a facet option, a search is run with that added filter applied to return new results. When searchOnChange
is false
, we need a way to conduct that search when the user is ready to apply the selected facets.
We can do this by adding an <ApplyFiltersButton />
component:
import {
useSearchActions,
useSearchState,
} from "@yext/search-headless-react";
import {
SearchBar,
StandardCard,
Facets,
VerticalResults,
ApplyFiltersButton,
} from "@yext/search-ui-react";
import { useEffect } from "react";
function App() {
const searchActions = useSearchActions();
const facetOptionCount =
useSearchState((state) => state.filters.facets?.flatMap((f) => f.options))
?.length ?? 0;
useEffect(() => {
searchActions.setVertical("locations");
}, []);
return (
<div className="flex justify-center px-4 py-6">
<div className="w-full max-w-5xl">
<SearchBar />
<div className="flex">
<div>
<Facets
customCssClasses={{ facetsContainer: "mr-10" }}
searchOnChange={false}
/>
{facetOptionCount > 0 && (
<ApplyFiltersButton customCssClasses={{ button: "mt-2" }} />
)}
</div>
<VerticalResults
customCssClasses={{ results: "flex-grow" }}
CardComponent={StandardCard}
allowPagination={false}
/>
</div>
</div>
</div>
);
}
export default App;
Resulting in an experience that looks like so:
Customizations
Like the rest of our components, you can customize the elements of the Facets using the customCssClasses
prop.