Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Facets container

The Facets container lists and manages search filters (facets) to refine product search results.

import Facets from '@dropins/storefront-product-discovery/containers/Facets.js';

The Facets container provides the following configuration options:

Option Type Req? Description
scopestringNo Scope identifier for isolated instances. Default: undefined.
onFilterChangefunctionNo Callback when filters are changed. Receives updated filters array.
slotsobjectNo Allows passing custom components for Facet, SelectedFacets, and Facets slots.
// Basic facets container
await provider.render(Facets)($container);
// With scope and callback
await provider.render(Facets, {
scope: 'popover',
onFilterChange: (filters) => {
console.log('Filters changed:', filters);
}
})($container);

The Facets container supports several customization slots. For detailed information about available slots and their usage, see Product Discovery Slots.

slots: {
FacetBucketLabel: (ctx) => {
// Here we are overriding the default Facet labels.
const $label = document.createElement('span');
$label.innerText = `${ctx.data.name ?? ctx.data.title} (${ctx.data.count})`;
// If the facet has an icon, add it to the label
if (ctx.data.icon) {
const $icon = document.createElement('img');
$icon.className = 'facet-bucket-label__icon';
$icon.src = ctx.data.icon;
$label.prepend($icon);
}
ctx.replaceWith($label);
},
}

The container automatically updates when search events are received:

  1. Search Results: Updates available facets based on results
  2. Filter Changes: Automatically triggers new searches with updated filters

The Facets container supports isolated instances through scope configuration:

// Global scope (default) Listens to all search events
await provider.render(Facets)($container);
// Only listens to events with scope: 'popover'
await provider.render(Facets, { scope: 'popover' })($container);
  • Shows all currently selected filters as removable buttons
  • Displays filter labels with appropriate formatting (including currency for price ranges)
  • Provides individual remove functionality for each selected filter
  • “Clear All” button to remove all selected filters at once
  • Automatically triggers a new search with no filters applied
await provider.render(Facets)($facetsContainer);
await provider.render(Facets, {
onFilterChange: (filters) => {
console.log('Electronics filters changed:', filters);
}
})($electronicsFacets);
await provider.render(Facets, {
scope: 'popover',
onFilterChange: (filters) => {
// Quick search filters
console.log('Popover filters:', filters);
}
})($popoverFacets);
  1. Scope Management: Use unique scope identifiers for multiple instances
  2. Scope Configuration: Use appropriate scope identifiers for multiple instances
  3. Filter Callbacks: Use onFilterChange for custom filter handling
  4. Real-time Updates: Let the container handle updates automatically
  5. Performance: Use scoping to limit unnecessary updates
  6. Slot Customization: Use slots for merchant-specific facet styling
  1. Container Not Updating: Check scope configuration and event handling
  2. Slots Not Rendering: Ensure the element is added to the slot using ctx.appendChild(), ctx.replaceWith(), etc.
  3. Performance Issues: Use proper scoping to limit unnecessary updates
  4. Styling Conflicts: Use specific CSS classes to avoid conflicts
  • Dynamic Facets: Facets are automatically generated based on search results and available product attributes.
  • Category-Relative Filtering: If a categoryPath is provided in the search, facet selections will automatically include the categoryPath to ensure filters are relative to the current category.