Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(atomic): add ipx facets (#2565)
* fix(atomic): remove dangling div * feat(atomic): Add facets in IPX * Add generated files * fix(atomic): remove unused style + story * feat(atomic): add customizable class to atomic-icon-button * fix(atomic): Use part to style icon * fix(ipx): move facets to facets section Co-authored-by: GitHub Actions Bot <>
- Loading branch information
1 parent
dece950
commit d58e5df
Showing
9 changed files
with
356 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
1 change: 1 addition & 0 deletions
1
packages/atomic/src/components/ipx/atomic-ipx-refine-modal/atomic-ipx-refine-modal.pcss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
@import '../../common/refine-modal/refine-modal-common.pcss'; |
170 changes: 170 additions & 0 deletions
170
packages/atomic/src/components/ipx/atomic-ipx-refine-modal/atomic-ipx-refine-modal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import { | ||
BreadcrumbManager, | ||
BreadcrumbManagerState, | ||
buildBreadcrumbManager, | ||
buildFacetManager, | ||
buildQuerySummary, | ||
FacetManager, | ||
QuerySummary, | ||
QuerySummaryState, | ||
} from '@coveo/headless'; | ||
import {Component, h, State, Prop, Element, Watch, Host} from '@stencil/core'; | ||
import {rectEquals} from '../../../utils/dom-utils'; | ||
import { | ||
BindStateToController, | ||
InitializableComponent, | ||
InitializeBindings, | ||
} from '../../../utils/initialization-utils'; | ||
import {Button} from '../../common/button'; | ||
import {Hidden} from '../../common/hidden'; | ||
import { | ||
getClonedFacetElements, | ||
RefineModalCommon, | ||
} from '../../common/refine-modal/refine-modal-common'; | ||
import {Bindings} from '../../search/atomic-search-interface/atomic-search-interface'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
@Component({ | ||
tag: 'atomic-ipx-refine-modal', | ||
styleUrl: 'atomic-ipx-refine-modal.pcss', | ||
shadow: true, | ||
}) | ||
export class AtomicIPXRefineModal implements InitializableComponent { | ||
@InitializeBindings() public bindings!: Bindings; | ||
@Element() public host!: HTMLElement; | ||
|
||
@BindStateToController('querySummary') | ||
@State() | ||
public querySummaryState!: QuerySummaryState; | ||
|
||
@BindStateToController('breadcrumbManager') | ||
@State() | ||
public breadcrumbManagerState!: BreadcrumbManagerState; | ||
|
||
@State() | ||
public error!: Error; | ||
|
||
@State() | ||
public interfaceDimensions?: DOMRect; | ||
|
||
@Prop({mutable: true}) openButton?: HTMLElement; | ||
|
||
@Prop({reflect: true, mutable: true}) isOpen = false; | ||
|
||
private breadcrumbManager!: BreadcrumbManager; | ||
public querySummary!: QuerySummary; | ||
private facetManager!: FacetManager; | ||
|
||
@Watch('isOpen') | ||
watchEnabled(isOpen: boolean) { | ||
if (isOpen) { | ||
if (!this.host.querySelector('div[slot="facets"]')) { | ||
this.host.append( | ||
getClonedFacetElements( | ||
this.bindings.store.getFacetElements(), | ||
this.facetManager | ||
) | ||
); | ||
} | ||
this.onAnimationFrame(); | ||
} | ||
} | ||
|
||
private onAnimationFrame() { | ||
if (!this.isOpen) { | ||
return; | ||
} | ||
if (this.dimensionChanged()) { | ||
this.updateDimensions(); | ||
} | ||
window.requestAnimationFrame(() => this.onAnimationFrame()); | ||
} | ||
|
||
private dimensionChanged() { | ||
if (!this.interfaceDimensions) { | ||
return true; | ||
} | ||
|
||
return !rectEquals( | ||
this.interfaceDimensions, | ||
this.bindings.interfaceElement.getBoundingClientRect() | ||
); | ||
} | ||
|
||
public updateDimensions() { | ||
this.interfaceDimensions = this.bindings.interfaceElement | ||
.getElementsByTagName('atomic-ipx-layout')[0] | ||
.getBoundingClientRect(); | ||
} | ||
|
||
public initialize() { | ||
this.breadcrumbManager = buildBreadcrumbManager(this.bindings.engine); | ||
this.facetManager = buildFacetManager(this.bindings.engine); | ||
this.querySummary = buildQuerySummary(this.bindings.engine); | ||
} | ||
|
||
private renderHeader() { | ||
return ( | ||
<div class="w-full flex justify-between mb-3"> | ||
<h2 class="text-2xl font-bold truncate"> | ||
{this.bindings.i18n.t('filters')} | ||
</h2> | ||
{this.breadcrumbManagerState.hasBreadcrumbs && ( | ||
<Button | ||
onClick={() => this.breadcrumbManager.deselectAll()} | ||
style="text-primary" | ||
text={this.bindings.i18n.t('clear-all-filters')} | ||
class="px-2 py-1" | ||
></Button> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
private renderBody() { | ||
if (!this.bindings.store.getFacetElements().length) { | ||
return <Hidden></Hidden>; | ||
} | ||
|
||
return ( | ||
<aside slot="body" class="flex flex-col w-full adjust-for-scroll-bar"> | ||
{this.renderHeader()} | ||
<slot name="facets"></slot> | ||
</aside> | ||
); | ||
} | ||
|
||
public render() { | ||
return ( | ||
<Host> | ||
{this.interfaceDimensions && ( | ||
<style> | ||
{`atomic-modal::part(backdrop) { | ||
top: ${this.interfaceDimensions.top}px; | ||
left: ${this.interfaceDimensions.left}px; | ||
width: ${this.interfaceDimensions.width}px; | ||
height: ${this.interfaceDimensions.height}px; | ||
}`} | ||
</style> | ||
)} | ||
<RefineModalCommon | ||
bindings={this.bindings} | ||
host={this.host} | ||
isOpen={this.isOpen} | ||
onClose={() => (this.isOpen = false)} | ||
querySummaryState={this.querySummaryState} | ||
title={this.bindings.i18n.t('filters')} | ||
openButton={this.openButton} | ||
> | ||
{this.renderBody()} | ||
</RefineModalCommon> | ||
</Host> | ||
); | ||
} | ||
|
||
public componentDidLoad() { | ||
this.host.style.display = ''; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
packages/atomic/src/components/ipx/atomic-ipx-refine-toggle/atomic-ipx-refine-toggle.pcss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@import '../../../global/global.pcss'; | ||
|
||
atomic-icon-button { | ||
height: 100%; | ||
&::part(button) { | ||
height: 100%; | ||
width: auto; | ||
} | ||
&::part(badge) { | ||
width: 1.25rem; | ||
height: 1.25rem; | ||
line-height: 1.25rem; | ||
font-size: 0.7rem; | ||
} | ||
|
||
&::part(icon) { | ||
width: 1.25rem; | ||
height: 1.25rem; | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
packages/atomic/src/components/ipx/atomic-ipx-refine-toggle/atomic-ipx-refine-toggle.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { | ||
BreadcrumbManager, | ||
BreadcrumbManagerState, | ||
buildBreadcrumbManager, | ||
buildSearchStatus, | ||
SearchStatus, | ||
SearchStatusState, | ||
} from '@coveo/headless'; | ||
import {Component, h, State, Element} from '@stencil/core'; | ||
import FilterIcon from '../../../images/filter.svg'; | ||
import { | ||
InitializeBindings, | ||
BindStateToController, | ||
} from '../../../utils/initialization-utils'; | ||
import {Bindings} from '../../search/atomic-search-interface/atomic-search-interface'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
@Component({ | ||
tag: 'atomic-ipx-refine-toggle', | ||
styleUrl: 'atomic-ipx-refine-toggle.pcss', | ||
shadow: true, | ||
}) | ||
export class AtomicIPXRefineToggle { | ||
@InitializeBindings() public bindings!: Bindings; | ||
@Element() public host!: HTMLElement; | ||
|
||
@State() public error!: Error; | ||
|
||
@BindStateToController('breadcrumbManager') | ||
@State() | ||
private breadcrumbManagerState!: BreadcrumbManagerState; | ||
|
||
@BindStateToController('searchStatus') | ||
@State() | ||
private searchStatusState!: SearchStatusState; | ||
|
||
public breadcrumbManager!: BreadcrumbManager; | ||
public searchStatus!: SearchStatus; | ||
private modalRef?: HTMLAtomicIpxRefineModalElement; | ||
private buttonRef?: HTMLButtonElement; | ||
|
||
private get numberOfBreadcrumbs(): number { | ||
return [ | ||
...this.breadcrumbManagerState.facetBreadcrumbs, | ||
...this.breadcrumbManagerState.categoryFacetBreadcrumbs, | ||
...this.breadcrumbManagerState.numericFacetBreadcrumbs, | ||
...this.breadcrumbManagerState.dateFacetBreadcrumbs, | ||
...this.breadcrumbManagerState.staticFilterBreadcrumbs, | ||
].length; | ||
} | ||
|
||
public initialize() { | ||
this.breadcrumbManager = buildBreadcrumbManager(this.bindings.engine); | ||
this.searchStatus = buildSearchStatus(this.bindings.engine); | ||
} | ||
|
||
private enableModal() { | ||
this.modalRef && (this.modalRef.isOpen = true); | ||
} | ||
|
||
private loadModal() { | ||
if (this.modalRef) { | ||
return; | ||
} | ||
|
||
this.modalRef = document.createElement('atomic-ipx-refine-modal'); | ||
this.host.parentElement?.insertAdjacentElement( | ||
'beforebegin', | ||
this.modalRef | ||
); | ||
this.modalRef.openButton = this.buttonRef; | ||
} | ||
|
||
public render() { | ||
return ( | ||
<atomic-icon-button | ||
tooltip={this.bindings.i18n.t('filters')} | ||
icon={FilterIcon} | ||
disabled={ | ||
!this.searchStatusState.hasResults && !this.numberOfBreadcrumbs | ||
} | ||
labelI18nKey="sort" | ||
clickCallback={() => { | ||
this.bindings.store.waitUntilAppLoaded(() => { | ||
this.enableModal(); | ||
}); | ||
}} | ||
buttonRef={(button?: HTMLButtonElement) => { | ||
if (!button) { | ||
return; | ||
} | ||
this.buttonRef = button; | ||
this.loadModal(); | ||
}} | ||
badge={ | ||
this.breadcrumbManagerState.hasBreadcrumbs ? ( | ||
<slot>{this.numberOfBreadcrumbs.toString()}</slot> | ||
) : undefined | ||
} | ||
/> | ||
); | ||
} | ||
} |
Oops, something went wrong.