Skip to content

Commit

Permalink
feat(ui5-table): action header cell is added
Browse files Browse the repository at this point in the history
  • Loading branch information
aborjinik committed Feb 5, 2025
1 parent b37af30 commit af907a3
Show file tree
Hide file tree
Showing 19 changed files with 279 additions and 40 deletions.
17 changes: 6 additions & 11 deletions packages/main/src/TableCell.hbs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
{{#if _popin}}
{{#if _popinText}}
{{_popinText}}
<span class="popin-colon">{{_i18nPopinColon}}</span>
{{else if _popinHeader}}
{{_popinHeader}}
<span class="popin-colon">{{_i18nPopinColon}}</span>
{{/if}}
<slot></slot>
{{else}}
<slot></slot>
{{/if}}
{{#each _popinHeaderNodes}}
{{this}}
{{/each}}
<span class="popin-colon">{{_i18nPopinColon}}</span>
{{/if}}
<slot></slot>
18 changes: 12 additions & 6 deletions packages/main/src/TableCell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,18 @@ class TableCell extends TableCellBase {
return table.headerRow[0].cells[index];
}

get _popinText() {
return this._headerCell?.popinText;
}

get _popinHeader() {
return this._headerCell?.content[0]?.cloneNode(true);
get _popinHeaderNodes() {
const nodes = [];
const headerCell = this._headerCell;
if (headerCell.popinText) {
nodes.push(headerCell.popinText);
} else {
nodes.push(...this._headerCell.content.map(node => node.cloneNode(true)));
}
if (headerCell.action[0]) {
nodes.push(headerCell.action[0].cloneNode(true));
}
return nodes;
}

get _i18nPopinColon() {
Expand Down
6 changes: 5 additions & 1 deletion packages/main/src/TableHeaderCell.hbs
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
<slot></slot>
<slot name="action"></slot>
<slot></slot>
{{#if _sortIcon}}
<ui5-icon name="{{_sortIcon}}"></ui5-icon>
{{/if}}
41 changes: 39 additions & 2 deletions packages/main/src/TableHeaderCell.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import { customElement, property, slot } from "@ui5/webcomponents-base/dist/decorators.js";
import TableCellBase from "./TableCellBase.js";
import TableHeaderCellTemplate from "./generated/templates/TableHeaderCellTemplate.lit.js";
import TableHeaderCellStyles from "./generated/themes/TableHeaderCell.css.js";
import Icon from "./Icon.js";
import TableSortOrder from "./types/TableSortOrder.js";
import type TableHeaderCellActionBase from "./TableHeaderCellActionBase.js";
import "@ui5/webcomponents-icons/dist/sort-ascending.js";
import "@ui5/webcomponents-icons/dist/sort-descending.js";

/**
* @class
Expand All @@ -28,6 +32,7 @@ import TableHeaderCellStyles from "./generated/themes/TableHeaderCell.css.js";
tag: "ui5-table-header-cell",
styles: [TableCellBase.styles, TableHeaderCellStyles],
template: TableHeaderCellTemplate,
dependencies: [Icon],
})
class TableHeaderCell extends TableCellBase {
/**
Expand Down Expand Up @@ -85,6 +90,27 @@ class TableHeaderCell extends TableCellBase {
@property()
popinText?: string;

/**
* Defines the sort indicator of the column.
*
* @default "None"
* @since 2.7.0
* @public
*/
@property()
sortIndicator: `${TableSortOrder}` = "None";

/**
* Defines the action of the column.
*
* **Note:** Only one `action` is allowed.
*
* @public
* @since 2.7.0
*/
@slot()
action!: Array<TableHeaderCellActionBase>;

@property({ type: Boolean, noAttribute: true })
_popin = false;

Expand All @@ -104,6 +130,17 @@ class TableHeaderCell extends TableCellBase {
// overwrite setting of TableCellBase so that the TableHeaderCell always uses the slot variable
this.style.justifyContent = `var(--horizontal-align-${this._individualSlot})`;
}
if (this.sortIndicator !== TableSortOrder.None) {
this.setAttribute("aria-sort", this.sortIndicator.toLowerCase());
} else if (this.hasAttribute("aria-sort")) {
this.removeAttribute("aria-sort");
}
}

get _sortIcon() {
if (this.sortIndicator !== TableSortOrder.None) {
return `sort-${this.sortIndicator.toLowerCase()}`;
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions packages/main/src/TableHeaderCellActionAI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { customElement, i18n } from "@ui5/webcomponents-base/dist/decorators.js";
import TableHeaderCellActionBase from "./TableHeaderCellActionBase.js";
import { TABLE_GENERATED_BY_AI } from "./generated/i18n/i18n-defaults.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import "@ui5/webcomponents-icons/dist/ai.js";

/**
* @class
*
* ### Overview
*
* The `ui5-table-header-cell-action-ai` component defines a dedicated AI action for the table column.
*
* ### ES6 Module Import
*
* `import "@ui5/webcomponents/dist/TableHeaderCellActionAI.js";`
*
* @constructor
* @extends TableHeaderCellActionBase
* @since 2.7.0
* @public
*/
@customElement({ tag: "ui5-table-header-cell-action-ai" })

class TableHeaderCellActionAI extends TableHeaderCellActionBase {
@i18n("@ui5/webcomponents")
static i18nBundle: I18nBundle;

getRenderInfo() {
return {
icon: "ai",
tooltip: TableHeaderCellActionAI.i18nBundle.getText(TABLE_GENERATED_BY_AI),
};
}
}

TableHeaderCellActionAI.define();

export default TableHeaderCellActionAI;
6 changes: 6 additions & 0 deletions packages/main/src/TableHeaderCellActionBase.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<ui5-button
icon="{{_icon}}"
tooltip="{{_tooltip}}"
@click={{_onClick}}
design="Transparent">
</ui5-button>
64 changes: 64 additions & 0 deletions packages/main/src/TableHeaderCellActionBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import { customElement, eventStrict } from "@ui5/webcomponents-base/dist/decorators.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import TableHeaderCellActionBaseTemplate from "./generated/templates/TableHeaderCellActionBaseTemplate.lit.js";
import TableHeaderCellActionBaseStyles from "./generated/themes/TableHeaderCellActionBase.css.js";
import Button from "./Button.js";
import type TableCell from "./TableCell.js";

/**
* @class
* The `TableHeaderCellActionBase` class serves as a foundation for table header cell actions.
* @constructor
* @abstract
* @extends UI5Element
* @since 2.7.0
* @public
*/
@customElement({
renderer: litRender,
styles: TableHeaderCellActionBaseStyles,
template: TableHeaderCellActionBaseTemplate,
dependencies: [Button],
})

/**
* Fired when an action is clicked.
*
* @public
* @since 2.7.0
*/
@eventStrict("click", {
bubbles: false,
})

abstract class TableHeaderCellActionBase extends UI5Element {
eventDetails!: {
"click": void
}

abstract getRenderInfo(): {
icon: string;
tooltip: string;
};

onBeforeRendering() {
this.toggleAttribute("_popin", !this.parentElement);
}

_onClick(e: MouseEvent) {
const action = this.parentElement ? this : ((this.getRootNode() as ShadowRoot).host as TableCell)._headerCell.action[0] as this;
action.fireDecoratorEvent("click");
e.stopPropagation();
}

get _tooltip() {
return this.getRenderInfo().tooltip;
}

get _icon() {
return this.getRenderInfo().icon;
}
}

export default TableHeaderCellActionBase;
4 changes: 1 addition & 3 deletions packages/main/src/TableHeaderRow.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import { customElement, slot, property } from "@ui5/webcomponents-base/dist/decorators.js";
import TableRowBase from "./TableRowBase.js";
import TableHeaderRowTemplate from "./generated/templates/TableHeaderRowTemplate.lit.js";
import TableHeaderRowStyles from "./generated/themes/TableHeaderRow.css.js";
Expand Down
3 changes: 1 addition & 2 deletions packages/main/src/TableRowActionBase.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
{{else if _isInteractive}}
<ui5-button
icon="{{_icon}}"
text="{{_text}}"
tooltip="{{_text}}"
@click={{_onActionClick}}
design="Transparent">
Expand All @@ -12,6 +11,6 @@
<ui5-icon
name="{{_icon}}"
tooltip="{{_text}}"
design="Transparent">
design="NonInteractive">
</ui5-icon>
{{/if}}
5 changes: 0 additions & 5 deletions packages/main/src/TableRowActionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { customElement, property } from "@ui5/webcomponents-base/dist/decorators
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import TableRowActionBaseTemplate from "./generated/templates/TableRowActionBaseTemplate.lit.js";
import TableRowActionBaseStyles from "./generated/themes/TableRowActionBase.css.js";
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
import Icon from "./Icon.js";
import Button from "./Button.js";
import type Menu from "./Menu.js";
import type MenuItem from "./MenuItem.js";
import type Table from "./Table.js";
import type TableRow from "./TableRow.js";
import type TableRowAction from "./TableRowAction.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";

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

@i18n("@ui5/webcomponents")
static i18nBundle: I18nBundle;

private static _menu: Menu;
private static _menuItems = new WeakMap();
static async showMenu(actions: TableRowActionBase[], opener: HTMLElement) {
Expand Down
19 changes: 15 additions & 4 deletions packages/main/src/TableRowActionNavigation.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import { customElement, property, i18n } from "@ui5/webcomponents-base/dist/decorators.js";
import TableRowActionBase from "./TableRowActionBase.js";
import { TABLE_NAVIGATION } from "./generated/i18n/i18n-defaults.js";
import "@ui5/webcomponents-icons/dist/navigation-right-arrow.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";

/**
* @class
* The `TableRowActionNavigation` class defines a navigation actio‚n for table rows.
*
* ### Overview
*
* The `ui5-table-row-action-navigation` component defines a navigation action for table rows.
*
* ### ES6 Module Import
*
* `import "@ui5/webcomponents/dist/TableRowActionNavigation.js";`
*
* @constructor
* @extends TableRowActionBase
* @since 2.7.0
Expand All @@ -24,6 +32,9 @@ class TableRowActionNavigation extends TableRowActionBase {
@property({ type: Boolean })
interactive = false;

@i18n("@ui5/webcomponents")
static i18nBundle: I18nBundle;

getRenderInfo() {
return {
text: this._i18nNavigation,
Expand All @@ -37,7 +48,7 @@ class TableRowActionNavigation extends TableRowActionBase {
}

get _i18nNavigation() {
return TableRowActionBase.i18nBundle.getText(TABLE_NAVIGATION);
return TableRowActionNavigation.i18nBundle.getText(TABLE_NAVIGATION);
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/main/src/bundle.esm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import FormGroup from "./FormGroup.js";
import FileUploader from "./FileUploader.js";
import Table from "./Table.js";
import TableHeaderCell from "./TableHeaderCell.js";
import TableHeaderCellActionAI from "./TableHeaderCellActionAI.js";
import TableHeaderRow from "./TableHeaderRow.js";
import TableGrowing from "./TableGrowing.js";
import TableSelection from "./TableSelection.js";
Expand Down
2 changes: 2 additions & 0 deletions packages/main/src/i18n/messagebundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -620,3 +620,5 @@ TABLE_MORE_DESCRIPTION=To load more rows, press Enter or Space
TABLE_ROW_ACTIONS=Row Actions
#XACT: ARIA description for the row action navigation
TABLE_NAVIGATION=Navigation
#XTOL: Tooltip for the AI icon in the column header to indicate that the column is generated by AI
TABLE_GENERATED_BY_AI=Generated by AI
1 change: 1 addition & 0 deletions packages/main/src/themes/TableCell.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
:host([_popin]) {
color: var(--sapContent_LabelColor);
padding-inline-start: 0;
padding-inline-end: 0;
align-items: center;
Expand Down
23 changes: 20 additions & 3 deletions packages/main/src/themes/TableHeaderCell.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
:host {
font-family: var(--sapFontSemiboldDuplexFamily);
color: var(--sapList_HeaderTextColor);
font-family: var(--sapFontSemiboldDuplexFamily);
color: var(--sapList_HeaderTextColor);
align-items: center;
flex-wrap: nowrap;
max-width: 100%;
gap: 0.125rem;
}

:host(:empty) {
padding: 0;
padding: 0;
}

[ui5-icon] {
margin-inline-start: 0.375rem;
width: 1rem;
height: 1rem;
flex-shrink: 0;
}

::slotted([ui5-label]) {
color: inherit;
font-family: inherit;
overflow: hidden;
}
Loading

0 comments on commit af907a3

Please sign in to comment.