Skip to content

Commit 12e7dcd

Browse files
DonkeyCoKvM2
andauthored
feat(ui5-table-header-cell): add popinHidden property (#10834)
Provides the property popinHidden on the header-cell, allowing applications to hide columns in the popin if they are moved there. Co-authored-by: Katja <[email protected]>
1 parent d0b11a8 commit 12e7dcd

File tree

12 files changed

+203
-106
lines changed

12 files changed

+203
-106
lines changed

packages/main/cypress/specs/Table.cy.tsx

+83-61
Original file line numberDiff line numberDiff line change
@@ -60,38 +60,64 @@ describe("Table - Rendering", () => {
6060
});
6161

6262
describe("Table - Popin Mode", () => {
63-
beforeEach(() => {
63+
function checkPopinState(expectedState: { poppedIn: string[], hidden: string[] }) {
64+
cy.get("ui5-table-header-cell").each(($cell, index) => {
65+
const id = $cell.attr("id") ?? "";
66+
const shouldBePoppedIn = expectedState.poppedIn.includes(id);
67+
const shouldBeHidden = expectedState.hidden.includes(id);
68+
const roleCondition = shouldBePoppedIn || shouldBeHidden ? "not.have.attr" : "have.attr";
69+
70+
cy.wrap($cell)
71+
.should(roleCondition, "role", ROLE_COLUMN_HEADER);
72+
cy.get("ui5-table-header-row")
73+
.shadow()
74+
.find(`slot[name=default-${index + 1}]`)
75+
.should(shouldBePoppedIn || shouldBeHidden ? "not.exist" : "exist");
76+
});
77+
78+
cy.get("ui5-table-row").each($row => {
79+
cy.wrap($row).find("ui5-table-cell").each(($cell, index) => {
80+
const id = $cell.attr("id") ?? "NOT_FOUND";
81+
const shouldBeHidden = expectedState.hidden.some(hiddenId => id.includes(hiddenId));
82+
cy.wrap($row).shadow().find(`slot[name=default-${index + 1}]`)
83+
.should(shouldBeHidden ? "not.exist" : "exist");
84+
});
85+
});
86+
}
87+
88+
function mounTable(popinHidden = false) {
6489
cy.mount(
6590
<Table id="table" overflowMode="Popin">
6691
<TableHeaderRow slot="headerRow">
6792
<TableHeaderCell id="colA" minWidth="300px"><span>ColumnA</span></TableHeaderCell>
6893
<TableHeaderCell id="colB" minWidth="200px">Column B</TableHeaderCell>
6994
<TableHeaderCell id="colC" minWidth="200px">Column C</TableHeaderCell>
70-
<TableHeaderCell id="colD" minWidth="150px" popinText="Column ?">Column D</TableHeaderCell>
95+
<TableHeaderCell id="colD" minWidth="150px" popinText="Column ?" popinHidden={popinHidden}>Column D</TableHeaderCell>
7196
</TableHeaderRow>
7297
<TableRow>
73-
<TableCell><Label>Cell A</Label></TableCell>
74-
<TableCell><Label>Cell B</Label></TableCell>
75-
<TableCell><Label>Cell C</Label></TableCell>
76-
<TableCell><Label>Cell D</Label></TableCell>
98+
<TableCell id="row-1-colA"><Label>Cell A</Label></TableCell>
99+
<TableCell id="row-1-colB"><Label>Cell B</Label></TableCell>
100+
<TableCell id="row-1-colC"><Label>Cell C</Label></TableCell>
101+
<TableCell id="row-1-colD"><Label>Cell D</Label></TableCell>
77102
</TableRow>
78103
<TableRow>
79-
<TableCell><Label>Cell A</Label></TableCell>
80-
<TableCell><Label>Cell B</Label></TableCell>
81-
<TableCell><Label>Cell C</Label></TableCell>
82-
<TableCell><Label>Cell D</Label></TableCell>
104+
<TableCell id="row-2-colA"><Label>Cell A</Label></TableCell>
105+
<TableCell id="row-2-colB"><Label>Cell B</Label></TableCell>
106+
<TableCell id="row-2-colC"><Label>Cell C</Label></TableCell>
107+
<TableCell id="row-2-colD"><Label>Cell D</Label></TableCell>
83108
</TableRow>
84109
<TableRow>
85-
<TableCell><Label>Cell A</Label></TableCell>
86-
<TableCell><Label>Cell B</Label></TableCell>
87-
<TableCell><Label>Cell C</Label></TableCell>
88-
<TableCell><Label>Cell D</Label></TableCell>
110+
<TableCell id="row-3-colA"><Label>Cell A</Label></TableCell>
111+
<TableCell id="row-3-colB"><Label>Cell B</Label></TableCell>
112+
<TableCell id="row-3-colC"><Label>Cell C</Label></TableCell>
113+
<TableCell id="row-3-colD"><Label>Cell D</Label></TableCell>
89114
</TableRow>
90115
</Table>
91116
);
92-
});
117+
}
93118

94119
it("no pop-in width 'optimal' table width", () => {
120+
mounTable();
95121
cy.get("ui5-table").then($table => {
96122
$table.css("width", "850px");
97123
});
@@ -103,17 +129,11 @@ describe("Table - Popin Mode", () => {
103129
cy.get("ui5-table-header-cell")
104130
.should("have.length", 4);
105131

106-
cy.get("ui5-table-header-cell").each(($cell, index) => {
107-
cy.wrap($cell)
108-
.should("have.attr", "role", ROLE_COLUMN_HEADER);
109-
cy.get("ui5-table-header-row")
110-
.shadow()
111-
.find(`slot[name=default-${index + 1}]`)
112-
.should("exist");
113-
});
132+
checkPopinState({ poppedIn: [], hidden: [] });
114133
});
115134

116135
it("test with one by one popping in", () => {
136+
mounTable();
117137
const testWidths = [
118138
{ width: 850, poppedIn: [] },
119139
{ width: 700, poppedIn: ["colD"] },
@@ -127,22 +147,12 @@ describe("Table - Popin Mode", () => {
127147
$table.css("width", `${width}px`);
128148
});
129149

130-
cy.get("ui5-table-header-cell").each(($cell, index) => {
131-
const id = $cell.attr("id") ?? "";
132-
const shouldBePoppedIn = poppedIn.includes(id);
133-
const roleCondition = shouldBePoppedIn ? "not.have.attr" : "have.attr";
134-
135-
cy.wrap($cell)
136-
.should(roleCondition, "role", ROLE_COLUMN_HEADER);
137-
cy.get("ui5-table-header-row")
138-
.shadow()
139-
.find(`slot[name=default-${index + 1}]`)
140-
.should(shouldBePoppedIn ? "not.exist" : "exist");
141-
});
150+
checkPopinState({ poppedIn, hidden: [] });
142151
});
143152
});
144153

145154
it("test with one by one popping out", () => {
155+
mounTable();
146156
const testWidths = [
147157
{ width: 150, poppedIn: ["colD", "colC", "colB"] },
148158
{ width: 300, poppedIn: ["colD", "colC", "colB"] },
@@ -156,22 +166,12 @@ describe("Table - Popin Mode", () => {
156166
$table.css("width", `${width}px`);
157167
});
158168

159-
cy.get("ui5-table-header-cell").each(($cell, index) => {
160-
const id = $cell.attr("id") ?? "";
161-
const shouldBePoppedIn = poppedIn.includes(id);
162-
const roleCondition = shouldBePoppedIn ? "not.have.attr" : "have.attr";
163-
164-
cy.wrap($cell)
165-
.should(roleCondition, "role", ROLE_COLUMN_HEADER);
166-
cy.get("ui5-table-header-row")
167-
.shadow()
168-
.find(`slot[name=default-${index + 1}]`)
169-
.should(shouldBePoppedIn ? "not.exist" : "exist");
170-
});
169+
checkPopinState({ poppedIn, hidden: [] });
171170
});
172171
});
173172

174173
it("test with random widths", () => {
174+
mounTable();
175175
const expectedStates = [
176176
{ width: 500, poppedIn: ["colD", "colC", "colB"] },
177177
{ width: 700, poppedIn: ["colD", "colC"] },
@@ -187,24 +187,12 @@ describe("Table - Popin Mode", () => {
187187
});
188188

189189
const expectedState = expectedStates.find(state => state.width >= randomWidth);
190-
// eslint-disable-next-line cypress/no-unnecessary-waiting, no-loop-func
191-
cy.get("ui5-table-header-cell").each(($cell, index) => {
192-
const id = $cell.attr("id") ?? "";
193-
const shouldBePoppedIn = expectedState?.poppedIn.includes(id);
194-
const roleCondition = shouldBePoppedIn ? "not.have.attr" : "have.attr";
195-
196-
cy.wrap($cell)
197-
.should(roleCondition, "role", ROLE_COLUMN_HEADER);
198-
199-
cy.get("ui5-table-header-row")
200-
.shadow()
201-
.find(`slot[name=default-${index + 1}]`)
202-
.should(shouldBePoppedIn ? "not.exist" : "exist");
203-
});
190+
checkPopinState({ poppedIn: expectedState?.poppedIn ?? [], hidden: [] });
204191
}
205192
});
206193

207194
it("should show the popin-text in the popin area", () => {
195+
mounTable();
208196
cy.get("ui5-table").then($table => {
209197
$table.css("width", "150px");
210198
});
@@ -232,6 +220,40 @@ describe("Table - Popin Mode", () => {
232220
return popinCellCount && popinCellCount === validPopinTextCount;
233221
}).should("be.true");
234222
});
223+
224+
it("should hide column in popin if popinHidden is set", () => {
225+
mounTable(true);
226+
227+
const testWidths = [
228+
{ width: 150, poppedIn: ["colC", "colB"], hidden: ["colD"] },
229+
{ width: 300, poppedIn: ["colC", "colB"], hidden: ["colD"] },
230+
{ width: 500, poppedIn: ["colC"], hidden: ["colD"] },
231+
{ width: 700, poppedIn: [], hidden: ["colD"] },
232+
{ width: 850, poppedIn: [], hidden: [] },
233+
];
234+
235+
testWidths.forEach(({ width, poppedIn, hidden }) => {
236+
cy.get("ui5-table").then($table => {
237+
$table.css("width", `${width}px`);
238+
});
239+
240+
checkPopinState({ poppedIn, hidden });
241+
});
242+
});
243+
244+
it("should hide popin if popinHidden, shows it if changed on runtime", () => {
245+
mounTable(true);
246+
cy.get("ui5-table").then($table => {
247+
$table.css("width", "150px");
248+
});
249+
250+
checkPopinState({ poppedIn: ["colC", "colB"], hidden: ["colD"] });
251+
252+
cy.get("#colD")
253+
.invoke("removeAttr", "popin-hidden");
254+
255+
checkPopinState({ poppedIn: ["colC", "colB", "colD"], hidden: [] });
256+
});
235257
});
236258

237259
describe("Table - Horizontal alignment of cells", () => {

packages/main/src/Table.ts

+19-17
Original file line numberDiff line numberDiff line change
@@ -505,23 +505,6 @@ class Table extends UI5Element {
505505
scrollElementIntoView(this._scrollContainer, e.target as HTMLElement, this._stickyElements, this.effectiveDir === "rtl");
506506
}
507507

508-
/**
509-
* Refreshes the popin state of the columns.
510-
* Syncs the popin state of the columns with the popin state of the header cells.
511-
* This is needed when additional rows are manually added and no resize happens.
512-
* @private
513-
*/
514-
_refreshPopinState() {
515-
this.headerRow[0]?.cells.forEach((header, index) => {
516-
this.rows.forEach(row => {
517-
const cell = row.cells[index];
518-
if (cell && cell._popin !== header._popin) {
519-
cell._popin = header._popin;
520-
}
521-
});
522-
});
523-
}
524-
525508
_onGrow() {
526509
this._growing?.loadMore();
527510
}
@@ -539,11 +522,30 @@ class Table extends UI5Element {
539522
return headers;
540523
}
541524

525+
/**
526+
* Refreshes the popin state of the columns.
527+
* Syncs the popin state of the columns with the popin state of the header cells.
528+
* This is needed when additional rows are manually added and no resize happens.
529+
* @private
530+
*/
531+
_refreshPopinState() {
532+
this.headerRow[0]?.cells.forEach((header, index) => {
533+
this.rows.forEach(row => {
534+
const cell = row.cells[index];
535+
if (cell) {
536+
cell._popinHidden = header.popinHidden;
537+
cell._popin = header._popin;
538+
}
539+
});
540+
});
541+
}
542+
542543
_setHeaderPopinState(headerCell: TableHeaderCell, inPopin: boolean, popinWidth: number) {
543544
const headerIndex = this.headerRow[0].cells.indexOf(headerCell);
544545
headerCell._popin = inPopin;
545546
headerCell._popinWidth = popinWidth;
546547
this.rows.forEach(row => {
548+
row.cells[headerIndex]._popinHidden = headerCell.popinHidden;
547549
row.cells[headerIndex]._popin = inPopin;
548550
});
549551
}

packages/main/src/TableCellBase.ts

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ abstract class TableCellBase extends UI5Element {
4141
@property({ type: Boolean })
4242
_popin = false;
4343

44+
@property({ type: Boolean, noAttribute: true })
45+
_popinHidden = false;
46+
4447
protected ariaRole: string = "gridcell";
4548

4649
@i18n("@ui5/webcomponents")

packages/main/src/TableHeaderCell.ts

+13
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ class TableHeaderCell extends TableCellBase {
100100
@property()
101101
sortIndicator: `${SortOrder}` = "None";
102102

103+
/**
104+
* Defines if the column is hidden in the popin.
105+
*
106+
* **Note:** Please be aware that hiding the column in the popin might lead to accessibility issues as
107+
* users might not be able to access the content of the column on small screens.
108+
*
109+
* @default false
110+
* @since 2.8.0
111+
* @public
112+
*/
113+
@property({ type: Boolean })
114+
popinHidden: boolean = false;
115+
103116
/**
104117
* Defines the action of the column.
105118
*

packages/main/src/TableHeaderRow.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class TableHeaderRow extends TableRowBase {
5656
type: HTMLElement,
5757
"default": true,
5858
invalidateOnChildChange: {
59-
properties: ["width", "_popin", "horizontalAlign"],
59+
properties: ["width", "_popin", "horizontalAlign", "popinHidden"],
6060
slots: false,
6161
},
6262
individualSlots: true,

packages/main/src/TableRow.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class TableRow extends TableRowBase {
4848
"default": true,
4949
individualSlots: true,
5050
invalidateOnChildChange: {
51-
properties: ["_popin"],
51+
properties: ["_popin", "_popinHidden"],
5252
slots: false,
5353
},
5454
})

packages/main/src/TableRowBase.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ abstract class TableRowBase extends UI5Element {
110110
}
111111

112112
get _popinCells() {
113-
return this.cells.filter(c => c._popin);
113+
return this.cells.filter(c => c._popin && !c._popinHidden);
114114
}
115115

116116
get _stickyCells() {

0 commit comments

Comments
 (0)