Skip to content

Commit d5ab16a

Browse files
authored
feat(ui5-table-group-row): introduce new component (#3470)
The new type of row represents group header row which can be used in case a grouping in the table is required. More information and samples can be found here: https://sap.github.io/ui5-webcomponents/playground/components/Table/ Fixes #3319
1 parent 19b0a5b commit d5ab16a

12 files changed

+542
-14
lines changed

packages/main/bundle.common.js

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import TabSeparator from "./dist/TabSeparator.js";
7474
import Table from "./dist/Table.js";
7575
import TableColumn from "./dist/TableColumn.js";
7676
import TableRow from "./dist/TableRow.js";
77+
import TableGroupRow from "./dist/TableGroupRow.js";
7778
import TableCell from "./dist/TableCell.js";
7879
import TextArea from "./dist/TextArea.js";
7980
import TimeSelection from "./dist/TimeSelection.js";

packages/main/src/Table.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
LOAD_MORE_TEXT,
1919
ARIA_LABEL_SELECT_ALL_CHECKBOX,
2020
TABLE_HEADER_ROW_TEXT,
21+
TABLE_ROW_POSITION,
2122
} from "./generated/i18n/i18n-defaults.js";
2223

2324
// Template
@@ -377,7 +378,7 @@ const metadata = {
377378
* @alias sap.ui.webcomponents.main.Table
378379
* @extends sap.ui.webcomponents.base.UI5Element
379380
* @tagname ui5-table
380-
* @appenddocs TableColumn TableRow TableCell
381+
* @appenddocs TableColumn TableRow TableGroupRow TableCell
381382
* @public
382383
*/
383384
class Table extends UI5Element {
@@ -433,13 +434,15 @@ class Table extends UI5Element {
433434
onBeforeRendering() {
434435
const columnSettings = this.getColumnPropagationSettings();
435436
const columnSettingsString = JSON.stringify(columnSettings);
437+
const rowsCount = this.rows.length;
436438

437-
this.rows.forEach(row => {
439+
this.rows.forEach((row, index) => {
438440
if (row._columnsInfoString !== columnSettingsString) {
439441
row._columnsInfo = columnSettings;
440442
row._columnsInfoString = JSON.stringify(row._columnsInfo);
441443
}
442444

445+
row._ariaPosition = this.i18nBundle.getText(TABLE_ROW_POSITION, index + 1, rowsCount);
443446
row._busy = this.busy;
444447
row.removeEventListener("ui5-_focused", this.fnOnRowFocused);
445448
row.addEventListener("ui5-_focused", this.fnOnRowFocused);

packages/main/src/TableGroupRow.hbs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<tr
2+
class="ui5-table-group-row-root"
3+
part="group-row"
4+
role="row"
5+
aria-label={{ariaLabelText}}
6+
tabindex="{{_tabIndex}}"
7+
dir="{{effectiveDir}}"
8+
>
9+
<td colspan={{colSpan}}>
10+
<slot></slot>
11+
</td>
12+
</tr>

packages/main/src/TableGroupRow.js

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
2+
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
3+
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
4+
import TableGroupRowTemplate from "./generated/templates/TableGroupRowTemplate.lit.js";
5+
import TableMode from "./types/TableMode.js";
6+
7+
// Texts
8+
import {
9+
TABLE_GROUP_ROW_ARIA_LABEL,
10+
} from "./generated/i18n/i18n-defaults.js";
11+
12+
// Styles
13+
import styles from "./generated/themes/TableGroupRow.css.js";
14+
15+
/**
16+
* @public
17+
*/
18+
const metadata = {
19+
tag: "ui5-table-group-row",
20+
slots: /** @lends sap.ui.webcomponents.main.TableGroupRow.prototype */ {
21+
/**
22+
* Defines the text of the component.
23+
* <br>
24+
* <b>Note:</b> Although this slot accepts HTML Elements, it is strongly recommended that you only use text in order to preserve the intended design.
25+
*
26+
* @type {Node[]}
27+
* @slot
28+
* @public
29+
*/
30+
"default": {
31+
type: Node,
32+
},
33+
},
34+
properties: /** @lends sap.ui.webcomponents.main.TableGroupRow.prototype */ {
35+
/**
36+
* Defines the mode of the row
37+
*
38+
* <br><br>
39+
* <b>Note:</b>
40+
* Available options are:
41+
* <ul>
42+
* <li><code>None</code></li>
43+
* <li><code>SingleSelect</code></li>
44+
* <li><code>MultiSelect</code></li>
45+
* </ul>
46+
* @type {TableMode}
47+
* @defaultvalue "None"
48+
* @private
49+
*/
50+
mode: {
51+
type: TableMode,
52+
defaultValue: TableMode.None,
53+
},
54+
_columnsInfo: {
55+
type: Object,
56+
multiple: true,
57+
},
58+
_tabIndex: {
59+
type: String,
60+
defaultValue: "-1",
61+
},
62+
_busy: {
63+
type: Boolean,
64+
},
65+
_ariaPosition: {
66+
type: String,
67+
defaultValue: "",
68+
noAttribute: true,
69+
},
70+
},
71+
};
72+
73+
/**
74+
* @class
75+
*
76+
* <h3 class="comment-api-title">Overview</h3>
77+
*
78+
* The <code>ui5-table-group-row</code> component represents a group row in the <code>ui5-table</code>.
79+
*
80+
* <h3>CSS Shadow Parts</h3>
81+
*
82+
* <ui5-link target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/::part">CSS Shadow Parts</ui5-link> allow developers to style elements inside the Shadow DOM.
83+
* <br>
84+
* The <code>ui5-table-group-row</code> exposes the following CSS Shadow Parts:
85+
* <ul>
86+
* <li>group-row - Used to style the native <code>tr</code> tag element.</li>
87+
* </ul>
88+
*
89+
* @constructor
90+
* @author SAP SE
91+
* @alias sap.ui.webcomponents.main.TableGroupRow
92+
* @extends sap.ui.webcomponents.base.UI5Element
93+
* @tagname ui5-table-group-row
94+
* @since 1.0.0-rc.15
95+
* @public
96+
*/
97+
class TableGroupRow extends UI5Element {
98+
static get metadata() {
99+
return metadata;
100+
}
101+
102+
static get styles() {
103+
return styles;
104+
}
105+
106+
static get render() {
107+
return litRender;
108+
}
109+
110+
static get template() {
111+
return TableGroupRowTemplate;
112+
}
113+
114+
constructor() {
115+
super();
116+
this.i18nBundle = getI18nBundle("@ui5/webcomponents");
117+
}
118+
119+
get colSpan() {
120+
return this._colSpan;
121+
}
122+
123+
get ariaLabelText() {
124+
return `${this.i18nBundle.getText(TABLE_GROUP_ROW_ARIA_LABEL)} ${this.innerText}. ${this._ariaPosition}`;
125+
}
126+
127+
visibleColCount() {
128+
let count = this._columnsInfo.reduce((acc, column) => {
129+
return column.visible ? ++acc : acc;
130+
}, 0);
131+
132+
if (this.mode === TableMode.MultiSelect) {
133+
count++;
134+
}
135+
136+
return count;
137+
}
138+
139+
onBeforeRendering() {
140+
if (!this._columnsInfo || this._columnsInfo.length === 0) {
141+
return;
142+
}
143+
this._colSpan = this.visibleColCount();
144+
}
145+
146+
static async onDefine() {
147+
await fetchI18nBundle("@ui5/webcomponents");
148+
}
149+
}
150+
151+
TableGroupRow.define();
152+
153+
export default TableGroupRow;

packages/main/src/TableRow.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ const metadata = {
101101
_busy: {
102102
type: Boolean,
103103
},
104+
_ariaPosition: {
105+
type: String,
106+
defaultValue: "",
107+
noAttribute: true,
108+
},
104109
},
105110
events: /** @lends sap.ui.webcomponents.main.TableRow.prototype */ {
106111
/**
@@ -341,11 +346,12 @@ class TableRow extends UI5Element {
341346
}
342347

343348
get ariaLabelText() {
344-
return this.cells.map((cell, index) => {
349+
const ariaLabel = this.cells.map((cell, index) => {
345350
const columText = this.getColumnTextByIdx(index);
346351
const cellText = this.getCellText(cell);
347352
return `${columText} ${cellText}`;
348353
}).join(" ");
354+
return `${ariaLabel}. ${this._ariaPosition}`;
349355
}
350356

351357
get ariaLabelRowSelection() {

packages/main/src/i18n/messagebundle.properties

+6
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ LOAD_MORE_TEXT=More
187187
#XTXT Table's header row text.
188188
TABLE_HEADER_ROW_TEXT=Header Row
189189

190+
#XACT Table row's position
191+
TABLE_ROW_POSITION={0} of {1}
192+
193+
#XACT Table group row's aria label
194+
TABLE_GROUP_ROW_ARIA_LABEL=Group header row.
195+
190196
#XACT ARIA label for selection checkbox
191197
ARIA_LABEL_ROW_SELECTION=Item selection
192198

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
:host {
2+
display: contents;
3+
}
4+
5+
:host([_busy]) .ui5-table-group-row-root {
6+
opacity: 0.72;
7+
pointer-events: none;
8+
}
9+
10+
.ui5-table-group-row-root {
11+
height: 2rem;
12+
border-bottom: 1px solid var(--sapList_TableGroupHeaderBorderColor);
13+
background-color: var(--sapList_TableGroupHeaderBackground);
14+
color: var(--sapList_TableGroupHeaderTextColor);
15+
font-family: "72override", var(--sapFontFamily);
16+
font-size: var(--sapFontSize);
17+
font-weight: normal;
18+
}
19+
20+
.ui5-table-group-row-root:focus {
21+
outline: var(--ui5_table_row_outline_width) dotted var(--sapContent_FocusColor);
22+
outline-offset: -0.0625rem;
23+
}
24+
25+
td {
26+
word-break: break-word;
27+
vertical-align: middle;
28+
padding: .5rem .25rem .5rem 1rem;
29+
text-align: left;
30+
}
31+
32+
:host [dir="rtl"] td {
33+
text-align: right;
34+
}
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<title>Web components Table</title>
8+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
9+
<script data-ui5-config type="application/json">
10+
{
11+
"language": "EN"
12+
}
13+
</script>
14+
15+
<script src="../../webcomponentsjs/webcomponents-loader.js"></script>
16+
<script src="../../resources/bundle.esm.js" type="module"></script>
17+
<script nomodule src="../../resources/bundle.es5.js"></script>
18+
19+
</head>
20+
21+
<body style="background-color: var(--sapBackgroundColor);">
22+
23+
<ui5-title>Table with grouping:</ui5-title>
24+
<ui5-table class="demo-table-single" id="groupedSingleTable">
25+
<ui5-table-column id="column-1" slot="columns">
26+
<ui5-label>City</ui5-label>
27+
</ui5-table-column>
28+
<ui5-table-column id="column-2" slot="columns" min-width="500" popin-text="Supplier">
29+
<ui5-label>Supplier</ui5-label>
30+
</ui5-table-column>
31+
<ui5-table-column id="column-3" slot="columns" min-width="500" popin-text="Country" demand-popin>
32+
<div class="column-content">
33+
<ui5-label>Country</ui5-label>
34+
</div>
35+
</ui5-table-column>
36+
37+
<ui5-table-group-row>Country: Bulgaria</ui5-table-group-row>
38+
39+
<ui5-table-row>
40+
<ui5-table-cell><span>Sofia</span></ui5-table-cell>
41+
<ui5-table-cell><span>Sirenje EOOD</span></ui5-table-cell>
42+
<ui5-table-cell><span>Bulgaria</span></ui5-table-cell>
43+
</ui5-table-row>
44+
<ui5-table-row>
45+
<ui5-table-cell><span>Plovdiv</span></ui5-table-cell>
46+
<ui5-table-cell><span>Kashkavali AD</span></ui5-table-cell>
47+
<ui5-table-cell><span>Bulgaria</span></ui5-table-cell>
48+
</ui5-table-row>
49+
<ui5-table-group-row><span>Country: USA</span></ui5-table-group-row>
50+
<ui5-table-row>
51+
<ui5-table-cell><span>Dublin</span></ui5-table-cell>
52+
<ui5-table-cell><span>J.M. Brothers</span></ui5-table-cell>
53+
<ui5-table-cell><span>USA</span></ui5-table-cell>
54+
</ui5-table-row>
55+
<ui5-table-row>
56+
<ui5-table-cell><span>Boston</span></ui5-table-cell>
57+
<ui5-table-cell><span>J.M. Brothers</span></ui5-table-cell>
58+
<ui5-table-cell><span>USA</span></ui5-table-cell>
59+
</ui5-table-row>
60+
</ui5-table>
61+
62+
<br>
63+
<hr>
64+
<br>
65+
66+
<ui5-title>MultiSelect Table with grouping:</ui5-title>
67+
<ui5-table class="demo-table-multi" id="groupedMultiTable" mode="MultiSelect">
68+
<ui5-table-column id="column-1" slot="columns">
69+
<ui5-label>City</ui5-label>
70+
</ui5-table-column>
71+
<ui5-table-column id="column-2" slot="columns" min-width="500" popin-text="Supplier">
72+
<ui5-label>Supplier</ui5-label>
73+
</ui5-table-column>
74+
<ui5-table-column id="column-3" slot="columns" min-width="500" popin-text="Country" demand-popin>
75+
<div class="column-content">
76+
<ui5-label>Country</ui5-label>
77+
</div>
78+
</ui5-table-column>
79+
80+
<ui5-table-group-row>Country: Bulgaria</ui5-table-group-row>
81+
<ui5-table-row>
82+
<ui5-table-cell><span>Sofia</span></ui5-table-cell>
83+
<ui5-table-cell><span>Sirenje EOOD</span></ui5-table-cell>
84+
<ui5-table-cell><span>Bulgaria</span></ui5-table-cell>
85+
</ui5-table-row>
86+
<ui5-table-row>
87+
<ui5-table-cell><span>Plovdiv</span></ui5-table-cell>
88+
<ui5-table-cell><span>Kashkavali AD</span></ui5-table-cell>
89+
<ui5-table-cell><span>Bulgaria</span></ui5-table-cell>
90+
</ui5-table-row>
91+
<ui5-table-group-row>Country: USA</ui5-table-group-row>
92+
<ui5-table-row>
93+
<ui5-table-cell><span>Dublin</span></ui5-table-cell>
94+
<ui5-table-cell><span>J.M. Brothers</span></ui5-table-cell>
95+
<ui5-table-cell><span>USA</span></ui5-table-cell>
96+
</ui5-table-row>
97+
<ui5-table-row>
98+
<ui5-table-cell><span>Boston</span></ui5-table-cell>
99+
<ui5-table-cell><span>J.M. Brothers</span></ui5-table-cell>
100+
<ui5-table-cell><span>USA</span></ui5-table-cell>
101+
</ui5-table-row>
102+
</ui5-table>
103+
104+
105+
</body>
106+
107+
</html>

0 commit comments

Comments
 (0)