Skip to content

Commit fa4a7b7

Browse files
committed
feat(ui5-table): action header cell is added
1 parent 99faaa8 commit fa4a7b7

19 files changed

+279
-40
lines changed

packages/main/src/TableCell.hbs

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
{{#if _popin}}
2-
{{#if _popinText}}
3-
{{_popinText}}
4-
<span class="popin-colon">{{_i18nPopinColon}}</span>
5-
{{else if _popinHeader}}
6-
{{_popinHeader}}
7-
<span class="popin-colon">{{_i18nPopinColon}}</span>
8-
{{/if}}
9-
<slot></slot>
10-
{{else}}
11-
<slot></slot>
12-
{{/if}}
2+
{{#each _popinHeaderNodes}}
3+
{{this}}
4+
{{/each}}
5+
<span class="popin-colon">{{_i18nPopinColon}}</span>
6+
{{/if}}
7+
<slot></slot>

packages/main/src/TableCell.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,18 @@ class TableCell extends TableCellBase {
4646
return table.headerRow[0].cells[index];
4747
}
4848

49-
get _popinText() {
50-
return this._headerCell?.popinText;
51-
}
52-
53-
get _popinHeader() {
54-
return this._headerCell?.content[0]?.cloneNode(true);
49+
get _popinHeaderNodes() {
50+
const nodes = [];
51+
const headerCell = this._headerCell;
52+
if (headerCell.popinText) {
53+
nodes.push(headerCell.popinText);
54+
} else {
55+
nodes.push(...this._headerCell.content.map(node => node.cloneNode(true)));
56+
}
57+
if (headerCell.action[0]) {
58+
nodes.push(headerCell.action[0].cloneNode(true));
59+
}
60+
return nodes;
5561
}
5662

5763
get _i18nPopinColon() {

packages/main/src/TableHeaderCell.hbs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
<slot></slot>
1+
<slot name="action"></slot>
2+
<slot></slot>
3+
{{#if _sortIcon}}
4+
<ui5-icon name="{{_sortIcon}}"></ui5-icon>
5+
{{/if}}

packages/main/src/TableHeaderCell.ts

+39-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
2-
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
1+
import { customElement, property, slot } from "@ui5/webcomponents-base/dist/decorators.js";
32
import TableCellBase from "./TableCellBase.js";
43
import TableHeaderCellTemplate from "./generated/templates/TableHeaderCellTemplate.lit.js";
54
import TableHeaderCellStyles from "./generated/themes/TableHeaderCell.css.js";
5+
import Icon from "./Icon.js";
6+
import TableSortOrder from "./types/TableSortOrder.js";
7+
import type TableHeaderCellActionBase from "./TableHeaderCellActionBase.js";
8+
import "@ui5/webcomponents-icons/dist/sort-ascending.js";
9+
import "@ui5/webcomponents-icons/dist/sort-descending.js";
610

711
/**
812
* @class
@@ -28,6 +32,7 @@ import TableHeaderCellStyles from "./generated/themes/TableHeaderCell.css.js";
2832
tag: "ui5-table-header-cell",
2933
styles: [TableCellBase.styles, TableHeaderCellStyles],
3034
template: TableHeaderCellTemplate,
35+
dependencies: [Icon],
3136
})
3237
class TableHeaderCell extends TableCellBase {
3338
/**
@@ -85,6 +90,27 @@ class TableHeaderCell extends TableCellBase {
8590
@property()
8691
popinText?: string;
8792

93+
/**
94+
* Defines the sort indicator of the column.
95+
*
96+
* @default "None"
97+
* @since 2.7.0
98+
* @public
99+
*/
100+
@property()
101+
sortIndicator: `${TableSortOrder}` = "None";
102+
103+
/**
104+
* Defines the action of the column.
105+
*
106+
* **Note:** Only one `action` is allowed.
107+
*
108+
* @public
109+
* @since 2.7.0
110+
*/
111+
@slot()
112+
action!: Array<TableHeaderCellActionBase>;
113+
88114
@property({ type: Boolean, noAttribute: true })
89115
_popin = false;
90116

@@ -104,6 +130,17 @@ class TableHeaderCell extends TableCellBase {
104130
// overwrite setting of TableCellBase so that the TableHeaderCell always uses the slot variable
105131
this.style.justifyContent = `var(--horizontal-align-${this._individualSlot})`;
106132
}
133+
if (this.sortIndicator !== TableSortOrder.None) {
134+
this.setAttribute("aria-sort", this.sortIndicator.toLowerCase());
135+
} else if (this.hasAttribute("aria-sort")) {
136+
this.removeAttribute("aria-sort");
137+
}
138+
}
139+
140+
get _sortIcon() {
141+
if (this.sortIndicator !== TableSortOrder.None) {
142+
return `sort-${this.sortIndicator.toLowerCase()}`;
143+
}
107144
}
108145
}
109146

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { customElement, i18n } from "@ui5/webcomponents-base/dist/decorators.js";
2+
import TableHeaderCellActionBase from "./TableHeaderCellActionBase.js";
3+
import { TABLE_GENERATED_BY_AI } from "./generated/i18n/i18n-defaults.js";
4+
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
5+
import "@ui5/webcomponents-icons/dist/ai.js";
6+
7+
/**
8+
* @class
9+
*
10+
* ### Overview
11+
*
12+
* The `ui5-table-header-cell-action-ai` component defines a dedicated AI action for the table column.
13+
*
14+
* ### ES6 Module Import
15+
*
16+
* `import "@ui5/webcomponents/dist/TableHeaderCellActionAI.js";`
17+
*
18+
* @constructor
19+
* @extends TableHeaderCellActionBase
20+
* @since 2.7.0
21+
* @public
22+
*/
23+
@customElement({ tag: "ui5-table-header-cell-action-ai" })
24+
25+
class TableHeaderCellActionAI extends TableHeaderCellActionBase {
26+
@i18n("@ui5/webcomponents")
27+
static i18nBundle: I18nBundle;
28+
29+
getRenderInfo() {
30+
return {
31+
icon: "ai",
32+
tooltip: TableHeaderCellActionAI.i18nBundle.getText(TABLE_GENERATED_BY_AI),
33+
};
34+
}
35+
}
36+
37+
TableHeaderCellActionAI.define();
38+
39+
export default TableHeaderCellActionAI;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<ui5-button
2+
icon="{{_icon}}"
3+
tooltip="{{_tooltip}}"
4+
@click={{_onClick}}
5+
design="Transparent">
6+
</ui5-button>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
2+
import { customElement, eventStrict } from "@ui5/webcomponents-base/dist/decorators.js";
3+
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
4+
import TableHeaderCellActionBaseTemplate from "./generated/templates/TableHeaderCellActionBaseTemplate.lit.js";
5+
import TableHeaderCellActionBaseStyles from "./generated/themes/TableHeaderCellActionBase.css.js";
6+
import Button from "./Button.js";
7+
import type TableCell from "./TableCell.js";
8+
9+
/**
10+
* @class
11+
* The `TableHeaderCellActionBase` class serves as a foundation for table header cell actions.
12+
* @constructor
13+
* @abstract
14+
* @extends UI5Element
15+
* @since 2.7.0
16+
* @public
17+
*/
18+
@customElement({
19+
renderer: litRender,
20+
styles: TableHeaderCellActionBaseStyles,
21+
template: TableHeaderCellActionBaseTemplate,
22+
dependencies: [Button],
23+
})
24+
25+
/**
26+
* Fired when an action is clicked.
27+
*
28+
* @public
29+
* @since 2.7.0
30+
*/
31+
@eventStrict("click", {
32+
bubbles: false,
33+
})
34+
35+
abstract class TableHeaderCellActionBase extends UI5Element {
36+
eventDetails!: {
37+
"click": void
38+
}
39+
40+
abstract getRenderInfo(): {
41+
icon: string;
42+
tooltip: string;
43+
};
44+
45+
onBeforeRendering() {
46+
this.toggleAttribute("_popin", !this.parentElement);
47+
}
48+
49+
_onClick(e: MouseEvent) {
50+
const action = this.parentElement ? this : ((this.getRootNode() as ShadowRoot).host as TableCell)._headerCell.action[0] as this;
51+
action.fireDecoratorEvent("click");
52+
e.stopPropagation();
53+
}
54+
55+
get _tooltip() {
56+
return this.getRenderInfo().tooltip;
57+
}
58+
59+
get _icon() {
60+
return this.getRenderInfo().icon;
61+
}
62+
}
63+
64+
export default TableHeaderCellActionBase;

packages/main/src/TableHeaderRow.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
2-
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
3-
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
1+
import { customElement, slot, property } from "@ui5/webcomponents-base/dist/decorators.js";
42
import TableRowBase from "./TableRowBase.js";
53
import TableHeaderRowTemplate from "./generated/templates/TableHeaderRowTemplate.lit.js";
64
import TableHeaderRowStyles from "./generated/themes/TableHeaderRow.css.js";

packages/main/src/TableRowActionBase.hbs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{{else if _isInteractive}}
44
<ui5-button
55
icon="{{_icon}}"
6-
text="{{_text}}"
76
tooltip="{{_text}}"
87
@click={{_onActionClick}}
98
design="Transparent">
@@ -12,6 +11,6 @@
1211
<ui5-icon
1312
name="{{_icon}}"
1413
tooltip="{{_text}}"
15-
design="Transparent">
14+
design="NonInteractive">
1615
</ui5-icon>
1716
{{/if}}

packages/main/src/TableRowActionBase.ts

-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ import { customElement, property } from "@ui5/webcomponents-base/dist/decorators
33
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
44
import TableRowActionBaseTemplate from "./generated/templates/TableRowActionBaseTemplate.lit.js";
55
import TableRowActionBaseStyles from "./generated/themes/TableRowActionBase.css.js";
6-
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
76
import Icon from "./Icon.js";
87
import Button from "./Button.js";
98
import type Menu from "./Menu.js";
109
import type MenuItem from "./MenuItem.js";
1110
import type Table from "./Table.js";
1211
import type TableRow from "./TableRow.js";
1312
import type TableRowAction from "./TableRowAction.js";
14-
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
1513

1614
let MenuConstructor: new () => Menu;
1715
let MenuItemConstructor: new () => MenuItem;
@@ -44,9 +42,6 @@ abstract class TableRowActionBase extends UI5Element {
4442
@property({ type: Boolean })
4543
invisible = false;
4644

47-
@i18n("@ui5/webcomponents")
48-
static i18nBundle: I18nBundle;
49-
5045
private static _menu: Menu;
5146
private static _menuItems = new WeakMap();
5247
static async showMenu(actions: TableRowActionBase[], opener: HTMLElement) {

packages/main/src/TableRowActionNavigation.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
2-
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
1+
import { customElement, property, i18n } from "@ui5/webcomponents-base/dist/decorators.js";
32
import TableRowActionBase from "./TableRowActionBase.js";
43
import { TABLE_NAVIGATION } from "./generated/i18n/i18n-defaults.js";
54
import "@ui5/webcomponents-icons/dist/navigation-right-arrow.js";
5+
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
66

77
/**
88
* @class
9-
* The `TableRowActionNavigation` class defines a navigation actio‚n for table rows.
9+
*
10+
* ### Overview
11+
*
12+
* The `ui5-table-row-action-navigation` component defines a navigation action for table rows.
13+
*
14+
* ### ES6 Module Import
15+
*
16+
* `import "@ui5/webcomponents/dist/TableRowActionNavigation.js";`
17+
*
1018
* @constructor
1119
* @extends TableRowActionBase
1220
* @since 2.7.0
@@ -24,6 +32,9 @@ class TableRowActionNavigation extends TableRowActionBase {
2432
@property({ type: Boolean })
2533
interactive = false;
2634

35+
@i18n("@ui5/webcomponents")
36+
static i18nBundle: I18nBundle;
37+
2738
getRenderInfo() {
2839
return {
2940
text: this._i18nNavigation,
@@ -37,7 +48,7 @@ class TableRowActionNavigation extends TableRowActionBase {
3748
}
3849

3950
get _i18nNavigation() {
40-
return TableRowActionBase.i18nBundle.getText(TABLE_NAVIGATION);
51+
return TableRowActionNavigation.i18nBundle.getText(TABLE_NAVIGATION);
4152
}
4253
}
4354

packages/main/src/bundle.esm.ts

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import FormGroup from "./FormGroup.js";
5656
import FileUploader from "./FileUploader.js";
5757
import Table from "./Table.js";
5858
import TableHeaderCell from "./TableHeaderCell.js";
59+
import TableHeaderCellActionAI from "./TableHeaderCellActionAI.js";
5960
import TableHeaderRow from "./TableHeaderRow.js";
6061
import TableGrowing from "./TableGrowing.js";
6162
import TableSelection from "./TableSelection.js";

packages/main/src/i18n/messagebundle.properties

+2
Original file line numberDiff line numberDiff line change
@@ -620,3 +620,5 @@ TABLE_MORE_DESCRIPTION=To load more rows, press Enter or Space
620620
TABLE_ROW_ACTIONS=Row Actions
621621
#XACT: ARIA description for the row action navigation
622622
TABLE_NAVIGATION=Navigation
623+
#XTOL: Tooltip for the AI icon in the column header to indicate that the column is generated by AI
624+
TABLE_GENERATED_BY_AI=Generated by AI

packages/main/src/themes/TableCell.css

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
:host([_popin]) {
2+
color: var(--sapContent_LabelColor);
23
padding-inline-start: 0;
34
padding-inline-end: 0;
45
align-items: center;
+20-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
:host {
2-
font-family: var(--sapFontSemiboldDuplexFamily);
3-
color: var(--sapList_HeaderTextColor);
2+
font-family: var(--sapFontSemiboldDuplexFamily);
3+
color: var(--sapList_HeaderTextColor);
4+
align-items: center;
5+
flex-wrap: nowrap;
6+
max-width: 100%;
7+
gap: 0.125rem;
48
}
59

610
:host(:empty) {
7-
padding: 0;
11+
padding: 0;
12+
}
13+
14+
[ui5-icon] {
15+
margin-inline-start: 0.375rem;
16+
width: 1rem;
17+
height: 1rem;
18+
flex-shrink: 0;
19+
}
20+
21+
::slotted([ui5-label]) {
22+
color: inherit;
23+
font-family: inherit;
24+
overflow: hidden;
825
}

0 commit comments

Comments
 (0)