Skip to content
Closed
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
71 changes: 4 additions & 67 deletions packages/atomic/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
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 { 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";
import { InsightStore } from "./components/insight/atomic-insight-interface/store";
import { ItemDisplayBasicLayout, ItemDisplayDensity, ItemDisplayImageSize, ItemDisplayLayout } from "./components/common/layout/display-options";
import { Actions, InsightResultActionClickedEvent } from "./components/insight/atomic-insight-result-action/atomic-insight-result-action";
import { InsightResultAttachToCaseEvent } from "./components/insight/atomic-insight-result-attach-to-case-action/atomic-insight-result-attach-to-case-action";
import { ItemRenderingFunction } from "./components/common/item-list/stencil-item-list-common";
import { InteractiveResult as RecsInteractiveResult, Result as RecsResult, ResultTemplate as RecsResultTemplate, ResultTemplateCondition as RecsResultTemplateCondition } from "@coveo/headless/recommendation";
import { RecsStore } from "./components/recommendations/atomic-recs-interface/store";
import { RedirectionPayload } from "./components/common/search-box/redirection-payload";
Expand All @@ -21,12 +21,12 @@ 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 { 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";
export { InsightStore } from "./components/insight/atomic-insight-interface/store";
export { ItemDisplayBasicLayout, ItemDisplayDensity, ItemDisplayImageSize, ItemDisplayLayout } from "./components/common/layout/display-options";
export { Actions, InsightResultActionClickedEvent } from "./components/insight/atomic-insight-result-action/atomic-insight-result-action";
export { InsightResultAttachToCaseEvent } from "./components/insight/atomic-insight-result-attach-to-case-action/atomic-insight-result-attach-to-case-action";
export { ItemRenderingFunction } from "./components/common/item-list/stencil-item-list-common";
export { InteractiveResult as RecsInteractiveResult, Result as RecsResult, ResultTemplate as RecsResultTemplate, ResultTemplateCondition as RecsResultTemplateCondition } from "@coveo/headless/recommendation";
export { RecsStore } from "./components/recommendations/atomic-recs-interface/store";
export { RedirectionPayload } from "./components/common/search-box/redirection-payload";
Expand Down Expand Up @@ -131,35 +131,6 @@ export namespace Components {
*/
"sortCriteria": InsightFacetSortCriterion;
}
interface AtomicInsightFoldedResultList {
/**
* The name of the field that uniquely identifies a result within a collection.
* @defaultValue `foldingchild`
*/
"childField"?: string;
/**
* The name of the field on which to do the folding. The folded result list component will use the values of this field to resolve the collections of result items.
* @defaultValue `foldingcollection`
*/
"collectionField"?: string;
/**
* The spacing of various elements in the result list, including the gap between results, the gap between parts of a result, and the font sizes of different parts in a result.
*/
"density": ItemDisplayDensity;
/**
* The expected size of the image displayed in the results.
*/
"imageSize": ItemDisplayImageSize;
/**
* The name of the field that determines whether a certain result is a top result containing other child results within a collection.
* @defaultValue `foldingparent`
*/
"parentField"?: string;
/**
* Sets a rendering function to bypass the standard HTML template mechanism for rendering results. You can use this function while working with web frameworks that don't use plain HTML syntax such as React, Angular, or Vue. Do not use this method if you integrate Atomic in a plain HTML deployment.
*/
"setRenderFunction": (resultRenderingFunction: ItemRenderingFunction) => Promise<void>;
}
interface AtomicInsightFullSearchButton {
"tooltip": string;
}
Expand Down Expand Up @@ -1183,12 +1154,6 @@ declare global {
prototype: HTMLAtomicInsightFacetElement;
new (): HTMLAtomicInsightFacetElement;
};
interface HTMLAtomicInsightFoldedResultListElement extends Components.AtomicInsightFoldedResultList, HTMLStencilElement {
}
var HTMLAtomicInsightFoldedResultListElement: {
prototype: HTMLAtomicInsightFoldedResultListElement;
new (): HTMLAtomicInsightFoldedResultListElement;
};
interface HTMLAtomicInsightFullSearchButtonElement extends Components.AtomicInsightFullSearchButton, HTMLStencilElement {
}
var HTMLAtomicInsightFullSearchButtonElement: {
Expand Down Expand Up @@ -1768,7 +1733,6 @@ declare global {
"atomic-generated-answer-feedback-modal": HTMLAtomicGeneratedAnswerFeedbackModalElement;
"atomic-insight-edit-toggle": HTMLAtomicInsightEditToggleElement;
"atomic-insight-facet": HTMLAtomicInsightFacetElement;
"atomic-insight-folded-result-list": HTMLAtomicInsightFoldedResultListElement;
"atomic-insight-full-search-button": HTMLAtomicInsightFullSearchButtonElement;
"atomic-insight-generated-answer": HTMLAtomicInsightGeneratedAnswerElement;
"atomic-insight-history-toggle": HTMLAtomicInsightHistoryToggleElement;
Expand Down Expand Up @@ -1924,31 +1888,6 @@ declare namespace LocalJSX {
*/
"sortCriteria"?: InsightFacetSortCriterion;
}
interface AtomicInsightFoldedResultList {
/**
* The name of the field that uniquely identifies a result within a collection.
* @defaultValue `foldingchild`
*/
"childField"?: string;
/**
* The name of the field on which to do the folding. The folded result list component will use the values of this field to resolve the collections of result items.
* @defaultValue `foldingcollection`
*/
"collectionField"?: string;
/**
* The spacing of various elements in the result list, including the gap between results, the gap between parts of a result, and the font sizes of different parts in a result.
*/
"density"?: ItemDisplayDensity;
/**
* The expected size of the image displayed in the results.
*/
"imageSize"?: ItemDisplayImageSize;
/**
* The name of the field that determines whether a certain result is a top result containing other child results within a collection.
* @defaultValue `foldingparent`
*/
"parentField"?: string;
}
interface AtomicInsightFullSearchButton {
"tooltip"?: string;
}
Expand Down Expand Up @@ -2857,7 +2796,6 @@ declare namespace LocalJSX {
"atomic-generated-answer-feedback-modal": AtomicGeneratedAnswerFeedbackModal;
"atomic-insight-edit-toggle": AtomicInsightEditToggle;
"atomic-insight-facet": AtomicInsightFacet;
"atomic-insight-folded-result-list": AtomicInsightFoldedResultList;
"atomic-insight-full-search-button": AtomicInsightFullSearchButton;
"atomic-insight-generated-answer": AtomicInsightGeneratedAnswer;
"atomic-insight-history-toggle": AtomicInsightHistoryToggle;
Expand Down Expand Up @@ -2928,7 +2866,6 @@ declare module "@stencil/core" {
"atomic-generated-answer-feedback-modal": LocalJSX.AtomicGeneratedAnswerFeedbackModal & JSXBase.HTMLAttributes<HTMLAtomicGeneratedAnswerFeedbackModalElement>;
"atomic-insight-edit-toggle": LocalJSX.AtomicInsightEditToggle & JSXBase.HTMLAttributes<HTMLAtomicInsightEditToggleElement>;
"atomic-insight-facet": LocalJSX.AtomicInsightFacet & JSXBase.HTMLAttributes<HTMLAtomicInsightFacetElement>;
"atomic-insight-folded-result-list": LocalJSX.AtomicInsightFoldedResultList & JSXBase.HTMLAttributes<HTMLAtomicInsightFoldedResultListElement>;
"atomic-insight-full-search-button": LocalJSX.AtomicInsightFullSearchButton & JSXBase.HTMLAttributes<HTMLAtomicInsightFullSearchButtonElement>;
"atomic-insight-generated-answer": LocalJSX.AtomicInsightGeneratedAnswer & JSXBase.HTMLAttributes<HTMLAtomicInsightGeneratedAnswerElement>;
"atomic-insight-history-toggle": LocalJSX.AtomicInsightHistoryToggle & JSXBase.HTMLAttributes<HTMLAtomicInsightHistoryToggleElement>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Meta } from '@storybook/addon-docs/blocks';
import * as AtomicInsightFoldedResultListStories from './atomic-insight-folded-result-list.new.stories';
import { AtomicDocTemplate } from '@/storybook-utils/documentation/atomic-doc-template';

<Meta of={AtomicInsightFoldedResultListStories} />

<AtomicDocTemplate
stories={AtomicInsightFoldedResultListStories}
githubPath="insight/result-lists/atomic-insight-folded-result-list/atomic-insight-folded-result-list.ts"
tagName="atomic-insight-folded-result-list"
className="AtomicInsightFoldedResultList"
>

This component is typically placed within an Insight interface to display folded query results. Folded results group related documents together, such as case threads or support article versions.

```html
<atomic-insight-interface>
...
<atomic-insight-layout>
...
<atomic-insight-folded-result-list></atomic-insight-folded-result-list>
</atomic-insight-layout>
</atomic-insight-interface>
```

## Defining Result Templates

You can define custom templates for how results and their children are displayed:

```html
<atomic-insight-folded-result-list>
<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>
<atomic-result-section-children>
<atomic-result-children>
<atomic-result-children-template>
<template>
<atomic-result-section-title>
<atomic-result-link></atomic-result-link>
</atomic-result-section-title>
</template>
</atomic-result-children-template>
</atomic-result-children>
</atomic-result-section-children>
</template>
</atomic-insight-result-template>
</atomic-insight-folded-result-list>
```

For more information on Result Folding, see [Result Folding](https://docs.coveo.com/en/1884).

</AtomicDocTemplate>
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/** biome-ignore-all lint/suspicious/noExplicitAny: <> */

import type {Meta, StoryObj as Story} from '@storybook/web-components-vite';
import {getStorybookHelpers} from '@wc-toolkit/storybook-helpers';
import {MockInsightApi} from '@/storybook-utils/api/insight/mock';
import {baseFoldedResponse} from '@/storybook-utils/api/insight/search-response';
import {parameters} from '@/storybook-utils/common/common-meta-parameters';
import {wrapInInsightInterface} from '@/storybook-utils/insight/insight-interface-wrapper';

const SLOTS_DEFAULT = `
<atomic-insight-result-template>
<template>
<atomic-result-section-visual>
<atomic-result-image class="icon" fallback="https://picsum.photos/seed/insight/350"></atomic-result-image>
<img src="https://picsum.photos/seed/insight/350" alt="Thumbnail" class="thumbnail" />
</atomic-result-section-visual>
<atomic-result-section-badges>
<atomic-field-condition must-match-sourcetype="KnowledgeBase">
<atomic-result-badge
label="Knowledge Base"
class="kb-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-result-fields-list>
</atomic-result-section-bottom-metadata>
<atomic-result-section-children>
<atomic-result-children image-size="icon">
<atomic-result-children-template>
<template>
<atomic-result-section-visual>
<atomic-result-image class="icon" fallback="https://picsum.photos/seed/insight/350"></atomic-result-image>
<img src="https://picsum.photos/seed/insight/350" alt="Thumbnail" class="thumbnail" />
</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>
<atomic-result-section-bottom-metadata>
<atomic-result-fields-list>
<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="source">
<span class="field-label"
><atomic-text value="source"></atomic-text>:</span
>
<atomic-result-text field="source"></atomic-result-text>
</atomic-field-condition>
</atomic-result-fields-list>
</atomic-result-section-bottom-metadata>
<atomic-result-section-children>
<atomic-result-children inherit-templates>
</atomic-result-children>
</atomic-result-section-children>
</template>
</atomic-result-children-template>
</atomic-result-children>
</atomic-result-section-children>
</template>
</atomic-insight-result-template>
`;

const mockInsightApi = new MockInsightApi();

const {decorator, play} = wrapInInsightInterface();
const {events, args, argTypes, template} = getStorybookHelpers(
'atomic-insight-folded-result-list',
{excludeCategories: ['methods']}
);

const meta: Meta = {
component: 'atomic-insight-folded-result-list',
title: 'Insight/Folded Result List',
id: 'atomic-insight-folded-result-list',
render: (args) => template(args),
decorators: [decorator],
parameters: {
...parameters,
actions: {
handles: events,
},
msw: {handlers: [...mockInsightApi.handlers]},
},
args,
argTypes,
beforeEach: async () => {
mockInsightApi.searchEndpoint.clear();
},
play,
tags: ['!dev'],
};

export default meta;

export const Default: Story = {
args: {
'default-slot': SLOTS_DEFAULT,
},
beforeEach: async () => {
mockInsightApi.searchEndpoint.mockOnce(() => baseFoldedResponse);
mockInsightApi.searchEndpoint.mockOnce(() => {
const results = baseFoldedResponse.results;
results[0]!.childResults.push({
title: 'Security Best Practices',
excerpt: 'Essential security guidelines',
clickUri: 'https://support.example.com/kb/security',
uniqueId: 'kb-security-child',
raw: {
foldingcollection: 'Knowledge Base',
foldingchild: ['security'],
foldingparent: 'kb',
},
});
results[0].totalNumberOfChildResults = 3;
return {
...baseFoldedResponse,
results,
};
});
},
play,
};

export const WithNoResultChildren: Story = {
name: 'With no result children',
args: {
'default-slot': SLOTS_DEFAULT,
},
beforeEach: async () => {
mockInsightApi.searchEndpoint.mockOnce(() => ({
...baseFoldedResponse,
results: [
{
...baseFoldedResponse.results[0],
parentResult: null,
totalNumberOfChildResults: 0,
childResults: [],
},
] as unknown as typeof baseFoldedResponse.results,
}));
},
play,
};

export const WithFewResultChildren: Story = {
name: 'With result children',
args: {
'default-slot': SLOTS_DEFAULT,
},
beforeEach: async () => {
mockInsightApi.searchEndpoint.mockOnce(() => ({
...baseFoldedResponse,
results: [
{
...baseFoldedResponse.results[0]!,
totalNumberOfChildResults: 2,
},
...baseFoldedResponse.results.slice(1),
],
}));
},
play,
};

export const WithMoreResultsAvailableAndNoChildren: Story = {
name: 'With more results available and no children',
args: {
'default-slot': SLOTS_DEFAULT,
},
beforeEach: async () => {
mockInsightApi.searchEndpoint.mockOnce(() => ({
...baseFoldedResponse,
results: [
{
...baseFoldedResponse.results[0]!,
totalNumberOfChildResults: 10,
childResults: [],
},
],
}));
},
play,
};
Loading
Loading