From 552e28f0107b0a492901790b59d34f178ce08619 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 5 Dec 2022 17:07:34 -0800 Subject: [PATCH] fix(list, list-item): Fix focus behavior when clicking on an item (#5901) **Related Issue:** #5899 ## Summary fix(list, list-item): Fix focus behavior when clicking on an item. --- src/components/list-item/list-item.e2e.ts | 16 ++++++++++++ src/components/list-item/list-item.tsx | 17 ++++++++++--- src/components/list/list.e2e.ts | 31 +++++++++++++++++++++++ src/components/list/list.tsx | 11 +++++++- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/components/list-item/list-item.e2e.ts b/src/components/list-item/list-item.e2e.ts index 37076c3b050..6061856ba5d 100755 --- a/src/components/list-item/list-item.e2e.ts +++ b/src/components/list-item/list-item.e2e.ts @@ -100,4 +100,20 @@ describe("calcite-list-item", () => { expect(eventSpy).toHaveReceivedEventTimes(1); }); + + it("emits calciteInternalListItemActive on click", async () => { + const page = await newE2EPage({ + html: `` + }); + + await page.waitForChanges(); + + const contentContainer = await page.find(`calcite-list-item >>> .${CSS.contentContainer}`); + + const eventSpy = await page.spyOnEvent("calciteInternalListItemActive"); + + await contentContainer.click(); + + expect(eventSpy).toHaveReceivedEventTimes(1); + }); }); diff --git a/src/components/list-item/list-item.tsx b/src/components/list-item/list-item.tsx index 6209c78dd54..a5fd79a3c3f 100644 --- a/src/components/list-item/list-item.tsx +++ b/src/components/list-item/list-item.tsx @@ -150,6 +150,12 @@ export class ListItem implements InteractiveComponent, LoadableComponent { */ @Event({ cancelable: false }) calciteInternalListItemSelect: EventEmitter; + /** + * + * @internal + */ + @Event({ cancelable: false }) calciteInternalListItemActive: EventEmitter; + /** * * @internal @@ -250,7 +256,7 @@ export class ListItem implements InteractiveComponent, LoadableComponent { } return ( - + ) : parentListEl?.openable ? ( - + ) : null; @@ -380,7 +386,7 @@ export class ListItem implements InteractiveComponent, LoadableComponent { [CSS.contentContainerHasCenterContent]: hasCenterContent }} key="content-container" - onClick={this.toggleSelected} + onClick={this.itemClicked} ref={(el) => (this.contentEl = el)} role="gridcell" > @@ -509,6 +515,11 @@ export class ListItem implements InteractiveComponent, LoadableComponent { this.open = !this.open; }; + itemClicked = (): void => { + this.toggleSelected(); + this.calciteInternalListItemActive.emit(); + }; + toggleSelected = (): void => { if (this.disabled) { return; diff --git a/src/components/list/list.e2e.ts b/src/components/list/list.e2e.ts index eb93a7c74b4..171b965c3fb 100755 --- a/src/components/list/list.e2e.ts +++ b/src/components/list/list.e2e.ts @@ -147,4 +147,35 @@ describe("calcite-list", () => { expect(await list.getProperty("filteredData")).toHaveLength(0); expect(await list.getProperty("filterText")).toBe("twoblah"); }); + + it("should update active item on init and click", async () => { + const page = await newE2EPage({ + html: html` + + + + ` + }); + + await page.waitForTimeout(debounceTimeout); + await page.waitForChanges(); + + const items = await page.findAll("calcite-list-item"); + + expect(await items[0].getProperty("active")).toBe(true); + expect(await items[1].getProperty("active")).toBe(false); + expect(await items[2].getProperty("active")).toBe(false); + + const eventSpy = await page.spyOnEvent("calciteInternalListItemActive"); + + await items[1].click(); + + await page.waitForTimeout(debounceTimeout); + await page.waitForChanges(); + expect(eventSpy).toHaveReceivedEventTimes(1); + + expect(await items[0].getProperty("active")).toBe(false); + expect(await items[1].getProperty("active")).toBe(true); + expect(await items[2].getProperty("active")).toBe(false); + }); }); diff --git a/src/components/list/list.tsx b/src/components/list/list.tsx index 2d79ea77ab4..afb52bc9363 100755 --- a/src/components/list/list.tsx +++ b/src/components/list/list.tsx @@ -151,13 +151,22 @@ export class List implements InteractiveComponent, LoadableComponent { } } + @Listen("calciteInternalListItemActive") + handleCalciteListItemActive(event: CustomEvent): void { + const target = event.target as HTMLCalciteListItemElement; + const { listItems } = this; + + listItems.forEach((listItem) => { + listItem.active = listItem === target; + }); + } + @Listen("calciteInternalListItemSelect") handleCalciteListItemSelect(event: CustomEvent): void { const target = event.target as HTMLCalciteListItemElement; const { listItems, selectionMode } = this; listItems.forEach((listItem) => { - listItem.active = listItem === target; if (selectionMode === "single") { listItem.selected = listItem === target; }