Usage

The Coveo Atomic library provides you with a customizable set of UI components that are already configured to communicate with the Coveo Platform. These web components, which are built on top of the Coveo Headless library, can be used with or without existing frameworks.

This article provides an overview of the core Atomic concepts.

Install Atomic

The simplest way to install the Atomic component library is through a content delivery network (CDN).

Include the following scripts in the target HTML page:

<script                                                                 (1)
    type="module"
    src="https://static.cloud.coveo.com/atomic/latest/atomic.esm.js">
</script>
<link                                                                   (2)
    rel="stylesheet"
    href="https://static.cloud.coveo.com/atomic/latest/themes/default.css"/>
1 The main framework script.
2 The default stylesheet for the framework. While this import is optional, if you don’t import it you will need to define its variables yourself (see default.css).

The library is also available as an npm package.

npm install @coveo/atomic

All of the resources will be available under /node_modules/@coveo/atomic/dist/atomic. You can include those in target pages with <script> tags.

If you’re using a module bundler (Browserify, Webpack, Rollup, etc.), you can use require('@coveo/atomic') or import '@coveo/atomic'.

Use Components to Create a Search Interface

Atomic builds search pages by attaching components to target HTML elements.

This means you can build your search page by assembling the target HTML elements:

<body>
  <atomic-search-interface>
    <atomic-search-box></atomic-search-box>
    <atomic-facet-manager>
      <atomic-facet field="author" label="Authors"></atomic-facet>
      <!-- ... -->
    </atomic-facet-manager>
    <!-- ... -->
  </atomic-search-interface>
</body>

Then, to turn those HTML elements into real Atomic components, you use a script to initialize the overarching atomic-search-interface component:

<head>
  <script>
    (async () => {
      await customElements.whenDefined('atomic-search-interface');
      const searchInterface = document.querySelector('atomic-search-interface');
      await searchInterface.initialize({
        accessToken:'<ORGANIZATION_ID>',                                        (1)
        organizationId: '<ACCESS_TOKEN>'                                        (2)
      });
    })();
  </script>
  <!--- ... --->
</head>

where:

1 <ACCESS_TOKEN> (string) is an API key or search token that grants the Allowed access level on the Execute Queries domain, as well as the Push access level on the Analytics Data domain in the target organization.
2 <ORGANIZATION_ID> (string) is the unique identifier of your Coveo organization (e.g., mycoveoorganizationa1b23c).

Several components expose options. For example, the following search box will offer a maximum of two query suggestions:

<atomic-search-box number-of-suggestions=2></atomic-search-box>

For more details about the properties of the atomic-search-box component, see the Reference Documentation for that component.

Some components also expose methods:

const searchInterface = document.querySelector("atomic-search-interface");
await searchInterface.initialize({
  accessToken: "xx564559b1-0045-48e1-953c-3addd1ee4457",
  organizationId: "searchuisamples"
}); (1)
searchInterface.executeFirstSearch(); (2)
1 As seen in the example above, the initialize method is used to initialize the interface. In this case, use the await operator to wait for the interface initialization to complete before moving on.
2 The executeFirstSearch method this then used to trigger a search after initializing the interface. For more information about the atomic-search-interface methods, see the Reference Documentation.

Style Your Components

Atomic uses shadow DOM to instantiate components. This encapsulates a specific section of the DOM to allow for componentization, meaning that the component style is independent from the surrounding DOM styling. As such, you must style those components using their shadow DOM parts. For example:

<style>
  atomic-result::part(result-printable-uri-list-element){
    text-transform: capitalize;
  }
  atomic-search-box::part(submit-button){
    background-color: orangered;
  }
</style>

Elements that are outside of the shadow DOM can be styled generically:

<style>
  atomic-facet-manager {
    padding-top: 13px;
  }
  atomic-result-list {
    display: block;
    margin-top: 10px;
  }
  <!--- ... --->
</style>

You can also define styling constants or modify the constants that Atomic uses:

<style>
  :root {
    --atomic-primary: blue;
    --atomic-secondary: blue;
    --atomic-separator: " - ";
  }
  <!--- ... --->
</style>

For the overarching layout of your components in your search interface, we recommend using a CSS grid:

<head>
  <!--- ... --->
  <style>
    .interface-container {
      width: 100%;
      max-width: 1250px;
      margin: 0 auto;
      display: grid;
      grid-template-columns: 25% 1fr;
      gap: 20px;
    }
    .search-box-item {
      grid-column-start: 2;
    }
    .footer-item {
      grid-column-start: 2;
      grid-row-start: 3;
    }
    <!--- ... --->
  </style>
</head>
<body>
  <atomic-search-interface>
    <div class="interface-container">
      <atomic-search-box class="search-box-item"></atomic-search-box>
      <!--- ... --->
      <div class="footer-item">
        <atomic-pager></atomic-pager>
        <atomic-results-per-page></atomic-results-per-page>
      </div>
    </div>
  </atomic-search-interface>
</body>

Create Result Templates

Result templates determine the format of the individual query results in a search interface. When a query is successful, each result is rendered according to the first template whose condition is satisfied by that result.

Atomic currently provides one default template for all result types. More will be added in the future.

You can also create your own result templates as demonstrated in this example:

<atomic-result-list fields-to-include="filetype"> (1)
  <atomic-result-template id="demoTemplate">
    <template>
      <div id="title">
        <a href="{{clickUri}}"><h3>{{title}}</h3></a>
      </div>
      <div>
        <atomic-result-value value="excerpt"></atomic-result-value>
      </div>
      <div id="type">
        <atomic-result-value value="filetype"></atomic-result-value>
      </div>
    </template>
  </atomic-result-template>
</atomic-result-list>
1 Specifies which fields to fetch in search requests in addition to the default ones.

The mustMatch and mustNotMatch conditions allow you to apply your result template only to target result items. For example, the following template only applies to items whose filetype is video:

<atomic-result-template id="videoTemplate" must-match-filetype="video">
  <!--- ... --->
</atomic-result-template>

It’s also possible to set more advanced conditions with JavaScript. For example, the following template only applies to items whose title contains singapore:

<atomic-result-template id="singaporeTitle">
  <script>
    document.querySelector('atomic-result-template#singaporeTitle').conditions = [
      (result) => /singapore/i.test(result.title),
    ];
  </script>
  <template>
    <!--- ... --->
  </template>
</atomic-result-template>

Style Your Result Templates

You can style your result templates locally by using style tags inside of them:

<atomic-result-list>
  <atomic-result-template>
    <template>
      <style>
        h3 {
          color: blue;
        }
      </style>
      <h3><atomic-result-link></atomic-result-link></h3>
      <!--- ... --->
    </template>
  </atomic-result-template>
</atomic-result-list>
Recommended Articles