Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/atomic-react/src/components/commerce/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
AtomicIcon as LitAtomicIcon,
AtomicInsightGenerateAnswerButton as LitAtomicInsightGenerateAnswerButton,
AtomicInsightInterface as LitAtomicInsightInterface,
AtomicInsightResultTemplate as LitAtomicInsightResultTemplate,
AtomicLayoutSection as LitAtomicLayoutSection,
AtomicNumericRange as LitAtomicNumericRange,
AtomicProduct as LitAtomicProduct,
Expand Down Expand Up @@ -251,6 +252,12 @@ export const AtomicInsightInterface = createComponent({
elementClass: LitAtomicInsightInterface,
});

export const AtomicInsightResultTemplate = createComponent({
tagName: 'atomic-insight-result-template',
react: React,
elementClass: LitAtomicInsightResultTemplate,
});

export const AtomicLayoutSection = createComponent({
tagName: 'atomic-layout-section',
react: React,
Expand Down
7 changes: 7 additions & 0 deletions packages/atomic-react/src/components/search/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
AtomicIcon as LitAtomicIcon,
AtomicInsightGenerateAnswerButton as LitAtomicInsightGenerateAnswerButton,
AtomicInsightInterface as LitAtomicInsightInterface,
AtomicInsightResultTemplate as LitAtomicInsightResultTemplate,
AtomicLayoutSection as LitAtomicLayoutSection,
AtomicLoadMoreResults as LitAtomicLoadMoreResults,
AtomicNoResults as LitAtomicNoResults,
Expand Down Expand Up @@ -207,6 +208,12 @@ export const AtomicInsightInterface = createComponent({
elementClass: LitAtomicInsightInterface,
});

export const AtomicInsightResultTemplate = createComponent({
tagName: 'atomic-insight-result-template',
react: React,
elementClass: LitAtomicInsightResultTemplate,
});

export const AtomicLayoutSection = createComponent({
tagName: 'atomic-layout-section',
react: React,
Expand Down
73 changes: 2 additions & 71 deletions packages/atomic/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { DateFilterRange, DateRangeRequest, FacetResultsMustMatch, GeneratedAnswer, GeneratedAnswerCitation, InlineLink, InteractiveCitation, RangeFacetSortCriterion, Result, ResultTemplate, ResultTemplateCondition } from "@coveo/headless";
import { FacetSortCriterion as InsightFacetSortCriterion, FoldedResult as InsightFoldedResult, InteractiveResult as InsightInteractiveResult, RangeFacetRangeAlgorithm as InsightRangeFacetRangeAlgorithm, RangeFacetSortCriterion as InsightRangeFacetSortCriterion, Result as InsightResult, ResultTemplate as InsightResultTemplate, ResultTemplateCondition as InsightResultTemplateCondition, UserAction as IUserAction } from "@coveo/headless/insight";
import { FacetSortCriterion as InsightFacetSortCriterion, FoldedResult as InsightFoldedResult, InteractiveResult as InsightInteractiveResult, RangeFacetRangeAlgorithm as InsightRangeFacetRangeAlgorithm, RangeFacetSortCriterion as InsightRangeFacetSortCriterion, Result as InsightResult, UserAction as IUserAction } from "@coveo/headless/insight";
import { ItemDisplayBasicLayout, ItemDisplayDensity, ItemDisplayImageSize, ItemDisplayLayout } from "./components/common/layout/display-options";
import { ItemRenderingFunction } from "./components/common/item-list/stencil-item-list-common";
import { NumberInputType } from "./components/common/facets/facet-number-input/number-input-type";
Expand All @@ -20,7 +20,7 @@ import { AnyBindings } from "./components/common/interface/bindings";
import { i18n } from "i18next";
import { SearchBoxSuggestionElement } from "./components/common/suggestions/suggestions-types";
export { DateFilterRange, DateRangeRequest, FacetResultsMustMatch, GeneratedAnswer, GeneratedAnswerCitation, InlineLink, InteractiveCitation, RangeFacetSortCriterion, Result, ResultTemplate, ResultTemplateCondition } from "@coveo/headless";
export { FacetSortCriterion as InsightFacetSortCriterion, FoldedResult as InsightFoldedResult, InteractiveResult as InsightInteractiveResult, RangeFacetRangeAlgorithm as InsightRangeFacetRangeAlgorithm, RangeFacetSortCriterion as InsightRangeFacetSortCriterion, Result as InsightResult, ResultTemplate as InsightResultTemplate, ResultTemplateCondition as InsightResultTemplateCondition, UserAction as IUserAction } from "@coveo/headless/insight";
export { FacetSortCriterion as InsightFacetSortCriterion, FoldedResult as InsightFoldedResult, InteractiveResult as InsightInteractiveResult, RangeFacetRangeAlgorithm as InsightRangeFacetRangeAlgorithm, RangeFacetSortCriterion as InsightRangeFacetSortCriterion, Result as InsightResult, UserAction as IUserAction } from "@coveo/headless/insight";
export { ItemDisplayBasicLayout, ItemDisplayDensity, ItemDisplayImageSize, ItemDisplayLayout } from "./components/common/layout/display-options";
export { ItemRenderingFunction } from "./components/common/item-list/stencil-item-list-common";
export { NumberInputType } from "./components/common/facets/facet-number-input/number-input-type";
Expand Down Expand Up @@ -397,38 +397,6 @@ export namespace Components {
*/
"sandbox": string;
}
interface AtomicInsightResultTemplate {
/**
* A function that must return true on results for the result template to apply. Set programmatically before initialization, not via attribute. For example, the following targets a template and sets a condition to make it apply only to results whose `title` contains `singapore`: `document.querySelector('#target-template').conditions = [(result) => /singapore/i.test(result.title)];`
*/
"conditions": InsightResultTemplateCondition[];
/**
* Gets the appropriate result template based on conditions applied.
*/
"getTemplate": () => Promise<InsightResultTemplate<DocumentFragment> | null>;
/**
* The field that, when defined on a result item, would allow the template to be applied. For example, a template with the following attribute only applies to result items whose `filetype` and `sourcetype` fields are defined: `if-defined="filetype,sourcetype"`
*/
"ifDefined"?: string;
/**
* The field that, when defined on a result item, would prevent the template from being applied. For example, a template with the following attribute only applies to result items whose `filetype` and `sourcetype` fields are NOT defined: `if-not-defined="filetype,sourcetype"`
*/
"ifNotDefined"?: string;
/**
* The field and values that define which result items the condition must be applied to. For example, a template with the following attribute only applies to result items whose `filetype` is `lithiummessage` or `YouTubePlaylist`: `must-match-filetype="lithiummessage,YouTubePlaylist"`
*/
"mustMatch": Record<
string,
string[]
>;
/**
* The field and values that define which result items the condition must not be applied to. For example, a template with the following attribute only applies to result items whose `filetype` is not `lithiummessage`: `must-not-match-filetype="lithiummessage"`
*/
"mustNotMatch": Record<
string,
string[]
>;
}
interface AtomicInsightSearchBox {
/**
* Whether to prevent the user from triggering a search from the component. Perfect for use cases where you need to disable the search conditionally, like when the input is empty.
Expand Down Expand Up @@ -1343,12 +1311,6 @@ declare global {
prototype: HTMLAtomicInsightResultQuickviewActionElement;
new (): HTMLAtomicInsightResultQuickviewActionElement;
};
interface HTMLAtomicInsightResultTemplateElement extends Components.AtomicInsightResultTemplate, HTMLStencilElement {
}
var HTMLAtomicInsightResultTemplateElement: {
prototype: HTMLAtomicInsightResultTemplateElement;
new (): HTMLAtomicInsightResultTemplateElement;
};
interface HTMLAtomicInsightSearchBoxElement extends Components.AtomicInsightSearchBox, HTMLStencilElement {
}
var HTMLAtomicInsightSearchBoxElement: {
Expand Down Expand Up @@ -1789,7 +1751,6 @@ declare global {
"atomic-insight-result-children-template": HTMLAtomicInsightResultChildrenTemplateElement;
"atomic-insight-result-list": HTMLAtomicInsightResultListElement;
"atomic-insight-result-quickview-action": HTMLAtomicInsightResultQuickviewActionElement;
"atomic-insight-result-template": HTMLAtomicInsightResultTemplateElement;
"atomic-insight-search-box": HTMLAtomicInsightSearchBoxElement;
"atomic-insight-smart-snippet": HTMLAtomicInsightSmartSnippetElement;
"atomic-insight-smart-snippet-feedback-modal": HTMLAtomicInsightSmartSnippetFeedbackModalElement;
Expand Down Expand Up @@ -2181,34 +2142,6 @@ declare namespace LocalJSX {
*/
"sandbox"?: string;
}
interface AtomicInsightResultTemplate {
/**
* A function that must return true on results for the result template to apply. Set programmatically before initialization, not via attribute. For example, the following targets a template and sets a condition to make it apply only to results whose `title` contains `singapore`: `document.querySelector('#target-template').conditions = [(result) => /singapore/i.test(result.title)];`
*/
"conditions"?: InsightResultTemplateCondition[];
/**
* The field that, when defined on a result item, would allow the template to be applied. For example, a template with the following attribute only applies to result items whose `filetype` and `sourcetype` fields are defined: `if-defined="filetype,sourcetype"`
*/
"ifDefined"?: string;
/**
* The field that, when defined on a result item, would prevent the template from being applied. For example, a template with the following attribute only applies to result items whose `filetype` and `sourcetype` fields are NOT defined: `if-not-defined="filetype,sourcetype"`
*/
"ifNotDefined"?: string;
/**
* The field and values that define which result items the condition must be applied to. For example, a template with the following attribute only applies to result items whose `filetype` is `lithiummessage` or `YouTubePlaylist`: `must-match-filetype="lithiummessage,YouTubePlaylist"`
*/
"mustMatch"?: Record<
string,
string[]
>;
/**
* The field and values that define which result items the condition must not be applied to. For example, a template with the following attribute only applies to result items whose `filetype` is not `lithiummessage`: `must-not-match-filetype="lithiummessage"`
*/
"mustNotMatch"?: Record<
string,
string[]
>;
}
interface AtomicInsightSearchBox {
/**
* Whether to prevent the user from triggering a search from the component. Perfect for use cases where you need to disable the search conditionally, like when the input is empty.
Expand Down Expand Up @@ -2878,7 +2811,6 @@ declare namespace LocalJSX {
"atomic-insight-result-children-template": AtomicInsightResultChildrenTemplate;
"atomic-insight-result-list": AtomicInsightResultList;
"atomic-insight-result-quickview-action": AtomicInsightResultQuickviewAction;
"atomic-insight-result-template": AtomicInsightResultTemplate;
"atomic-insight-search-box": AtomicInsightSearchBox;
"atomic-insight-smart-snippet": AtomicInsightSmartSnippet;
"atomic-insight-smart-snippet-feedback-modal": AtomicInsightSmartSnippetFeedbackModal;
Expand Down Expand Up @@ -2949,7 +2881,6 @@ declare module "@stencil/core" {
"atomic-insight-result-children-template": LocalJSX.AtomicInsightResultChildrenTemplate & JSXBase.HTMLAttributes<HTMLAtomicInsightResultChildrenTemplateElement>;
"atomic-insight-result-list": LocalJSX.AtomicInsightResultList & JSXBase.HTMLAttributes<HTMLAtomicInsightResultListElement>;
"atomic-insight-result-quickview-action": LocalJSX.AtomicInsightResultQuickviewAction & JSXBase.HTMLAttributes<HTMLAtomicInsightResultQuickviewActionElement>;
"atomic-insight-result-template": LocalJSX.AtomicInsightResultTemplate & JSXBase.HTMLAttributes<HTMLAtomicInsightResultTemplateElement>;
"atomic-insight-search-box": LocalJSX.AtomicInsightSearchBox & JSXBase.HTMLAttributes<HTMLAtomicInsightSearchBoxElement>;
"atomic-insight-smart-snippet": LocalJSX.AtomicInsightSmartSnippet & JSXBase.HTMLAttributes<HTMLAtomicInsightSmartSnippetElement>;
"atomic-insight-smart-snippet-feedback-modal": LocalJSX.AtomicInsightSmartSnippetFeedbackModal & JSXBase.HTMLAttributes<HTMLAtomicInsightSmartSnippetFeedbackModalElement>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { Meta } from '@storybook/addon-docs/blocks';
import * as AtomicInsightResultTemplateStories from './atomic-insight-result-template.new.stories';
import { AtomicDocTemplate } from '@/storybook-utils/documentation/atomic-doc-template';

<Meta of={AtomicInsightResultTemplateStories} />

<AtomicDocTemplate
stories={AtomicInsightResultTemplateStories}
defaultStory="Default"
githubPath="insight/atomic-insight-result-template/atomic-insight-result-template.ts"
tagName="atomic-insight-result-template"
className="AtomicInsightResultTemplate"
>

This component defines the UI display of your search results within an Insight interface.
A `template` element must be the child of an `atomic-insight-result-template`. Furthermore, an `atomic-insight-result-list` or `atomic-insight-folded-result-list` must be the parent of each `atomic-insight-result-template`.
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation uses inconsistent terminology. Throughout this file, "result items" is used (lines 16, 42, 50, 54, etc.), but the search component version uses "results" for consistency. The MDX documentation should use "results" instead of "result items" to maintain consistency with atomic-result-template documentation.

Copilot uses AI. Check for mistakes.

**Note:** Any `<script>` tags that are defined inside a `<template>` element will not be executed when the results are being rendered.

Example using the `atomic-insight-result-list`:

```html
<atomic-insight-interface>
<atomic-insight-result-list>
<atomic-insight-result-template>
<template>
<atomic-result-section-visual>
<atomic-result-image field="ytthumbnailurl" fallback="https://picsum.photos/seed/picsum/350"></atomic-result-image>
</atomic-result-section-visual>

<atomic-result-section-badges>
<atomic-field-condition must-match-sourcetype="YouTube">
<atomic-result-badge
label="YouTube"
class="youtube-badge"
></atomic-result-badge>
</atomic-field-condition>
</atomic-result-section-badges>

<atomic-result-section-title>
<atomic-result-link></atomic-result-link>
</atomic-result-section-title>

<atomic-result-section-excerpt>
<atomic-result-text field="excerpt"></atomic-result-text>
</atomic-result-section-excerpt>

<atomic-result-section-bottom-metadata>
<atomic-result-fields-list>
<atomic-field-condition class="field" if-defined="source">
<span class="field-label">
<atomic-text value="source"></atomic-text>:
</span>
<atomic-result-text field="source"></atomic-result-text>
</atomic-field-condition>

<atomic-field-condition class="field" if-defined="author">
<span class="field-label">
<atomic-text value="author"></atomic-text>:
</span>
<atomic-result-text field="author"></atomic-result-text>
</atomic-field-condition>

<atomic-field-condition class="field" if-defined="date">
<span class="field-label">
<atomic-text value="date"></atomic-text>:
</span>
<atomic-result-date></atomic-result-date>
</atomic-field-condition>
</atomic-result-fields-list>
</atomic-result-section-bottom-metadata>
</template>
</atomic-insight-result-template>
</atomic-insight-result-list>
</atomic-insight-interface>
```

## Template Conditions

You can use conditions to display different templates based on result properties. You can specify as many `must-match-*` and `must-not-match-*` attributes as you want on a template, each targeting a different field. Each attribute can accept multiple comma-separated values.

**Comma represents OR:** Within a single attribute, comma-separated values represent a logical OR. For example, `must-match-sourcetype="YouTube,Salesforce"` means the sourcetype must be YouTube OR Salesforce.

**Multiple attributes represent AND:** All conditions from different attributes must be met (logical AND) for the template to apply to a result.

If you set both `must-match-*` and `must-not-match-*` for the same field and there is any overlap in values, the template will be ignored (it will never match any result).

**Order of declaration matters:** The first template whose conditions are met will be applied. If a default template (without conditions) is declared first, it will apply to all results, even if other templates with conditions are declared later.

### Examples

```html
<!-- Template applies if sourcetype is YouTube or Salesforce, and language is NOT fr -->
<atomic-insight-result-template
must-match-sourcetype="YouTube,Salesforce"
must-not-match-language="fr"
>
<template>
<!-- ... -->
</template>
</atomic-insight-result-template>

<!-- This template will never apply, because the same value is required and forbidden -->
<atomic-insight-result-template
must-match-sourcetype="YouTube"
must-not-match-sourcetype="YouTube"
>
<template>
<!-- ... -->
</template>
</atomic-insight-result-template>
```

### Multiple Templates Example

```html
<atomic-insight-result-list>
<!-- Template for YouTube videos -->
<atomic-insight-result-template must-match-sourcetype="YouTube">
<template>
<atomic-result-section-visual>
<atomic-result-image field="ytthumbnailurl"></atomic-result-image>
</atomic-result-section-visual>
<atomic-result-section-title>
<atomic-result-link></atomic-result-link>
</atomic-result-section-title>
<atomic-result-section-excerpt>
<atomic-result-text field="excerpt"></atomic-result-text>
</atomic-result-section-excerpt>
</template>
</atomic-insight-result-template>

<!-- Default template for all other results -->
<atomic-insight-result-template>
<template>
<atomic-result-section-title>
<atomic-result-link></atomic-result-link>
</atomic-result-section-title>
<atomic-result-section-excerpt>
<atomic-result-text field="excerpt"></atomic-result-text>
</atomic-result-section-excerpt>
</template>
</atomic-insight-result-template>
</atomic-insight-result-list>
```

</AtomicDocTemplate>
Loading