Skip to content

Commit ae8064e

Browse files
josercarcamobenelan
authored andcommitted
fix(tabs): redisplay close button when more than one tab is closable (#11492)
**Related Issue:** #10183 ## Summary Redisplays x when > 1 closable tab is added programmatically.
1 parent e3837a6 commit ae8064e

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

packages/calcite-components/src/components/tab-nav/tab-nav.tsx

+23-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
focusElementInGroup,
1313
FocusElementInGroupDestination,
1414
getElementDir,
15-
slotChangeGetAssignedElements,
1615
} from "../../utils/dom";
1716
import { createObserver } from "../../utils/observers";
1817
import { Scale } from "../interfaces";
@@ -72,6 +71,8 @@ export class TabNav extends LitElement {
7271
return filterDirectChildren<TabTitle["el"]>(this.el, "calcite-tab-title");
7372
}
7473

74+
private makeFirstVisibleTabClosable = false;
75+
7576
// #endregion
7677

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

370-
private onSlotChange(event: Event): void {
371+
private onSlotChange(): void {
371372
this.intersectionObserver?.disconnect();
372373

373-
const slottedElements = slotChangeGetAssignedElements(event, "calcite-tab-title");
374-
slottedElements.forEach((child) => {
374+
const tabTitles = this.tabTitles;
375+
tabTitles.forEach((child) => {
375376
this.intersectionObserver?.observe(child);
376377
});
377-
this.calciteInternalTabNavSlotChange.emit(slottedElements);
378+
const visibleTabTitlesIndices = this.getVisibleTabTitlesIndices(tabTitles);
379+
const totalVisibleTabTitles = visibleTabTitlesIndices.length;
380+
if (totalVisibleTabTitles > 1 && this.makeFirstVisibleTabClosable) {
381+
tabTitles[visibleTabTitlesIndices[0]].closable = true;
382+
this.makeFirstVisibleTabClosable = false;
383+
}
384+
385+
this.calciteInternalTabNavSlotChange.emit(tabTitles);
378386
}
379387

380388
private storeTabTitleWrapperRef(el: HTMLDivElement) {
@@ -517,18 +525,23 @@ export class TabNav extends LitElement {
517525
});
518526
}
519527

520-
private handleTabTitleClose(closedTabTitleEl: TabTitle["el"]): void {
521-
const { tabTitles } = this;
522-
const selectionModified = closedTabTitleEl.selected;
523-
524-
const visibleTabTitlesIndices = tabTitles.reduce(
528+
private getVisibleTabTitlesIndices(tabTitles: TabTitle["el"][]): number[] {
529+
return tabTitles.reduce(
525530
(tabTitleIndices: number[], tabTitle, index) =>
526531
!tabTitle.closed ? [...tabTitleIndices, index] : tabTitleIndices,
527532
[],
528533
);
534+
}
535+
536+
private handleTabTitleClose(closedTabTitleEl: TabTitle["el"]): void {
537+
const { tabTitles } = this;
538+
const selectionModified = closedTabTitleEl.selected;
539+
540+
const visibleTabTitlesIndices = this.getVisibleTabTitlesIndices(tabTitles);
529541
const totalVisibleTabTitles = visibleTabTitlesIndices.length;
530542

531543
if (totalVisibleTabTitles === 1 && tabTitles[visibleTabTitlesIndices[0]].closable) {
544+
this.makeFirstVisibleTabClosable = true;
532545
tabTitles[visibleTabTitlesIndices[0]].closable = false;
533546
this.selectedTabId = visibleTabTitlesIndices[0];
534547

packages/calcite-components/src/components/tabs/tabs.e2e.ts

+40
Original file line numberDiff line numberDiff line change
@@ -405,5 +405,45 @@ describe("calcite-tabs", () => {
405405

406406
expect(selectedTitleOnEmit).toBe("Tab 2 Title");
407407
});
408+
409+
describe("hiding/displaying X", () => {
410+
it("should hide x when tabs 2 to 4 closed and display x closable tab added", async () => {
411+
for (let i = 2; i <= 4; ++i) {
412+
await page.click(`#tab-title-${i} >>> .${TabTitleCSS.closeButton}`);
413+
}
414+
let tab1 = await page.find(`#tab-title-1`);
415+
expect(await tab1.getProperty("closable")).toBe(false);
416+
expect(await page.find(`#tab-title-1 >>> .${TabTitleCSS.closeButton}`)).toBeNull();
417+
418+
await page.evaluate(() => {
419+
document
420+
.getElementById("tab-title-4")
421+
.insertAdjacentHTML("afterend", `<calcite-tab-title id="tab-title-5" closable>Test</calcite-tab-title>`);
422+
});
423+
await page.waitForChanges();
424+
tab1 = await page.find(`#tab-title-1`);
425+
expect(await tab1.getProperty("closable")).toBe(true);
426+
expect(await page.find(`#tab-title-1 >>> .${TabTitleCSS.closeButton}`)).toBeDefined();
427+
});
428+
429+
it("should hide x when tabs 1 to 3 closed and display x when closable tab added", async () => {
430+
for (let i = 1; i <= 3; ++i) {
431+
await page.click(`#tab-title-${i} >>> .${TabTitleCSS.closeButton}`);
432+
}
433+
let tab4 = await page.find(`#tab-title-4`);
434+
expect(await tab4.getProperty("closable")).toBe(false);
435+
expect(await page.find(`#tab-title-4 >>> .${TabTitleCSS.closeButton}`)).toBeNull();
436+
437+
await page.evaluate(() => {
438+
document
439+
.getElementById("tab-title-4")
440+
.insertAdjacentHTML("afterend", `<calcite-tab-title id="tab-title-5" closable>Test</calcite-tab-title>`);
441+
});
442+
await page.waitForChanges();
443+
tab4 = await page.find(`#tab-title-4`);
444+
expect(await tab4.getProperty("closable")).toBe(true);
445+
expect(await page.find(`#tab-title-4 >>> .${TabTitleCSS.closeButton}`)).toBeDefined();
446+
});
447+
});
408448
});
409449
});

0 commit comments

Comments
 (0)