Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/declarative-table.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DeclarativeTable

A data table web component that renders rows and columns from a declarative column definition. Supports pagination, grouped columns, conditional cell styling, and multiple cell display modes (plain text, link, boolean icon, secret, tooltip, button, image).
A data table web component that renders rows and columns from a declarative column definition. Supports pagination, grouped columns, conditional cell styling, and multiple cell display modes (plain text, link, boolean icon, secret, tooltip, button, image, tag).

## Tags

Expand Down Expand Up @@ -201,6 +201,7 @@ By default a cell renders its value as plain text. Use `uiSettings.displayAs` to
| `'alert'` | Alert-styled text |
| `'img'` | `<img>` element using the value as `src` |
| `'button'` | Action button (requires `buttonSettings`) |
| `'tag'` | One `<ui5-tag>` chip per value (split by `tagSettings.separator`, default `','`); also accepts an array of values |

### Copy button

Expand Down
69 changes: 55 additions & 14 deletions docs/value-cell.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ValueCell

A standalone cell renderer that displays a single field value from a resource object. Supports seven display modes (plain text, secret, boolean icon, link, tooltip, alert, image, button), conditional CSS rules, static CSS overrides, a copy-to-clipboard button, and a label badge mode. Used internally by `DeclarativeTable` and available for direct use in custom layouts.
A standalone cell renderer that displays a single field value from a resource object. Supports eight display modes (plain text, secret, boolean icon, link, tooltip, alert, image, button, tag), conditional CSS rules, static CSS overrides, a copy-to-clipboard button, and a label badge mode. Used internally by `DeclarativeTable` and available for direct use in custom layouts.

## Tags

Expand Down Expand Up @@ -135,6 +135,7 @@ By default the cell renders its value as plain text. Use `uiSettings.displayAs`
| `'alert'` | Critical alert icon when the value is falsy; empty otherwise |
| `'img'` | `<img>` element using the value as `src` |
| `'button'` | Action button (requires `buttonSettings`) |
| `'tag'` | One `<ui5-tag>` chip per value (split by `tagSettings.separator`, default `','`); also accepts an array of values |

### Secret

Expand Down Expand Up @@ -209,28 +210,48 @@ Renders a `<ui5-button>`. A `buttonClick` event fires with `{ event, field, reso
}
```

---

## Copy button
### Tags

Add a copy-to-clipboard icon to any cell regardless of `displayAs`:
Renders each value as a `<ui5-tag>` chip. String values are split by `tagSettings.separator` (default `','`); array values each become a separate chip. Empty segments are filtered out automatically.

```ts
{ property: 'metadata.uid', uiSettings: { withCopyButton: true } }
```
// Comma-separated string → three chips
{
property: 'labels',
uiSettings: { displayAs: 'tag' },
// resource value: 'api,backend,v2'
}

The icon appears beside the rendered value. Clicking it writes the resolved value to the clipboard without propagating the event to parent elements.
// Custom separator
{
property: 'environments',
uiSettings: {
displayAs: 'tag',
tagSettings: { design: 'Information', separator: '|' },
},
// resource value: 'prod|staging'
}

// Array value
{
property: 'tags',
uiSettings: { displayAs: 'tag' },
// resource value: ['prod', 'staging']
}
```

---

## Label badge
## Copy button

Wrap the value in a styled blue badge pill:
Add a copy-to-clipboard icon to any cell regardless of `displayAs`:

```ts
{ property: 'metadata.namespace', uiSettings: { labelDisplay: true } }
{ property: 'metadata.uid', uiSettings: { withCopyButton: true } }
```

The icon appears beside the rendered value. Clicking it writes the resolved value to the clipboard without propagating the event to parent elements.

---

## Conditional cell styling (`cssRules`)
Expand Down Expand Up @@ -262,7 +283,7 @@ uiSettings: { cssCustomization: { fontStyle: 'italic' } }

## Sub-components

`ValueCell` composes three internal components that are also exported from the public API and can be used independently.
`ValueCell` composes four internal components that are also exported from the public API and can be used independently.

### `BooleanValue`

Expand Down Expand Up @@ -306,23 +327,43 @@ import { SecretValue } from '@openmfp/webcomponents';

The masked form renders `*` repeated to the same length as `value` (minimum 8 characters when the value is empty).

### `TagListValue`

Renders an array of strings as `<ui5-tag>` chips in a wrapping flex container.

```ts
import { TagListValue } from '@openmfp/webcomponents';
```

| Input | Type | Required | Description |
| ------------ | ------------- | -------- | --------------------------------------------------------- |
| `tags` | `string[]` | yes | Each string becomes one chip |
| `tagSettings`| `TagSettings` | no | Controls chip `design`, `colorScheme` (`'1'`–`'10'`, default `'1'`), and `separator` |
| `testId` | `string` | no | `test-id` attribute on the wrapper element (default `'tag-list-value'`) |

---

## Types

```ts
interface UiSettings {
displayAs?: 'secret' | 'boolIcon' | 'link' | 'tooltip' | 'alert' | 'img' | 'button';
displayAs?: 'secret' | 'boolIcon' | 'link' | 'tooltip' | 'alert' | 'img' | 'button' | 'tag';
buttonSettings?: ButtonSettings;
tagSettings?: TagSettings;
tooltipIcon?: string;
withCopyButton?: boolean;
labelDisplay?: boolean;
cssCustomization?: Partial<CSSStyleDeclaration>;
cssRules?: CssRule[];
columnWidth?: string;
align?: 'start' | 'center' | 'end';
}

interface TagSettings {
design?: 'Neutral' | 'Positive' | 'Critical' | 'Negative' | 'Information' | 'Set1' | 'Set2';
colorScheme?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10'; // default '1'
separator?: string; // default ','
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a temptetion to rename it to valueSeparator, what do you think?

}

interface ButtonSettings {
text?: string;
icon?: string;
Expand Down
15 changes: 12 additions & 3 deletions projects/ngx/declarative-ui/models/ui-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ export interface PropertyField {
transform?: TransformType[];
}

/** Appearance settings for tag chip rendering. */
export interface TagSettings {
design?: 'Neutral' | 'Positive' | 'Critical' | 'Negative' | 'Information' | 'Set1' | 'Set2';
colorScheme?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10';
/** Delimiter used to split a plain-string value into individual tags. Default: `','`. */
separator?: string;
}

/** Display and interaction settings for a table cell. */
export interface UiSettings {
/** When `true`, renders the cell value as a styled badge (blue pill). */
labelDisplay?: boolean;
/** How the cell value is rendered. Defaults to plain text when omitted. */
displayAs?:
| 'secret'
Expand All @@ -28,9 +34,12 @@ export interface UiSettings {
| 'tooltip'
| 'alert'
| 'img'
| 'button';
| 'button'
| 'tag';
/** Button appearance and action — only used when `displayAs` is `'button'`. */
buttonSettings?: ButtonSettings;
/** Tag chip configuration — only used when `displayAs` is `'tag'`. */
tagSettings?: TagSettings;
/** SAP UI5 icon name shown as the tooltip trigger icon. */
tooltipIcon?: string;
/** When `true`, a copy-to-clipboard button is rendered next to the value. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,17 @@ export const GroupedColumns: Story = {
};

/**
* Group with a space delimiter and labelDisplay — values rendered as blue
* badge labels, separated by a single space. Also demonstrates the alert
* display type: a warning icon appears when the field value is falsy.
* Group with a space delimiter and tag display — values rendered as ui5-tag
* chips, separated by a single space. Also demonstrates the alert display
* type: a warning icon appears when the field value is falsy.
*/
export const GroupedWithLabelsAndAlert: Story = {
export const GroupedWithTagsAndAlert: Story = {
args: {
columns: [
{ label: 'Name', property: 'metadata.name' },
{
property: 'spec.nodeName',
uiSettings: { labelDisplay: true },
uiSettings: { displayAs: 'tag' },
group: {
name: 'placement',
label: 'Placement',
Expand All @@ -255,7 +255,7 @@ export const GroupedWithLabelsAndAlert: Story = {
},
{
property: 'spec.image',
uiSettings: { labelDisplay: true },
uiSettings: { displayAs: 'tag' },
group: { name: 'placement' },
},
{
Expand Down Expand Up @@ -379,6 +379,45 @@ export const ButtonCell: Story = {
},
};

/**
* `displayAs: 'tag'` renders comma-separated strings (or arrays) as `<ui5-tag>` chips.
* `tagSettings.separator` overrides the default `','` delimiter.
* `tagSettings.design` sets the chip colour scheme.
*/
export const Tags: Story = {
args: {
columns: [
{ label: 'Name', property: 'metadata.name' },
{
label: 'Labels',
property: 'labels',
uiSettings: { displayAs: 'tag' },
},
{
label: 'Environments',
property: 'environments',
uiSettings: {
displayAs: 'tag',
tagSettings: { design: 'Information', separator: '|' },
},
},
] satisfies TableFieldDefinition[],
resources: [
{
...PODS[0],
labels: 'api,backend,v2',
environments: ['prod', 'staging'],
},
{ ...PODS[1], labels: 'worker', environments: 'dev' },
{
...PODS[2],
labels: 'cache,infra',
environments: 'prod|dev|staging',
},
],
},
};

/** Empty resources array triggers the illustrated empty-state message. */
export const EmptyState: Story = {
args: {
Expand Down
4 changes: 2 additions & 2 deletions projects/ngx/declarative-ui/stories/pods-table.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ export const TABLE_COLUMNS: TableFieldDefinition[] = [
},
{
property: 'spec.image',
uiSettings: { labelDisplay: true },
uiSettings: { displayAs: 'tag' },
group: { name: 'placement', label: 'Placement', delimiter: ' ' },
},
{
property: 'spec.nodeName',
uiSettings: { labelDisplay: true },
uiSettings: { displayAs: 'tag' },
group: { name: 'placement' },
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@
@if (tableConfig(); as config) {
<mfp-declarative-table
[columns]="effectiveColumns()"
[growMode]="config.growMode"
[hasMore]="config.hasMore ?? false"
[height]="config.height"
[loadMoreButtonText]="config.loadMoreButtonText"
[paginationLimit]="config.paginationLimit ?? 5"
[resources]="resources()"
[totalItemsCount]="config.totalItemsCount"
(buttonClick)="onButtonClick($event)"
(loadMoreResources)="loadMoreResources.emit()"
(paginationLimitChanged)="paginationLimitChanged.emit($event)"
[growMode]="config.growMode"
[height]="config.height"
[loadMoreButtonText]="config.loadMoreButtonText"
(tableRowClicked)="tableRowClicked.emit($event)"
/>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<ui5-table
test-id="generic-table"
[style.height]="height() ? height() + 'px' : null"
[style.overflow-y]="'auto'"
test-id="generic-table">
[style.overflow-y]="'auto'">
<ui5-table-header-row slot="headerRow" [sticky]="growMode() === 'Scroll' && !!height()">
@for (column of viewColumns(); track columnTrackBy(column, $index)) {
@if (column.group) {
Expand Down Expand Up @@ -35,9 +35,9 @@
@let isMultiline = column.group.multiline ?? true;
<div
class="flex"
[style.justifyContent]="isMultiline ? null : column.uiSettings?.align"
[style.alignItems]="isMultiline ? column.uiSettings?.align : null"
[style.flexDirection]="isMultiline ? 'column' : 'row'">
[style.flexDirection]="isMultiline ? 'column' : 'row'"
[style.justifyContent]="isMultiline ? null : column.uiSettings?.align">
@for (
field of column.group.fields;
let last = $last;
Expand All @@ -64,7 +64,7 @@
/>
</span>
@if (!last && column.group.delimiter) {
<span>{{ column.group.delimiter }}</span>
<span class="delimiter">{{ column.group.delimiter }}</span>
}
}
</div>
Expand Down Expand Up @@ -98,9 +98,9 @@
@if (hasMore()) {
<ui5-table-growing
id="growing"
slot="features"
[mode]="growMode()"
[text]="loadMoreButtonText()"
slot="features"
(ui5LoadMore)="loadMoreResources.emit()"
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@
.flex {
display: flex;
width: 100%;
}

.delimiter {
min-width: 4px;
}
1 change: 1 addition & 0 deletions projects/ngx/declarative-ui/value-cell/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './value-cell.component';
export * from './boolean-value/boolean-value.component';
export * from './link-value/link-value.component';
export * from './secret-value/secret-value.component';
export * from './tag-list-value/tag-list-value.component';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<span class="tag-list" [attr.test-id]="testId()">
@for (tag of tags(); track $index) {
<ui5-tag
[colorScheme]="tagSettings()?.colorScheme"
[design]="tagSettings()?.design ?? 'Neutral'"
[hideStateIcon]="true"
>{{ tag }}</ui5-tag>
}
</span>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
:host {
display: inline-flex;
}

.tag-list {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
Loading