Customizing Instant Results

When ElasticPress Instant Results renders search results it does so using a React component. You can replace this component with your own from within a theme or plugin using the ep.InstantResults.Result JavaScript hook.

The result component receives the following props that your component can use to render the result:

proptypedescription
averageRatingnumberAverage review rating for WooCommerce products.
datestringLocalized date.
hitobjectFull result from Elasticsearch.
excerptstringHighlighted excerpt.
idstringPost ID.
priceHtmlstringPrice HTML for a WooCommerce product.
thumbnailobjectThumbnail image attributes.
titlestringHighlighted title.
typestringPost type label.
urlstringPost permalink.

This example replaces the result component with a component that renders results as just a simple linked title and date in a div:

JSX

JSX
const CustomResult = ({ date, title, url }) => {
	return (
		<div className="my-custom-result">
			<strong><a href={url}>{title}</a></strong> {date}
		</div>
	)
};
wp.hooks.addFilter('ep.InstantResults.Result', 'myTheme/customResult', () => CustomResult);

Plain

JavaScript
const el = wp.element.createElement;
const CustomResult = ({ date, title, url }) => {
	return el(
		'div',
		{
			className: 'my-custom-result',
		},
		el(
			'strong',
			{},
			el(
				'a',
				{ href: url },
				title
			),
		),
		' ',
		date
	);
};
wp.hooks.addFilter('ep.InstantResults.Result', 'myTheme/customResult', () => CustomResult);

To conditionally replace the component based on each result you can pass a simple component that checks the result before either rendering the original component or a new custom component. This example renders the custom component from above but only for results with the post post type:

JSX

JSX
wp.hooks.addFilter('ep.InstantResults.Result', 'myTheme/customResultForPosts', (Result) => {
	return (props) => {
		if (props.hit._source.post_type === 'post') {
			return <CustomResult {...props} />;
		}

		return <Result {...props} />;
	};
});

Plain

JavaScript
const el = wp.element.createElement;

wp.hooks.addFilter(
	'ep.InstantResults.Result',
	'myTheme/customResultForPosts',
	(Result) = {
		return(props) = {
			if (props.hit._source.post_type === 'post') {
				return el(CustomResult, props);
			}
			return el(Result, props);
		};
	}
);

By returning a new component that wraps the original component you can customize the props that are passed to it. This example uses this approach to remove the post type label from results with the page post type:

JSX

JSX
wp.hooks.addFilter(
	'ep.InstantResults.Result',
	'myTheme/noTypeLabelsForPages',
	(Result) => {
		return (props) => {
			if (props.hit._source.post_type === 'page') {
				return <Result {...props} type={null} />;
			}

			return <Result {...props} />;
		};
	}
);

Plain

JavaScript
const el = wp.element.createElement;

wp.hooks.addFilter(
	'ep.InstantResults.Result',
	'myTheme/noTypeLabelsForPages',
	(Result) => {
		return (props) => {
			if (props.hit._source.post_type === 'page') {
				return el(Result, {...props, type: null});
			}

			return el(Result, props);
		};
	}
);

Notes:

  • To take advantage of JavaScript hooks, make sure to set wp-hooks as a dependency of your script.
  • These examples use JSX to render for readability. Using JSX will require a build tool such as @wordpress/scripts to compile it into a format that can be understood by the browser. To create a component without a build process you will need to use the more verbose createElement method of @wordpress/element.

Styling Instant Results

The default styles for Instant Results are as minimal as they can be to allow Instant Results to reflect the active theme’s design and styles as much as possible while maintaining the expected layout. However, you may still wish to add styles to your theme specifically for Instant Results. To help with styling, Instant Results supports several custom CSS properties that can be used to update certain recurring styles without needing to target multiple selectors. For other elements, Instant Results uses BEM syntax to allow easier styling of recurring components.

Custom Properties

The following is a list of CSS custom properties you can set from your own theme to modify the appearance of Instant Results. This list may expand as more features and customization options are added to Instant Results.

  • --ep-search-background-colorSetting this property will set the background color of the Instant Results modal, as well as the colors of any elements that should match the background color, such as parts of the Price facet’s slider.
  • --ep-search-alternate-background-colorThis property is used for the background color for elements that should appear offset from the regular background. This includes the post type labels for results, as well as the track for the Price facet’s slider.
  • --ep-search-border-colorThis property is used for any lines used as borders or separators such as the borders around facets.
  • --ep-search-range-thumb-sizeThis property controls the size of the ‘thumbs’ or ‘handles’ of the range slider used for the Price facet. By default, this has different values for desktop and mobile so that on mobile they are more touch-friendly. This is something you may want to replicate in your own theme.
  • --ep-search-range-track-sizeThis property controls the size of the track that the range slider handles travel along in the Price facet. By default, this has different values for desktop and mobile so that on mobile it is more touch friendly. This also is something you may want to replicate in your own theme.

The values for custom properties can be set within a stylesheet by declaring them as you would any other CSS property:

CSS
:root {--ep-search-border-color:#1a1a1a;}

All other colors used in Instant Results are inherited from the default styles of your theme.

Components

The HTML classes used by Instant Results adhere to the BEM syntax and therefore the Instant Results UI is made from an assortment of components or “blocks”. The following is a list of the top-levelBlock classes that represent the components that you will most likely want to style, as they are the most likely to be affected by your theme’s default styles.

  • .ep-search-input: This is the main search input inside the Instant Results modal. By default, it will use the theme’s default styling for<input>elements but full-width and with increased font size.
  • .ep-search-result: This is the component used for individual search results and comprises the image, post-type label, title, excerpt, and date. The default styles for the post title and excerpt will be inherited from the theme’s default styles for<h2>and<p>elements respectively.
  • .ep-search-panel: This is the component used to contain each facet. It comprises a heading with a button for expanding and collapsing the facet, and the collapsible content of the panel which contains the facet itself. By default panels have a border whose color is controlled by a custom CSS property outlined above, and the button should inherit the theme’s default styles for<h3>elements.
    • Note that for WooCommerce Product results the price and star ratings use the default WooCommerce markup, rather than Instant Results’ own markup, so their styles will be inherited from the theme’s WooCommerce styles if they exist, or WooCommerce’s own styles.
  • .ep-search-small-button: This is the component used for the ‘chips’ for active filters and the clear filters button. By default, it will use the theme’s default styling for<button>elements but with a small font size and a little padding.
  • .ep-search-sidebar-toggle: This is the component used for the button that appears on mobile for displaying the list of filters. By default, it will use the theme’s default styling for<button>elements but full width.
  • .ep-search-pagination-button: This is the component used for the Next and Previous page buttons. By default, it will use the theme’s default styling for<button>elements.

All other components that can be styled, such as those used for layout, can be found by inspecting the markup of Instant Results with a browser’s developer tools. New components may be added as more features and customization options are added to Instant Results.

Open Instant Results on Button Press

By default, the Instant Results modal will only be opened by submitting a WordPress search form, but you can manually open Instant Results from your theme or plugin by calling thewindow.epInstantResults.openModal()function. This allows you to open Instant Results in response to other events, such as by clicking a button. Additionally, bypassing certain parameters to the function you can set the initial search term, sorting, and filters.

The following parameters are supported by passing them to theopenModal()function in an object:

ParameterTypeDescription
searchstringSearch term. Default''.
per_pageintegerMaximum number of items to be returned in result set.
tax-{$taxonomy}number[]Filter results by taxonomy terms. Array of term IDs.
orderasc|descOrder results in ascending or descending order. Defaultdesc.
orderbydate|relevance|priceOrder results by attribute. Defaultrelevance.
post_typestringFilter results by post type. Comma separated list of post type slugs.

This example uses the function to open the modal with a search for a specific search term when a button is clicked:

HTML
<button id="search-blocks" type="button">Search for "Blocks"</button>
<script>
	document
		.getElementById('search-blocks')
		.addEventListener(
			'click',
			() => {
				window
					.epInstantResults
					.openModal({ search:"blocks" });
			}
		);
</script>


Change the number of results per page

As of ElasticPress 4.5.0, Instant Results will display the same number of results per page as the number of posts per page set in Settings > Reading. The ep_instant_results_per_page filter can be used to change the number of results per page independently of the number of posts per page:

PHP
add_filter(
	'ep_instant_results_per_page',
	function() {
		return 12;
	}
);