Add Custom Location Result Cards | Yext Hitchhikers Platform

What You’ll Learn

In this section, you will:

  • Generate Typescript types for search results with the Yext CLI
  • Create a custom LocationResult component and use it with VerticalResults to display more information for each result

Overview

In this unit, you will create custom Location result cards. You will then pass the custom card to VerticalResults to display each result with more information about each location.


In the next two units, you are going to use React Icons for some custom styling. Add them to your project with the following command:

npm i react-icons

1. Generate Types For Your Search Experience

The Yext CLI comes with a handy tool for generating Typescript types for a particular search experience. You can read more about typing with Yext Search here .

In the terminal, run the following command:

yext types generate search src/types --experienceKey turtlehead-tacos-locator

Check out the new locations.ts file that was generated for you inside of src/types. You’ll notice that the Location type contains all the possible fields that could be included in a Location search result.

2. Create a Custom Location Result Card

Right now, you are using the StandardCard with VerticalResults in the StoreLocator component to display location results, which only displays the name and description fields for each result. To display more information, let’s create a custom LocationCard to display the address and neighborhood fields as well!

In src/components, add a new file called LocationCard.tsx and add the following code:

// src/components/LocationCard.tsx

import { CardComponent, CardProps } from "@yext/search-ui-react";
import Location, { Coordinate } from "../types/locations";
import { RiDirectionFill } from "react-icons/ri";

const LocationCard: CardComponent<Location> = ({
  result,
}: CardProps<Location>): JSX.Element => {
  const location = result.rawData;

  // function that takes coordinates and returns a google maps link for directions
  const getGoogleMapsLink = (coordinate: Coordinate): string => {
    return `https://www.google.com/maps/dir/?api=1&destination=${coordinate.latitude},${coordinate.longitude}`;
  };

  return (
    <div className="flex justify-between border-y p-4">
      <div className="flex">
        <div>
          <a
            target={"_blank"}
            href={location.slug}
            className="font-semibold text-orange"
            rel="noreferrer"
          >
            {location.neighborhood}
          </a>
          <p className="text-sm">{location.address.line1}</p>
          <p className="text-sm">{`${location.address.city}, ${location.address.region} ${location.address.postalCode}`}</p>
        </div>
      </div>
      <div className="flex items-center">
        {location.yextDisplayCoordinate && (
          <a
            target={"_blank"}
            className="flex flex-col items-center text-sm text-orange"
            href={getGoogleMapsLink(location.yextDisplayCoordinate)}
            rel="noreferrer"
          >
            <RiDirectionFill size={24} />
            <p>Directions</p>
          </a>
        )}
      </div>
    </div>
  );
};

export default LocationCard;

Let’s review what you just added:

  • CardComponent is generically typed. By passing Location as the type parameter to CardProps, the rawData on the result prop will be typed as a Location. You can learn more about Typescript generics here .
  • You are displaying the neighborhood rather than the name of the location and wrapping it in an a tag that links out to the landing page for the location.
  • You are taking the address, formatting it, and displaying it below the neighborhood.
  • You have wrapped an icon with an a tag that will link out to Google Maps with directions to that particular location.

3. Add the LocationCard to VerticalResults

Now that you new result cards are ready to go, pass LocationCard as the CardComponent prop to VerticalResults in your StoreLocator component:

// src/components/StoreLocator.tsx

import {
  MapboxMap,
  FilterSearch,
  OnSelectParams,
  VerticalResults,
} from "@yext/search-ui-react";
import {
  Matcher,
  SelectableStaticFilter,
  useSearchActions,
} from "@yext/search-headless-react";
// Mapbox CSS bundle
import "mapbox-gl/dist/mapbox-gl.css";
import LocationCard from "./LocationCard";               // New

const StoreLocator = (): JSX.Element => {
  const searchActions = useSearchActions();

  const handleFilterSelect = (params: OnSelectParams) => {
    const locationFilter: SelectableStaticFilter = {
      displayName: params.newDisplayName,
      selected: true,
      filter: {
        kind: "fieldValue",
        fieldId: params.newFilter.fieldId,
        value: params.newFilter.value,
        matcher: Matcher.Equals,
      },
    };
    searchActions.setStaticFilters([locationFilter]);
    searchActions.executeVerticalQuery();
  };

  return (
    <>
      <div className="flex h-[calc(100vh-242px)] border">
        <div className="w-1/3 flex flex-col">
          <FilterSearch
            onSelect={handleFilterSelect}
            placeholder="Find Locations Near You"
            searchFields={[
              {
                entityType: "location",
                fieldApiName: "builtin.location",
              },
            ]}
          />
          <VerticalResults
            customCssClasses={{ verticalResultsContainer: "overflow-y-auto" }}
            CardComponent={LocationCard}   // New           
          />
        </div>
        <div className="w-2/3">
          <MapboxMap
            mapboxAccessToken={YEXT_PUBLIC_MAPBOX_API_KEY || ""}
          />
        </div>
      </div>
     </>
  );
};

export default StoreLocator;

If your site isn’t already running, start it back up with npm run dev and go the locator page. Search for “New York City, New York, NY” to see your new result cards.

light bulb
Note
When running the site locally, you’ll notice that clicking on the neighborhood to link out to the location landing page will lead to a 404 page. This is because local URLs do not match production URLs in Yext Pages. After you push your code and deploy your site, you will be able to link out to the location landing pages.
unit Quiz
+20 points
Daily Quiz Streak Daily Quiz Streak: 0
Quiz Accuracy Streak Quiz Accuracy Streak: 0
    Error Success Question 1 of 1

    What fields from the location entity are being used in the LocationCard component?

    You're a star! ⭐

    You've already completed this quiz, so you can't earn more points.You completed this quiz in 1 attempt and earned 0 points! Feel free to review your answers and move on when you're ready.
1st attempt
0 incorrect
Feedback