Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(list): enable dragging on list items contained within a list that supports dragEnabled #9660

Merged
merged 7 commits into from
Jun 21, 2024
Merged
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
106 changes: 106 additions & 0 deletions packages/calcite-components/src/components/list/list.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,112 @@ describe("calcite-list", () => {
{ focusTarget: "child" },
);

it("should set the dragHandle property on items", async () => {
const page = await newE2EPage();
await page.setContent(
html`<calcite-list id="root" drag-enabled group="my-list">
<calcite-list-item open label="Depth 1" description="Item 1">
<calcite-list group="my-list">
<calcite-list-item open label="Depth 2" description="Item 2">
<calcite-list drag-enabled group="my-list">
<calcite-list-item label="Depth 3" description="Item 3">
<calcite-list drag-enabled group="my-list"></calcite-list>
</calcite-list-item>
<calcite-list-item label="Depth 3" description="Item 4"></calcite-list-item>
</calcite-list>
</calcite-list-item>
<calcite-list-item label="Depth 2" description="Item 5"></calcite-list-item>
</calcite-list>
</calcite-list-item>
<calcite-list-item label="Depth 1" description="Item 6"></calcite-list-item>
<calcite-list-item drag-disabled label="Depth 1" description="Item 7"></calcite-list-item>
</calcite-list>`,
);

await page.waitForChanges();
await page.waitForTimeout(listDebounceTimeout);

let dragHandleValues = [true, false, true, true, false, true, true];

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

expect(items.length).toBe(dragHandleValues.length);

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

const rootList = await page.find("#root");

rootList.setProperty("dragEnabled", false);
await page.waitForChanges();
await page.waitForTimeout(listDebounceTimeout);

dragHandleValues = [false, false, true, true, false, false, false];

expect(items.length).toBe(dragHandleValues.length);

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

it("should set the dragHandle property on items which are not direct children", async () => {
const page = await newE2EPage();
await page.setContent(
html`<calcite-list id="root" drag-enabled group="my-list">
<div>
<calcite-list-item open label="Depth 1" description="Item 1">
<calcite-list group="my-list">
<div>
<calcite-list-item open label="Depth 2" description="Item 2">
<calcite-list drag-enabled group="my-list">
<div>
<calcite-list-item label="Depth 3" description="Item 3">
<calcite-list drag-enabled group="my-list"></calcite-list>
</calcite-list-item>
</div>
<div><calcite-list-item label="Depth 3" description="Item 4"></calcite-list-item></div>
</calcite-list>
</calcite-list-item>
</div>
<div><calcite-list-item label="Depth 2" description="Item 5"></calcite-list-item></div>
</calcite-list>
</calcite-list-item>
</div>
<div><calcite-list-item label="Depth 1" description="Item 6"></calcite-list-item></div>
<div><calcite-list-item drag-disabled label="Depth 1" description="Item 7"></calcite-list-item></div>
</calcite-list>`,
);

await page.waitForChanges();
await page.waitForTimeout(listDebounceTimeout);

let dragHandleValues = [true, false, true, true, false, true, true];

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

expect(items.length).toBe(dragHandleValues.length);

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

const rootList = await page.find("#root");

rootList.setProperty("dragEnabled", false);
await page.waitForChanges();
await page.waitForTimeout(listDebounceTimeout);

dragHandleValues = [false, false, true, true, false, false, false];

expect(items.length).toBe(dragHandleValues.length);

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

it("disabling and enabling an item restores actions from being tabbable", async () => {
const page = await newE2EPage();
await page.setContent(html`
Expand Down
44 changes: 44 additions & 0 deletions packages/calcite-components/src/components/list/list.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,3 +1077,47 @@ export const closedItems_TestOnly = (): string =>
>
</calcite-list-item>
</calcite-list>`;

export const dragEnabledNestedLists = (): string =>
html`<calcite-list id="root" drag-enabled group="my-list">
<calcite-list-item open label="Depth 1" description="Item 1">
<calcite-list group="my-list">
<calcite-list-item open label="Depth 2" description="Item 2">
<calcite-list drag-enabled group="my-list">
<calcite-list-item label="Depth 3" description="Item 3">
<calcite-list drag-enabled group="my-list"></calcite-list>
</calcite-list-item>
<calcite-list-item label="Depth 3" description="Item 4"></calcite-list-item>
</calcite-list>
</calcite-list-item>
<calcite-list-item label="Depth 2" description="Item 5"></calcite-list-item>
</calcite-list>
</calcite-list-item>
<calcite-list-item label="Depth 1" description="Item 6"></calcite-list-item>
<calcite-list-item drag-disabled label="Depth 1" description="Item 7"></calcite-list-item>
</calcite-list>`;

export const dragEnabledNestedListsIndirectChildren = (): string =>
html`<calcite-list id="root" drag-enabled group="my-list">
<div>
<calcite-list-item open label="Depth 1" description="Item 1">
<calcite-list group="my-list">
<div>
<calcite-list-item open label="Depth 2" description="Item 2">
<calcite-list drag-enabled group="my-list">
<div>
<calcite-list-item label="Depth 3" description="Item 3">
<calcite-list drag-enabled group="my-list"></calcite-list>
</calcite-list-item>
</div>
<div><calcite-list-item label="Depth 3" description="Item 4"></calcite-list-item></div>
</calcite-list>
</calcite-list-item>
</div>
<div><calcite-list-item label="Depth 2" description="Item 5"></calcite-list-item></div>
</calcite-list>
</calcite-list-item>
</div>
<div><calcite-list-item label="Depth 1" description="Item 6"></calcite-list-item></div>
<div><calcite-list-item drag-disabled label="Depth 1" description="Item 7"></calcite-list-item></div>
</calcite-list>`;
18 changes: 6 additions & 12 deletions packages/calcite-components/src/components/list/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ import { ListMessages } from "./assets/list/t9n";
import { ListDragDetail } from "./interfaces";

const listItemSelector = "calcite-list-item";
const listItemSelectorDirect = `:scope > calcite-list-item`;
const parentSelector = "calcite-list-item-group, calcite-list-item";

/**
Expand Down Expand Up @@ -837,17 +836,16 @@ export class List
};

private updateListItems = debounce((emit = false): void => {
const { selectionAppearance, selectionMode, dragEnabled } = this;
const { selectionAppearance, selectionMode, dragEnabled, el } = this;

const items = Array.from(this.el.querySelectorAll(listItemSelector));

const items = this.queryListItems();
items.forEach((item) => {
item.selectionAppearance = selectionAppearance;
item.selectionMode = selectionMode;
});

const directItems = this.queryListItems(true);
directItems.forEach((item) => {
item.dragHandle = dragEnabled;
if (item.closest("calcite-list") === el) {
item.dragHandle = dragEnabled;
}
});

if (this.parentListEl) {
Expand All @@ -871,10 +869,6 @@ export class List
this.setUpSorting();
}, debounceTimeout);

private queryListItems = (direct = false): HTMLCalciteListItemElement[] => {
return Array.from(this.el.querySelectorAll(direct ? listItemSelectorDirect : listItemSelector));
};

private focusRow = (focusEl: HTMLCalciteListItemElement): void => {
const { focusableItems } = this;

Expand Down
Loading