Use and create custom components

This is for:

Developer

Coveo Atomic components fulfill most use cases, follow best UX practices, and are visually customizable. However, you may sometimes need more features, further visual customization, or a different behavior altogether. In such cases, we recommend that you build your own custom components using Stencil, which is the same toolchain we used.

Before creating your own custom component, we recommend that you check out the custom component search page. This page lets you browse custom components created by the Coveo developer community.

Note

The content of the custom component search page is intended for reference only and doesn’t fall under Coveo’s support obligations nor constitute official technical documentation. It’s provided on an as-is basis, and Coveo can’t guarantee its accuracy or reliability. Users should exercise caution and assess its suitability for their specific needs.

Although these components aren’t supported by Coveo, they can still save you a lot of time. If you find a component that fits your needs, you can include it in the target page.

If you find no existing component, create your own and optionally publish it to npm for others users' benefit.

Use a published custom component

All published custom components can be found in the custom component search page. To use such a component in your project, copy the unpkg link of the target component by clicking its COPY UNPKG button. You should have a string such as the following in your clipboard:

<!-- Include the following script in the <head> of the page -->
<script type="module" src="https://unpkg.com/custom-component-name"></script>

<!-- Add the following tag inside the atomic-search-interface -->
<custom-component-name></custom-component-name>

As written in the code comments, include the <script> in the head of your page and the custom component tag inside your atomic-search-interface.

Create a custom component

If no published custom component fits your needs, you need to create your own.

We strongly recommend that you use Stencil to create your custom component, as it’s the toolchain with which we built Atomic itself. The Coveo CLI provides two paths to help you do so:

  1. You have already created your Atomic application from scratch using the Coveo CLI (using either coveo ui:create:atomic or coveo atomic:init --type=app <PROJECT_NAME>) and you don’t need to create many complex custom components. In this case, you can use the sample custom components provided by the Coveo CLI in your application by default and craft them into your own custom components.

  2. You’ve created your Atomic application without the Coveo CLI, or you want to create many complex custom components, and perhaps even share them with others. In this case, use the Coveo CLI atomic:component command to create new starter components. Optionally, if you want to create many or complex custom components, we recommend that you use the coveo atomic:init --type=lib <PROJECT_NAME> command first to create a component library before creating components themselves. The library makes it easier to manage and deploy several complex components.

This article will focus on the second possibility. You can learn more about the first one in the Create a Custom Coveo Atomic Component tutorial on Coveo Level Up.

Provided that you’re working in an npm project or in an empty folder, the Coveo CLI atomic:component command generates the necessary files and configurations for you to start working on your custom component instantly. Upon successfully creating your component project, the Coveo CLI will print something similar to the following:

? What kind of component do you want to scaffold? result
✔ Project configured

  We suggest that you begin by typing:

  $ cd my-custom-component
  $ npm install
  $ npm start

  $ npm start
    Starts the development server.

  $ npm run build
    Builds your project in production mode.

  Happy coding!

You’ll find something like the following structure in your working directory:

.
├── package.json
├── readme.md
├── src
│   ├── components
│   │   └── my-custom-component
│   │       ├── package.json
│   │       ├── src
│   │       │   ├── my-custom-component.css
│   │       │   └── my-custom-component.tsx
│   │       ├── stencil.config.ts
│   │       └── tsconfig.json
│   ├── html.d.ts
│   └── pages
│       ├── index.css
│       ├── index.html
│       └── index.ts
├── stencil.config.ts
└── tsconfig.json

You’ll find the source code of your custom component in a file such as src/components/my-custom-component/my-custom-component.tsx.

import { Component } from "@stencil/core";
import { ... } from "@coveo/atomic";
import { ... } from "@coveo/headless";

@Component({
  tag: "my-custom-component",
  styleUrl: "my-custom-component.css",
  shadow: true,
})
export class MyCustomComponent {
  // ...

  public async connectedCallback() {
    // ...
  }

  public disconnectedCallback() {
    // ...
  }

  public render() {
    // ...
  }
}

The details of how to use that custom component will depend on the specifics of your project, but the basic idea is that building the custom component project generates an esm.js file (for example, /build/my-custom-components.esm.js) that you can import and use in the target file. For example:

<head>
  <!-- ... -->
  <script type="module" src="/build/my-custom-components.esm.js"></script>
</head>
<body>
  <!-- ... -->
  <atomic-layout-section section="pagination">
    <my-custom-component></my-custom-component>
  </atomic-layout-section>
  <!-- ... -->
<body>

Start from this to craft your own custom component. You’ll need to be familiar with Headless and Stencil, which Atomic is based on. For an introduction, consult the following resources:

Publish your custom component

While you could continue using your custom component in your own project, we suggest that you publish it to npm so it can help other Coveo Atomic developers. That said, to publish and share your custom Atomic component with others, it must comply with certain requirements.

Required package.json fields

If you’ve created a project with the Coveo CLI using the coveo atomic:component command, you should find a project with the following structure in your current working directory:

src/components/my-custom-component/
├── package.json
├── src
│   ├── my-custom-component.css
│   └── my-custom-component.tsx
├── stencil.config.ts
└── tsconfig.json

As you can see, the project includes a pre-generated package.json file. It pre-populates some required fields, but you need to manually populate some as well.

description

Explains the purpose of your component.

"Adds category suggestions in the search box"

homepage

Points to the home page of your custom component project.

"https://github.com/Coveo-Turbo/PS-Atomic-Components/tree/main/src/components/search-box-category-suggestions"

unpkg (pre-populated)

This custom field points to the .esm.js file of your custom component. By default, it’s located inside the dist/ folder once the custom component has been built. However, if you change the output targets of your builds, make sure to update the unpkg value accordingly.

"dist/my-custom-components/my-custom-components.esm.js"

keywords (prepopulated)

This array must include coveo-atomic-component, so your component can be indexed by the Coveo Platform and listed in the custom component search page. You can add more keywords.

["coveo-atomic-component"]

Readme

Make sure to include a readme.md file in the component directory, at the same location as the package.json. The readme file should explain the purpose of your component as well as configuration and usage instructions, if needed.

src/components/my-custom-component/
├── package.json
├── readme.md
├── src
├── stencil.config.ts
└── tsconfig.json

Component name uniformity

If you’ve created your component with the Coveo CLI and haven’t changed its name in its .tsx file or in the package.json file, the name should be uniform. If there’s a mismatch, however, you’ll see a warning such as the following until you fix it.

Component tag name from your .tsx file does not match the \`elementName\` property defined in your component's package.json file. Make sure both values are identical

The following examples show the correct naming configuration.

src/components/my-custom-component/src/my-custom-component.tsx:

@Component({
  tag: 'my-custom-component',
  // ...
})
// ...

src/components/my-custom-component/package.json:

{
  ...
  "elementName": "my-custom-component",
  ...
}

Tests (optional)

Adding tests to your custom component will improve your component quality and prevent potential errors. See Jest - Getting Started.

TypeScript (optional)

TypeScript is a strongly typed superset of JavaScript that can help you catch errors and improve the quality of your code. By using TypeScript, you can catch errors at compile-time rather than at runtime, saving you time and effort in debugging.

Publication

To learn how to publish your component on npm, see Contributing packages to the registry. The Coveo Platform scans npm projects on a recurring schedule. After a certain delay, the Coveo Platform will therefore find and index your custom component. It will then appear on the custom component search page.