Skip to content

Commit

Permalink
refactor(list-item): set displayMode on slotted list (#10965)
Browse files Browse the repository at this point in the history
**Related Issue:** #10949

## Summary

- set displayMode on slotted list
- cleanup 🧹 
- e2e test
  • Loading branch information
driskull authored Dec 9, 2024
1 parent b7e9294 commit 1a3cd67
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe("calcite-list-item", () => {
},
{
propertyName: "displayMode",
defaultValue: undefined,
defaultValue: "flat",
},
]);
});
Expand Down Expand Up @@ -352,17 +352,17 @@ describe("calcite-list-item", () => {

it("should fire calciteListItemToggle event when opened and closed", async () => {
const page = await newE2EPage({
html: html`<calcite-list-item display-mode="nested"
><calcite-list><calcite-list-item></calcite-list-item></calcite-list
html: html`<calcite-list-item id="test" display-mode="nested"
><calcite-list display-mode="nested"><calcite-list-item></calcite-list-item></calcite-list
></calcite-list-item>`,
});

const listItem = await page.find("calcite-list-item");
const listItem = await page.find("#test");
const calciteListItemToggle = await page.spyOnEvent("calciteListItemToggle", "window");

expect(await listItem.getProperty("open")).toBe(false);

const openButton = await page.find(`calcite-list-item >>> .${CSS.openContainer}`);
const openButton = await page.find(`#test >>> .${CSS.openContainer}`);

await openButton.click();
expect(await listItem.getProperty("open")).toBe(true);
Expand Down Expand Up @@ -396,6 +396,28 @@ describe("calcite-list-item", () => {
expect(calciteListItemToggle).toHaveReceivedEventTimes(0);
});

it("should set displayMode on slotted list", async () => {
const page = await newE2EPage({
html: html`<calcite-list-item><calcite-list></calcite-list></calcite-list-item>`,
});

const listItem = await page.find("calcite-list-item");
const list = await page.find("calcite-list");

expect(await listItem.getProperty("displayMode")).toBe("flat");
expect(await list.getProperty("displayMode")).toBe("flat");

listItem.setProperty("displayMode", "nested");
await page.waitForChanges();

expect(await list.getProperty("displayMode")).toBe("nested");

listItem.setProperty("displayMode", "flat");
await page.waitForChanges();

expect(await list.getProperty("displayMode")).toBe("flat");
});

it("flat list should not render open container", async () => {
const page = await newE2EPage({
html: html`<calcite-list-item display-mode="flat"
Expand Down
15 changes: 10 additions & 5 deletions packages/calcite-components/src/components/list-item/list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type { List } from "../list/list";
import { getIconScale } from "../../utils/component";
import { ListDisplayMode } from "../list/interfaces";
import T9nStrings from "./assets/t9n/list-item.t9n.en.json";
import { getDepth, hasListItemChildren } from "./utils";
import { getDepth, getListItemChildren, listSelector } from "./utils";
import { CSS, activeCellTestAttribute, ICONS, SLOTS } from "./resources";
import { styles } from "./list-item.scss";

Expand All @@ -34,8 +34,6 @@ declare global {
}

const focusMap = new Map<List["el"], number>();
const listSelector = "calcite-list";

/**
* @slot - A slot for adding `calcite-list`, `calcite-list-item` and `calcite-list-item-group` elements.
* @slot actions-start - A slot for adding actionable `calcite-action` elements before the content of the component.
Expand Down Expand Up @@ -168,7 +166,7 @@ export class ListItem
*
* @private
*/
@property({ reflect: true }) displayMode: ListDisplayMode;
@property({ reflect: true }) displayMode: ListDisplayMode = "flat";

/**
* Sets the item to display a border.
Expand Down Expand Up @@ -539,7 +537,14 @@ export class ListItem
return;
}

this.openable = this.displayMode === "nested" && hasListItemChildren(slotEl);
const children = getListItemChildren(slotEl);

children.lists.forEach((list) => {
list.displayMode = this.displayMode;
});

this.openable =
this.displayMode === "nested" && (children.lists.length > 0 || children.items.length > 0);
}

private handleDefaultSlotChange(event: Event): void {
Expand Down
16 changes: 11 additions & 5 deletions packages/calcite-components/src/components/list-item/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type { List } from "../list/list";
import type { ListItemGroup } from "../list-item-group/list-item-group";
import type { ListItem } from "./list-item";

const listSelector = "calcite-list";
const listItemGroupSelector = "calcite-list-item-group";
const listItemSelector = "calcite-list-item";
export const listSelector = "calcite-list";
export const listItemGroupSelector = "calcite-list-item-group";
export const listItemSelector = "calcite-list-item";

export function openAncestors(el: ListItem["el"]): void {
const ancestor = el.parentElement?.closest(listItemSelector);
Expand All @@ -18,7 +18,10 @@ export function openAncestors(el: ListItem["el"]): void {
openAncestors(ancestor);
}

export function hasListItemChildren(slotEl: HTMLSlotElement): boolean {
export function getListItemChildren(slotEl: HTMLSlotElement): {
lists: List["el"][];
items: ListItem["el"][];
} {
const assignedElements = slotEl.assignedElements({ flatten: true });

const groupChildren = assignedElements
Expand All @@ -30,7 +33,10 @@ export function hasListItemChildren(slotEl: HTMLSlotElement): boolean {

const listChildren = assignedElements.filter((el): el is List["el"] => el?.matches(listSelector));

return [...listChildren, ...groupChildren, ...listItemChildren].length > 0;
return {
lists: listChildren,
items: groupChildren.concat(listItemChildren),
};
}

export function updateListItemChildren(slotEl: HTMLSlotElement): void {
Expand Down
12 changes: 4 additions & 8 deletions packages/calcite-components/src/components/list/list.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,12 @@ describe("calcite-list", () => {
await page.waitForChanges();
await page.waitForTimeout(DEBOUNCE.filter);

let modeValues = ["nested", "flat", "nested", "nested", "flat", "nested", "nested"];

const items = await page.findAll("calcite-list-item");

expect(items.length).toBe(modeValues.length);
expect(items.length).toBe(7);

for (let i = 0; i < items.length; i++) {
expect(await items[i].getProperty("displayMode")).toBe(modeValues[i]);
expect(await items[i].getProperty("displayMode")).toBe("nested");
}

const rootList = await page.find("#root");
Expand All @@ -211,12 +209,10 @@ describe("calcite-list", () => {
await page.waitForChanges();
await page.waitForTimeout(DEBOUNCE.filter);

modeValues = ["flat", "flat", "nested", "nested", "flat", "flat", "flat"];

expect(items.length).toBe(modeValues.length);
expect(items.length).toBe(7);

for (let i = 0; i < items.length; i++) {
expect(await items[i].getProperty("displayMode")).toBe(modeValues[i]);
expect(await items[i].getProperty("displayMode")).toBe("flat");
}
});

Expand Down
16 changes: 10 additions & 6 deletions packages/calcite-components/src/components/list/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import {
import { createObserver } from "../../utils/observers";
import { SelectionMode, InteractionMode, Scale } from "../interfaces";
import { ItemData } from "../list-item/interfaces";
import { openAncestors, updateListItemChildren } from "../list-item/utils";
import {
listItemGroupSelector,
listItemSelector,
listSelector,
openAncestors,
updateListItemChildren,
} from "../list-item/utils";
import {
connectSortableComponent,
disconnectSortableComponent,
Expand Down Expand Up @@ -42,9 +48,7 @@ declare global {
}
}

const listItemSelector = "calcite-list-item";
const listItemGroupSelector = "calcite-list-item-group";
const parentSelector = `${listItemGroupSelector}, calcite-list-item`;
const parentSelector = `${listItemGroupSelector}, ${listItemSelector}`;

/**
* A general purpose list that enables users to construct list items that conform to Calcite styling.
Expand Down Expand Up @@ -111,7 +115,7 @@ export class List
item.selectionAppearance = selectionAppearance;
item.selectionMode = selectionMode;
item.interactionMode = interactionMode;
if (item.closest("calcite-list") === el) {
if (item.closest(listSelector) === el) {
item.moveToItems = moveToItems.filter(
(moveToItem) => moveToItem.element !== el && !item.contains(moveToItem.element),
);
Expand Down Expand Up @@ -604,7 +608,7 @@ export class List
}

private setParentList(): void {
this.parentListEl = this.el.parentElement?.closest("calcite-list");
this.parentListEl = this.el.parentElement?.closest(listSelector);
}

private handleDefaultSlotChange(event: Event): void {
Expand Down

0 comments on commit 1a3cd67

Please sign in to comment.