Skip to content

Commit

Permalink
fix(tabs): redisplay close button when more than one tab is closable (#…
Browse files Browse the repository at this point in the history
…11492)

**Related Issue:** #10183

## Summary
Redisplays x when > 1 closable tab is added programmatically.
  • Loading branch information
josercarcamo authored Mar 4, 2025
1 parent 0c002d9 commit 3150fe5
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 10 deletions.
33 changes: 23 additions & 10 deletions packages/calcite-components/src/components/tab-nav/tab-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
focusElementInGroup,
FocusElementInGroupDestination,
getElementDir,
slotChangeGetAssignedElements,
} from "../../utils/dom";
import { createObserver } from "../../utils/observers";
import { Scale } from "../interfaces";
Expand Down Expand Up @@ -72,6 +71,8 @@ export class TabNav extends LitElement {
return filterDirectChildren<TabTitle["el"]>(this.el, "calcite-tab-title");
}

private makeFirstVisibleTabClosable = false;

// #endregion

// #region State Properties
Expand Down Expand Up @@ -367,14 +368,21 @@ export class TabNav extends LitElement {
(event.currentTarget as HTMLDivElement).scrollBy(scrollByX, 0);
}

private onSlotChange(event: Event): void {
private onSlotChange(): void {
this.intersectionObserver?.disconnect();

const slottedElements = slotChangeGetAssignedElements(event, "calcite-tab-title");
slottedElements.forEach((child) => {
const tabTitles = this.tabTitles;
tabTitles.forEach((child) => {
this.intersectionObserver?.observe(child);
});
this.calciteInternalTabNavSlotChange.emit(slottedElements);
const visibleTabTitlesIndices = this.getVisibleTabTitlesIndices(tabTitles);
const totalVisibleTabTitles = visibleTabTitlesIndices.length;
if (totalVisibleTabTitles > 1 && this.makeFirstVisibleTabClosable) {
tabTitles[visibleTabTitlesIndices[0]].closable = true;
this.makeFirstVisibleTabClosable = false;
}

this.calciteInternalTabNavSlotChange.emit(tabTitles);
}

private storeTabTitleWrapperRef(el: HTMLDivElement) {
Expand Down Expand Up @@ -517,18 +525,23 @@ export class TabNav extends LitElement {
});
}

private handleTabTitleClose(closedTabTitleEl: TabTitle["el"]): void {
const { tabTitles } = this;
const selectionModified = closedTabTitleEl.selected;

const visibleTabTitlesIndices = tabTitles.reduce(
private getVisibleTabTitlesIndices(tabTitles: TabTitle["el"][]): number[] {
return tabTitles.reduce(
(tabTitleIndices: number[], tabTitle, index) =>
!tabTitle.closed ? [...tabTitleIndices, index] : tabTitleIndices,
[],
);
}

private handleTabTitleClose(closedTabTitleEl: TabTitle["el"]): void {
const { tabTitles } = this;
const selectionModified = closedTabTitleEl.selected;

const visibleTabTitlesIndices = this.getVisibleTabTitlesIndices(tabTitles);
const totalVisibleTabTitles = visibleTabTitlesIndices.length;

if (totalVisibleTabTitles === 1 && tabTitles[visibleTabTitlesIndices[0]].closable) {
this.makeFirstVisibleTabClosable = true;
tabTitles[visibleTabTitlesIndices[0]].closable = false;
this.selectedTabId = visibleTabTitlesIndices[0];

Expand Down
40 changes: 40 additions & 0 deletions packages/calcite-components/src/components/tabs/tabs.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,5 +405,45 @@ describe("calcite-tabs", () => {

expect(selectedTitleOnEmit).toBe("Tab 2 Title");
});

describe("hiding/displaying X", () => {
it("should hide x when tabs 2 to 4 closed and display x closable tab added", async () => {
for (let i = 2; i <= 4; ++i) {
await page.click(`#tab-title-${i} >>> .${TabTitleCSS.closeButton}`);
}
let tab1 = await page.find(`#tab-title-1`);
expect(await tab1.getProperty("closable")).toBe(false);
expect(await page.find(`#tab-title-1 >>> .${TabTitleCSS.closeButton}`)).toBeNull();

await page.evaluate(() => {
document
.getElementById("tab-title-4")
.insertAdjacentHTML("afterend", `<calcite-tab-title id="tab-title-5" closable>Test</calcite-tab-title>`);
});
await page.waitForChanges();
tab1 = await page.find(`#tab-title-1`);
expect(await tab1.getProperty("closable")).toBe(true);
expect(await page.find(`#tab-title-1 >>> .${TabTitleCSS.closeButton}`)).toBeDefined();
});

it("should hide x when tabs 1 to 3 closed and display x when closable tab added", async () => {
for (let i = 1; i <= 3; ++i) {
await page.click(`#tab-title-${i} >>> .${TabTitleCSS.closeButton}`);
}
let tab4 = await page.find(`#tab-title-4`);
expect(await tab4.getProperty("closable")).toBe(false);
expect(await page.find(`#tab-title-4 >>> .${TabTitleCSS.closeButton}`)).toBeNull();

await page.evaluate(() => {
document
.getElementById("tab-title-4")
.insertAdjacentHTML("afterend", `<calcite-tab-title id="tab-title-5" closable>Test</calcite-tab-title>`);
});
await page.waitForChanges();
tab4 = await page.find(`#tab-title-4`);
expect(await tab4.getProperty("closable")).toBe(true);
expect(await page.find(`#tab-title-4 >>> .${TabTitleCSS.closeButton}`)).toBeDefined();
});
});
});
});

0 comments on commit 3150fe5

Please sign in to comment.