Introducing the Search Web Components Module: A Better Way to Build Search Experiences
January 29, 2024
Since Drupal 8 was released in 2015, I've launched my fair share of sites, and one common feature of those sites was a search page. Working mainly with healthcare and e-commerce businesses during that time, the sites I launched often required not just a site search but a catalog search, a find a location search, or a find a doctor search. With those additional searches came designs and requirements that I needed to convince Views, Search API, and Facets to do. Search API is great, Views is great, Facets is great, but combined, they've never worked as expected for me. Every time I build one of those experiences, it's a fight to meet the expectations of site owners. And I'm not alone. When you go to the Facets issue queue, you'll find many issues and comments reporting issues with facets.
Today, I am bundling up all my hard won search experience to introduce an easier, better way to build search experiences with Drupal. Search Web Components will take a whole class of search challenges and make it something Drupal just does instead of being a complex and time consuming part of a project.
With some demo styles
Here's an example of what's possible with some styling. This video showcases functionality that's built into the Umami demo module for SWC.
Out of the box
Here's what the same demo experience looks like without any of the demo styling. This is what SWC will look like when you turn on the module and start building a search page.
Place components anywhere
All search components are required to be contained inside a
<search-root></search-root>, but within the search root, you can create any structure you want. Want the sort in the sidebar? Easy. Want facets below the search bar? Easy. Want a pager at the top and the bottom? Easy.
Render results with view modes
To make rendering results exactly like you want easy, you can index a Drupal view mode for each content type and render it in the results list.
Checkbox, radios, or dropdowns pick your flavor and have facets that work without AJAX or a full page refresh!
HTML dropdown facet
Create a dropdown that matches your designs with the
<facet-dropdown-html> component that provides a custom HTML dropdown functionally similar to a select field.
Bring your own styles
All the components are built as light DOM components, meaning you can use page level CSS for styles, and the components ship without styling, making them easy to style for your site.
Discover everything available in Storybook, where each component has examples, and all of its properties are documented.
A fully functional example implementation is maintained in the example module umami_search_web_components.
The long term goal for SWC is to make building search experiences that are performant and user friendly easy while leveraging Search API without custom code. Search is a huge problem space, so SWC will never be able to cover every search requirement but will target supporting 90% of common use cases.
When the 90% isn't enough, the goal is to build components in such a way that it is easy to extend and add your own components. Custom components should be easy to write, easy to maintain, and blend seamlessly with SWC provided components. Some experimentation with extension has been done in the Umami demo module and shows a promising path for achieving these goals.
Search pages are a big accessibility challenge. With changing content, lots of inputs, lots of tabbable elements, etc, all of which need to work on both mobile and desktop. By standardizing on a base set of components provided by SWC, it should be possible to provide a highly accessible search page out of the box.
The decoupled architecture of SWC means that search results only come from the search index itself. When using a traditional Search API/Views approach, it is easy to configure a search page that pulls content not just from the index but from Drupal's database. Pulling and rendering content from the database during a search will always be considerably slower than pulling content directly from the index.
Another benefit of the decoupled architecture is the much more stable on page experience. When searches are done, or facets are applied with Search API/Views rerenders are done either as a full page refresh or AJAX is used to replace parts of a page. Both can result in content shifting in what feels like a slow or laggy experience. With SWC, everything is rendered clientside, creating a minimal content shift and only one "flash" of change as all the components rerender simultaneously.
Facets that work
SWC facets are rendered directly from the API response, so as long as the response is correct, facets on the page will always be in sync and display the right options. From my personal experience, the issues I've had with Facets were largely with Ajax and not with the backend logic to determine available options. By using the backend logic without the Ajax logic, we get all the correct options without all the rendering issues.
Any component can be placed anywhere inside the
<search-root></search-root>, making it easy to create a structure that matches your site designs.
Try it yourself
The module page covers installation steps. If you already have Search API setup, setting up a SWC search page will be easy.
The Umami demo module is a great resource to quickly explore what's possible and contains working examples for configuration, styling, and extension.
Next StepsThe current set of functionality covers many of the bases, but there is always more to do. Some of the items currently on the shortlist are:
- Get user feedback: Part of the reason for an alpha release is to gather feedback on the current components and if there's anything big missing before a stable release can be tagged.
- Add missing commonly needed features: The current set of functionality is built based on my experience making search pages. I'm sure there are a few common components or configs left to add that I didn't think of.
- Better mock data in Storybook: Storybook currently mocks some of the components completely, but there are plenty of features that are not yet fully mocked. This is partially due to limitations in query support with Storybook and partially due to needing to support a bunch of variations of mock data.
- Write some tests: The more tests the better, with this many interactions and variables solid tests will be critical to providing a stable module. More tests are one of the major things that need to be done before a stable release.
- Add optional base styling: Unstyled components make it easy for sites to build the search they need. For sites that just need a functional search page, it'd be good to have some basic styling.
- Better document facet config support: Facets have a lot of configuration options associated with them, and each one needs to be evaluated per facet type to determine if special support needs to be added.
I'll be writing a follow up post doing a deep dive into the architecture of the components and modules, but until then here's a summary of how the module works. SWC is a library of web components written in TypeScript and built with Lit that share a common state using the Context concept provided by Lit. The main purpose of Context is to contain the current query represented as a
URLSearchParams object and the last API response with search terms, pages, results, facets, etc. The Search API endpoint is provided by the Search API Decoupled module. For styling, all components have changed Lit's default shadow DOM behavior to light DOM to allow global css to apply.