Skip to content

Commit

Permalink
feat(atomic): add tab support for atomic-generated-answer (#4285)
Browse files Browse the repository at this point in the history
This PR allows atomic-generated-answer to be visible/hidden based on the
currently active tab in the tab manager.

https://coveord.atlassian.net/browse/CDX-1557

---------

Co-authored-by: GitHub Actions Bot <>
Co-authored-by: Frederic Beaudoin <[email protected]>
  • Loading branch information
fpbrault and fbeaudoincoveo authored Sep 20, 2024
1 parent bad4ff5 commit 744fb61
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -984,14 +984,14 @@ export declare interface AtomicFormatUnit extends Components.AtomicFormatUnit {}


@ProxyCmp({
inputs: ['collapsible', 'withToggle']
inputs: ['collapsible', 'tabsExcluded', 'tabsIncluded', 'withToggle']
})
@Component({
selector: 'atomic-generated-answer',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['collapsible', 'withToggle'],
inputs: ['collapsible', 'tabsExcluded', 'tabsIncluded', 'withToggle'],
})
export class AtomicGeneratedAnswer {
protected el: HTMLElement;
Expand Down
16 changes: 16 additions & 0 deletions packages/atomic/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,14 @@ export namespace Components {
* @default false
*/
"collapsible"?: boolean;
/**
* The tabs on which this generated answer must not be displayed. This property should not be used at the same time as `tabs-included`. Set this property as a stringified JSON array, e.g., ```html <atomic-generated-answer tabs-excluded='["tabIDA", "tabIDB"]'></atomic-generated-answer> ``` If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer won't be displayed on any of the specified tabs.
*/
"tabsExcluded": string[] | string;
/**
* The tabs on which the generated answer can be displayed. This property should not be used at the same time as `tabs-excluded`. Set this property as a stringified JSON array, e.g., ```html <atomic-generated-answer tabs-included='["tabIDA", "tabIDB"]'></atomic-generated-answer> ``` If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer can only be displayed on the specified tabs.
*/
"tabsIncluded": string[] | string;
/**
* Whether to render a toggle button that lets the user hide or show the answer.
* @default false
Expand Down Expand Up @@ -6987,6 +6995,14 @@ declare namespace LocalJSX {
* @default false
*/
"collapsible"?: boolean;
/**
* The tabs on which this generated answer must not be displayed. This property should not be used at the same time as `tabs-included`. Set this property as a stringified JSON array, e.g., ```html <atomic-generated-answer tabs-excluded='["tabIDA", "tabIDB"]'></atomic-generated-answer> ``` If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer won't be displayed on any of the specified tabs.
*/
"tabsExcluded"?: string[] | string;
/**
* The tabs on which the generated answer can be displayed. This property should not be used at the same time as `tabs-excluded`. Set this property as a stringified JSON array, e.g., ```html <atomic-generated-answer tabs-included='["tabIDA", "tabIDB"]'></atomic-generated-answer> ``` If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer can only be displayed on the specified tabs.
*/
"tabsIncluded"?: string[] | string;
/**
* Whether to render a toggle button that lets the user hide or show the answer.
* @default false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@ import {
GeneratedAnswer,
GeneratedAnswerState,
buildInteractiveCitation,
buildTabManager,
TabManagerState,
TabManager,
} from '@coveo/headless';
import {Component, Element, State, Prop, Watch} from '@stencil/core';
import {Component, Element, State, Prop, Watch, h} from '@stencil/core';
import {AriaLiveRegion} from '../../../utils/accessibility-utils';
import {debounce} from '../../../utils/debounce-utils';
import {
BindStateToController,
InitializableComponent,
InitializeBindings,
} from '../../../utils/initialization-utils';
import {ArrayProp} from '../../../utils/props-utils';
import {shouldDisplayOnCurrentTab} from '../../../utils/tab-utils';
import {GeneratedAnswerCommon} from '../../common/generated-answer/generated-answer-common';
import {Hidden} from '../../common/hidden';
import {Bindings} from '../atomic-search-interface/atomic-search-interface';

/**
Expand Down Expand Up @@ -75,6 +81,12 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
@State()
private searchStatusState!: SearchStatusState;

public tabManager!: TabManager;

@BindStateToController('tabManager')
@State()
public tabManagerState!: TabManagerState;

@State()
public error!: Error;

Expand Down Expand Up @@ -104,6 +116,32 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
*/
@Prop() answerConfigurationId?: string;

/**
* The tabs on which the generated answer can be displayed. This property should not be used at the same time as `tabs-excluded`.
*
* Set this property as a stringified JSON array, e.g.,
* ```html
* <atomic-generated-answer tabs-included='["tabIDA", "tabIDB"]'></atomic-generated-answer>
* ```
* If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer can only be displayed on the specified tabs.
*/
@ArrayProp()
@Prop({reflect: true, mutable: true})
public tabsIncluded: string[] | string = '[]';

/**
* The tabs on which this generated answer must not be displayed. This property should not be used at the same time as `tabs-included`.
*
* Set this property as a stringified JSON array, e.g.,
* ```html
* <atomic-generated-answer tabs-excluded='["tabIDA", "tabIDB"]'></atomic-generated-answer>
* ```
* If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer won't be displayed on any of the specified tabs.
*/
@ArrayProp()
@Prop({reflect: true, mutable: true})
public tabsExcluded: string[] | string = '[]';

@AriaLiveRegion('generated-answer')
protected ariaMessage!: string;

Expand All @@ -112,6 +150,14 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
private maxCollapsedHeight = 250;

public initialize() {
if (
[...this.tabsIncluded].length > 0 &&
[...this.tabsExcluded].length > 0
) {
console.warn(
'Values for both "tabs-included" and "tabs-excluded" have been provided. This could lead to unexpected behaviors.'
);
}
this.generatedAnswerCommon = new GeneratedAnswerCommon({
host: this.host,
withToggle: this.withToggle,
Expand Down Expand Up @@ -150,6 +196,7 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
this.resizeObserver = new ResizeObserver(debouncedAdaptAnswerHeight);
this.resizeObserver.observe(this.host);
}
this.tabManager = buildTabManager(this.bindings.engine);
}

@Watch('generatedAnswerState')
Expand Down Expand Up @@ -253,7 +300,36 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
}
}

@Watch('tabManagerState')
watchTabManagerState(
newValue: {activeTab: string},
oldValue: {activeTab: string}
) {
if (newValue?.activeTab !== oldValue?.activeTab) {
if (
!shouldDisplayOnCurrentTab(
[...this.tabsIncluded],
[...this.tabsExcluded],
this.tabManagerState?.activeTab
)
) {
this.generatedAnswer.disable();
} else {
this.generatedAnswer.enable();
}
}
}

public render() {
if (
!shouldDisplayOnCurrentTab(
[...this.tabsIncluded],
[...this.tabsExcluded],
this.tabManagerState?.activeTab
)
) {
return <Hidden />;
}
return this.generatedAnswerCommon.render();
}
}
9 changes: 7 additions & 2 deletions packages/atomic/src/pages/examples/tabs.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
await searchInterface.initialize({
accessToken: 'xx564559b1-0045-48e1-953c-3addd1ee4457',
organizationId: 'searchuisamples',
search: {
pipeline: 'genqatest',
},
organizationEndpoints: await searchInterface.getOrganizationEndpoints('searchuisamples'),
});

// Trigger a first search
Expand Down Expand Up @@ -199,7 +203,7 @@
</atomic-facet-manager>
</atomic-layout-section>
<atomic-layout-section section="main">
<atomic-tab-manager clear-filters-on-tab-change="true">
<atomic-tab-manager clear-filters-on-tab-change="false">
<atomic-tab name="all" label="All"></atomic-tab>
<atomic-tab name="article" label="Articles"></atomic-tab>
<atomic-tab name="product" label="Products"></atomic-tab>
Expand Down Expand Up @@ -232,6 +236,7 @@
<atomic-query-summary></atomic-query-summary>
<atomic-refine-toggle></atomic-refine-toggle>
<atomic-sort-dropdown>
<atomic-sort-expression label="relevance" expression="relevancy"></atomic-sort-expression>
<atomic-sort-expression
tabs-excluded='["article"]'
label="Name descending"
Expand All @@ -252,12 +257,12 @@
label="Least Recent"
expression="date ascending"
></atomic-sort-expression>
<atomic-sort-expression label="relevance" expression="relevancy"></atomic-sort-expression>
</atomic-sort-dropdown>
<atomic-did-you-mean></atomic-did-you-mean>
<atomic-notifications></atomic-notifications>
</atomic-layout-section>
<atomic-layout-section section="results">
<atomic-generated-answer tabs-included='["all","parts"]'></atomic-generated-answer>
<atomic-smart-snippet></atomic-smart-snippet>
<atomic-smart-snippet-suggestions></atomic-smart-snippet-suggestions>
<atomic-result-list display="list" tabs-included='["all", "parts"]'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Tab, TabManager, TabState} from '@coveo/headless/ssr';
import {Tab, TabState} from '@coveo/headless/ssr';

interface TabCommonProps {
state: TabState;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use client';

import {TabManager} from '@coveo/headless-react/ssr';
import {
useTabAll,
useTabCountries,
Expand Down

0 comments on commit 744fb61

Please sign in to comment.