diff --git a/packages/components/src/components/@shared/_kol-popover-button-mixin.scss b/packages/components/src/components/@shared/_kol-popover-button-mixin.scss
new file mode 100644
index 00000000000..decb4dfad67
--- /dev/null
+++ b/packages/components/src/components/@shared/_kol-popover-button-mixin.scss
@@ -0,0 +1,17 @@
+@use 'mixins' as *;
+
+@mixin kol-popover-button-styles {
+ @layer kol-component {
+ .kol-popover-button {
+ &__button {
+ display: inline-block; // critical for floating UI to work correctly
+ }
+
+ &__popover {
+ border: 1px solid #000;
+ margin: 0;
+ padding: 0;
+ }
+ }
+ }
+}
diff --git a/packages/components/src/components/@shared/_kol-table-settings-mixin.scss b/packages/components/src/components/@shared/_kol-table-settings-mixin.scss
new file mode 100644
index 00000000000..b756b9dd881
--- /dev/null
+++ b/packages/components/src/components/@shared/_kol-table-settings-mixin.scss
@@ -0,0 +1,32 @@
+@use './mixins' as *;
+
+@mixin kol-table-settings-styles {
+ @layer kol-component {
+ .kol-table-settings {
+ background: #fff;
+ position: absolute;
+ right: 0;
+ top: 0;
+ z-index: 1;
+
+ &__columns-container {
+ margin-top: rem(16);
+ max-height: rem(200);
+ overflow: auto;
+ }
+
+ &__columns {
+ align-items: center;
+ display: grid;
+ gap: rem(8);
+ grid-auto-rows: min-content;
+ grid-template-columns: min-content 1fr rem(100) auto auto;
+ overflow: hidden;
+ }
+
+ &__column {
+ display: contents;
+ }
+ }
+ }
+}
diff --git a/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss b/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss
index 5b9b52939f7..4c46bb9cb05 100644
--- a/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss
+++ b/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss
@@ -1,16 +1,22 @@
-@use '../@shared/mixins' as *;
@use '../host-display-block' as *;
-@use '../tooltip/style.scss' as *;
+@use '../tooltip/style' as *;
+@use './kol-table-settings-mixin' as *;
+@use './mixins' as *;
@mixin kol-table-stateless-styles {
+ @include kol-table-settings-styles;
+
@layer kol-component {
.kol-table {
display: block;
font-size: rem(16);
-
max-width: 100%;
- overflow-x: auto;
- overflow-y: hidden;
+ position: relative;
+
+ &__scroll-container {
+ overflow-x: auto;
+ overflow-y: hidden;
+ }
&__table {
width: 100%;
@@ -18,6 +24,8 @@
&__caption {
text-align: start;
+ min-height: var(--a11y-min-size); // align with configuration button
+ padding-right: var(--a11y-min-size);
}
&__focus-element {
diff --git a/packages/components/src/components/popover-button/component.tsx b/packages/components/src/components/popover-button/component.tsx
new file mode 100644
index 00000000000..f237f79d4d0
--- /dev/null
+++ b/packages/components/src/components/popover-button/component.tsx
@@ -0,0 +1,257 @@
+import type { JSX } from '@stencil/core';
+import { Component, h, Method, Prop, State, Watch } from '@stencil/core';
+import { KolButtonWcTag } from '../../core/component-names';
+import { alignFloatingElements } from '../../utils/align-floating-elements';
+import type { PopoverButtonProps, PopoverButtonStates } from '../../schema/components/popover-button';
+import type {
+ AccessKeyPropType,
+ AlternativeButtonLinkRolePropType,
+ AriaDescriptionPropType,
+ ButtonCallbacksPropType,
+ ButtonTypePropType,
+ ButtonVariantPropType,
+ CustomClassPropType,
+ IconsPropType,
+ LabelWithExpertSlotPropType,
+ PopoverAlignPropType,
+ ShortKeyPropType,
+ StencilUnknown,
+ Stringified,
+ SyncValueBySelectorPropType,
+ TooltipAlignPropType,
+} from '../../schema';
+import { validatePopoverAlign } from '../../schema';
+
+/**
+ * @slot - The popover content.
+ */
+@Component({
+ tag: 'kol-popover-button-wc',
+ shadow: false,
+})
+// class implementing PopoverButtonProps and not API because we don't want to repeat the entire state and validation for button props
+export class KolPopoverButton implements PopoverButtonProps {
+ private refButton?: HTMLKolButtonWcElement;
+ private refPopover?: HTMLDivElement;
+
+ @State() public state: PopoverButtonStates = {
+ _label: '',
+ _popoverAlign: 'bottom',
+ };
+ @State() private justClosed = false;
+
+ /**
+ * Hides the popover programmatically by calling the native hidePopover method.
+ */
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async hidePopover() {
+ void this.refPopover?.hidePopover();
+ }
+
+ /* Regarding type issue see https://github.com/microsoft/TypeScript/issues/54864 */
+ private handleBeforeToggle(event: Event) {
+ if ((event as ToggleEvent).newState === 'closed') {
+ this.justClosed = true;
+
+ setTimeout(() => {
+ // Reset the flag after the event loop tick.
+ this.justClosed = false;
+ }, 10); // timeout of 0 should be sufficient but doesn't work in Safari Mobile (needs further investigation).
+ } else if (this.refPopover) {
+ /**
+ * Avoid "flicker" by hiding the element until the position is set in the `toggle` event handler. `alignFloatingElements` is responsible for setting the visibility back to 'visible'.
+ */
+ this.refPopover.style.visibility = 'hidden';
+ }
+ }
+
+ private handleToggle(event: Event) {
+ if ((event as ToggleEvent).newState === 'open' && this.refPopover && this.refButton) {
+ void alignFloatingElements({
+ align: this.state._popoverAlign,
+ floatingElement: this.refPopover,
+ referenceElement: this.refButton,
+ });
+ }
+ }
+
+ private handleButtonClick() {
+ // If the popover was just closed by native behavior, do nothing (and let it stay closed).
+ if (!this.justClosed) {
+ this.refPopover?.togglePopover();
+ }
+ }
+
+ public componentDidRender() {
+ this.refPopover?.addEventListener('toggle', this.handleToggle.bind(this));
+ this.refPopover?.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this));
+ }
+
+ public disconnectedCallback() {
+ this.refPopover?.removeEventListener('toggle', this.handleToggle.bind(this));
+ this.refPopover?.removeEventListener('beforetoggle', this.handleBeforeToggle.bind(this));
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+
+ /**
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
+ */
+ @Prop() public _accessKey?: AccessKeyPropType;
+
+ /**
+ * Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
+ */
+ @Prop() public _ariaControls?: string;
+
+ /**
+ * Defines the value for the aria-description attribute.
+ */
+ @Prop() public _ariaDescription?: AriaDescriptionPropType;
+
+ /**
+ * Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded)
+ */
+ @Prop() public _ariaExpanded?: boolean;
+
+ /**
+ * Defines whether the interactive element of the component is selected (e.g. role=tab). (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected)
+ */
+ @Prop() public _ariaSelected?: boolean;
+
+ /**
+ * Defines the custom class attribute if _variant="custom" is set.
+ */
+ @Prop() public _customClass?: CustomClassPropType;
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Hides the caption by default and displays the caption text with a tooltip when the
+ * interactive element is focused or the mouse is over it.
+ * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hideLabel?: boolean = false;
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: IconsPropType;
+
+ /**
+ * Defines the internal ID of the primary component element.
+ */
+ @Prop() public _id?: string;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
+ */
+ @Prop() public _label!: LabelWithExpertSlotPropType;
+
+ /**
+ * Defines the technical name of an input field.
+ */
+ @Prop() public _name?: string;
+
+ /**
+ * Defines the callback functions for button events.
+ */
+ @Prop() public _on?: ButtonCallbacksPropType;
+
+ /**
+ * Defines where to show the Popover preferably: top, right, bottom or left.
+ */
+ @Prop() public _popoverAlign?: PopoverAlignPropType = 'bottom';
+
+ /**
+ * Defines the role of the components primary element.
+ */
+ @Prop() public _role?: AlternativeButtonLinkRolePropType;
+
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
+ /**
+ * Selector for synchronizing the value with another input element.
+ * @internal
+ */
+ @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
+
+ /**
+ * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
+ */
+ @Prop() public _tabIndex?: number;
+
+ /**
+ * Defines where to show the Tooltip preferably: top, right, bottom or left.
+ */
+ @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
+
+ /**
+ * Defines either the type of the component or of the components interactive element.
+ */
+ @Prop() public _type?: ButtonTypePropType = 'button';
+
+ /**
+ * Defines the value that the button emits on click.
+ */
+ @Prop() public _value?: Stringified;
+
+ /**
+ * Defines which variant should be used for presentation.
+ */
+ @Prop() public _variant?: ButtonVariantPropType = 'normal';
+
+ @Watch('_popoverAlign')
+ public validatePopoverAlign(value?: PopoverAlignPropType): void {
+ validatePopoverAlign(this, value);
+ }
+
+ public componentWillLoad() {
+ this.validatePopoverAlign(this._popoverAlign);
+ }
+}
diff --git a/packages/components/src/components/popover-button/shadow.tsx b/packages/components/src/components/popover-button/shadow.tsx
index 145a9f490fb..dda6de13482 100644
--- a/packages/components/src/components/popover-button/shadow.tsx
+++ b/packages/components/src/components/popover-button/shadow.tsx
@@ -1,8 +1,7 @@
import type { JSX } from '@stencil/core';
-import { Component, h, Prop, State, Watch } from '@stencil/core';
-import { KolButtonWcTag } from '../../core/component-names';
-import { alignFloatingElements } from '../../utils/align-floating-elements';
-import type { PopoverButtonProps, PopoverButtonStates } from '../../schema/components/popover-button';
+import { Component, h, Method, Prop } from '@stencil/core';
+import { KolPopoverButtonWcTag } from '../../core/component-names';
+import type { PopoverButtonProps } from '../../schema/components/popover-button';
import type {
AccessKeyPropType,
AlternativeButtonLinkRolePropType,
@@ -20,7 +19,6 @@ import type {
SyncValueBySelectorPropType,
TooltipAlignPropType,
} from '../../schema';
-import { validatePopoverAlign } from '../../schema';
/**
* @slot - The popover content.
@@ -32,98 +30,48 @@ import { validatePopoverAlign } from '../../schema';
},
shadow: true,
})
-// class implementing PopoverButtonProps and not API because we don't want to repeat the entire state and validation for button props
export class KolPopoverButton implements PopoverButtonProps {
- private refButton?: HTMLKolButtonWcElement;
- private refPopover?: HTMLDivElement;
-
- @State() public state: PopoverButtonStates = {
- _label: '',
- _popoverAlign: 'bottom',
- };
- @State() private justClosed = false;
-
- /* Regarding type issue see https://github.com/microsoft/TypeScript/issues/54864 */
- private handleBeforeToggle(event: Event) {
- if ((event as ToggleEvent).newState === 'closed') {
- this.justClosed = true;
-
- setTimeout(() => {
- // Reset the flag after the event loop tick.
- this.justClosed = false;
- }, 10); // timeout of 0 should be sufficient but doesn't work in Safari Mobile (needs further investigation).
- } else if (this.refPopover) {
- /**
- * Avoid "flicker" by hiding the element until the position is set in the `toggle` event handler. `alignFloatingElements` is responsible for setting the visibility back to 'visible'.
- */
- this.refPopover.style.visibility = 'hidden';
- }
- }
-
- private handleToggle(event: Event) {
- if ((event as ToggleEvent).newState === 'open' && this.refPopover && this.refButton) {
- void alignFloatingElements({
- align: this.state._popoverAlign,
- floatingElement: this.refPopover,
- referenceElement: this.refButton,
- });
- }
- }
-
- private handleButtonClick() {
- // If the popover was just closed by native behavior, do nothing (and let it stay closed).
- if (!this.justClosed) {
- this.refPopover?.togglePopover();
- }
- }
-
- public componentDidRender() {
- this.refPopover?.addEventListener('toggle', this.handleToggle.bind(this));
- this.refPopover?.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this));
- }
+ private ref?: HTMLKolPopoverButtonWcElement;
- public disconnectedCallback() {
- this.refPopover?.removeEventListener('toggle', this.handleToggle.bind(this));
- this.refPopover?.removeEventListener('beforetoggle', this.handleBeforeToggle.bind(this));
+ /**
+ * Hides the popover programmatically by forwarding the call to the web component.
+ */
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async hidePopover() {
+ void this.ref?.hidePopover();
}
public render(): JSX.Element {
return (
-
+ (this.ref = element)}
+ _accessKey={this._accessKey}
+ _ariaControls={this._ariaControls}
+ _ariaDescription={this._ariaDescription}
+ _ariaExpanded={this._ariaExpanded}
+ _ariaSelected={this._ariaSelected}
+ _customClass={this._customClass}
+ _disabled={this._disabled}
+ _hideLabel={this._hideLabel}
+ _icons={this._icons}
+ _id={this._id}
+ _label={this._label}
+ _name={this._name}
+ _on={this._on}
+ _popoverAlign={this._popoverAlign}
+ _role={this._role}
+ _shortKey={this._shortKey}
+ _syncValueBySelector={this._syncValueBySelector}
+ _tabIndex={this._tabIndex}
+ _tooltipAlign={this._tooltipAlign}
+ _type={this._type}
+ _value={this._value}
+ _variant={this._variant}
+ >
+
+
+
);
}
@@ -239,13 +187,4 @@ export class KolPopoverButton implements PopoverButtonProps {
* Defines which variant should be used for presentation.
*/
@Prop() public _variant?: ButtonVariantPropType = 'normal';
-
- @Watch('_popoverAlign')
- public validatePopoverAlign(value?: PopoverAlignPropType): void {
- validatePopoverAlign(this, value);
- }
-
- public componentWillLoad() {
- this.validatePopoverAlign(this._popoverAlign);
- }
}
diff --git a/packages/components/src/components/popover-button/style.scss b/packages/components/src/components/popover-button/style.scss
index ee2f19db104..eca7a02ed0d 100644
--- a/packages/components/src/components/popover-button/style.scss
+++ b/packages/components/src/components/popover-button/style.scss
@@ -1,19 +1,7 @@
-@use '../@shared/mixins' as *;
@use '../../styles/global' as *;
@use '../@shared/kol-button-mixin' as *;
+@use '../@shared/kol-popover-button-mixin' as *;
+@use '../tooltip/style' as *;
@include kol-button-styles('kol-button');
-
-@layer kol-component {
- .kol-popover-button {
- &__button {
- display: inline-block; // critical for floating UI to work correctly
- }
-
- &__popover {
- border: 1px solid #000;
- margin: 0;
- padding: 0;
- }
- }
-}
+@include kol-popover-button-styles;
diff --git a/packages/components/src/components/popover-button/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/popover-button/test/__snapshots__/snapshot.spec.tsx.snap
index 02a6e77a153..716083e3bf0 100644
--- a/packages/components/src/components/popover-button/test/__snapshots__/snapshot.spec.tsx.snap
+++ b/packages/components/src/components/popover-button/test/__snapshots__/snapshot.spec.tsx.snap
@@ -3,14 +3,10 @@
exports[`kol-popover-button should render with _label="Click to toggle" 1`] = `
-
+
+
+
+
`;
diff --git a/packages/components/src/components/table-stateful/shadow.tsx b/packages/components/src/components/table-stateful/shadow.tsx
index 661c94bedaf..9528e8db9fc 100644
--- a/packages/components/src/components/table-stateful/shadow.tsx
+++ b/packages/components/src/components/table-stateful/shadow.tsx
@@ -41,6 +41,8 @@ import {
import { Callback } from '../../schema/enums';
import type { MinWidthPropType } from '../../schema/props/min-width';
import { dispatchDomEvent, KolEvent } from '../../utils/events';
+import type { TableSettingsPropType } from '../../schema/props/table-settings';
+import { validateTableSettings } from '../../schema/props/table-settings';
const PAGINATION_OPTIONS = [10, 20, 50, 100];
@@ -121,6 +123,11 @@ export class KolTableStateful implements TableAPI {
*/
@Prop() public _on?: TableStatefulCallbacksPropType;
+ /**
+ * Defines the table settings including column visibility, order and width.
+ */
+ @Prop() public _tableSettings?: TableSettingsPropType;
+
@State() public state: TableStates = {
_allowMultiSort: false,
_data: [],
@@ -295,6 +302,11 @@ export class KolTableStateful implements TableAPI {
validateTableStatefulCallbacks(this, value);
}
+ @Watch('_tableSettings')
+ public validateTableSettings(value?: TableSettingsPropType): void {
+ validateTableSettings(this, value);
+ }
+
private readonly handlePagination: KoliBriPaginationButtonCallbacks = {
onClick: (event: Event, page: number) => {
if (typeof this.state._pagination._on?.onClick === 'function') {
@@ -373,10 +385,11 @@ export class KolTableStateful implements TableAPI {
this.validateHeaders(this._headers);
this.validateLabel(this._label);
this.validateMinWidth(this._minWidth);
+ this.validateOn(this._on);
this.validatePagination(this._pagination);
this.validatePaginationPosition(this._paginationPosition);
this.validateSelection(this._selection);
- this.validateOn(this._on);
+ this.validateTableSettings(this._tableSettings);
}
private selectDisplayedData(data: KoliBriTableDataType[], pageSize: number, page: number): KoliBriTableDataType[] {
@@ -551,6 +564,7 @@ export class KolTableStateful implements TableAPI {
},
}}
_selection={this.state._selection}
+ _tableSettings={this.state._tableSettings}
/>
{this.pageEndSlice > 0 && this.showPagination && paginationBottom}
diff --git a/packages/components/src/components/table-stateful/style.scss b/packages/components/src/components/table-stateful/style.scss
index 47bdec17572..83eab3a3027 100644
--- a/packages/components/src/components/table-stateful/style.scss
+++ b/packages/components/src/components/table-stateful/style.scss
@@ -1,7 +1,13 @@
-@use '../@shared/mixins' as *;
@use '../../styles/global' as *;
+@use '../../styles/kol-alert-mixin' as *;
+@use '../@shared/kol-button-mixin' as *;
+@use '../@shared/kol-popover-button-mixin' as *;
@use '../@shared/kol-table-stateless-mixin' as *;
+@use '../@shared/mixins' as *;
+@include kol-alert;
+@include kol-button-styles('kol-button');
+@include kol-popover-button-styles;
@include kol-table-stateless-styles;
@layer kol-component {
diff --git a/packages/components/src/components/table-stateless/component.tsx b/packages/components/src/components/table-stateless/component.tsx
index 4917baa0afa..04955577805 100644
--- a/packages/components/src/components/table-stateless/component.tsx
+++ b/packages/components/src/components/table-stateless/component.tsx
@@ -2,7 +2,7 @@ import type { JSX } from '@stencil/core';
import { Component, Element, Fragment, h, Listen, Prop, State, Watch } from '@stencil/core';
import clsx from 'clsx';
-import { KolButtonWcTag, KolIconTag, KolTooltipWcTag } from '../../core/component-names';
+import { KolButtonWcTag, KolIconTag, KolTableSettingsWcTag, KolTooltipWcTag } from '../../core/component-names';
import type { TranslationKey } from '../../i18n';
import { translate } from '../../i18n';
import type {
@@ -19,9 +19,11 @@ import type {
TableDataPropType,
TableHeaderCellsPropType,
TableSelectionPropType,
+ TableSettings,
TableStatelessAPI,
TableStatelessStates,
} from '../../schema';
+import { setState } from '../../schema';
import {
validateLabel,
validateTableCallbacks,
@@ -30,11 +32,14 @@ import {
validateTableHeaderCells,
validateTableSelection,
} from '../../schema';
+import type { ColumnSettings } from '../../schema/types';
import { Callback } from '../../schema/enums';
import type { MinWidthPropType } from '../../schema/props/min-width';
import { validateMinWidth } from '../../schema/props/min-width';
import { nonce } from '../../utils/dev.utils';
import { dispatchDomEvent, KolEvent } from '../../utils/events';
+import type { TableSettingsPropType } from '../../schema/props/table-settings';
+import { validateTableSettings } from '../../schema/props/table-settings';
/**
* @internal
@@ -102,6 +107,11 @@ export class KolTableStateless implements TableStatelessAPI {
*/
@Prop() public _selection?: TableSelectionPropType;
+ /**
+ * Defines the table settings including column visibility, order and width.
+ */
+ @Prop() public _tableSettings?: TableSettingsPropType;
+
@Watch('_data')
public validateData(value?: TableDataPropType) {
validateTableData(this, value, {
@@ -119,6 +129,7 @@ export class KolTableStateless implements TableStatelessAPI {
@Watch('_headerCells')
public validateHeaderCells(value?: TableHeaderCellsPropType) {
validateTableHeaderCells(this, value);
+ this.initializeTableSettings();
}
@Watch('_label')
@@ -143,6 +154,11 @@ export class KolTableStateless implements TableStatelessAPI {
validateTableSelection(this, value);
}
+ @Watch('_tableSettings')
+ public validateTableSettings(value?: TableSettingsPropType) {
+ validateTableSettings(this, value);
+ }
+
@Listen('keydown')
public handleKeyDown(event: KeyboardEvent) {
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
@@ -175,6 +191,11 @@ export class KolTableStateless implements TableStatelessAPI {
}
}
+ @Listen('settingsChange')
+ public handleSettingsChange(event: CustomEvent) {
+ setState(this, '_tableSettings', event.detail);
+ }
+
public disconnectedCallback() {
this.tableDivElementResizeObserver?.disconnect();
}
@@ -291,6 +312,23 @@ export class KolTableStateless implements TableStatelessAPI {
return primaryHeadersWithKeys;
}
+ private getColumnPositionMap(): Map {
+ const keyToPosition = new Map();
+ this.state._tableSettings?.columns.forEach((setting) => {
+ keyToPosition.set(setting.key, setting.position);
+ });
+ return keyToPosition;
+ }
+
+ private sortByColumnPosition(columns: T[]): T[] {
+ const keyToPosition = this.getColumnPositionMap();
+ return [...columns].sort((a, b) => {
+ const posA = keyToPosition.get(a.key ?? '') ?? Number.MAX_SAFE_INTEGER;
+ const posB = keyToPosition.get(b.key ?? '') ?? Number.MAX_SAFE_INTEGER;
+ return posA - posB;
+ });
+ }
+
private createDataField(data: KoliBriTableDataType[], headers: KoliBriTableHeaders, isFoot?: boolean): (KoliBriTableCell & KoliBriTableDataType)[][] {
headers.horizontal = Array.isArray(headers?.horizontal) ? headers.horizontal : [];
headers.vertical = Array.isArray(headers?.vertical) ? headers.vertical : [];
@@ -311,6 +349,8 @@ export class KolTableStateless implements TableStatelessAPI {
rowSpans[index] = [];
});
+ const sortedPrimaryHeader = this.sortByColumnPosition(primaryHeader);
+
for (let i = startRow; i < maxRows; i++) {
const dataRow: KoliBriTableHeaderCellWithLogic[] = [];
headers.vertical.forEach((headerCells, index) => {
@@ -342,33 +382,33 @@ export class KolTableStateless implements TableStatelessAPI {
if (this.horizontal === true) {
const row = isFoot && this.state._dataFoot ? this.state._dataFoot[i - startRow] : data[i];
if (
- typeof primaryHeader[j] === 'object' &&
- primaryHeader[j] !== null &&
- typeof primaryHeader[j].key === 'string' &&
+ typeof sortedPrimaryHeader[j] === 'object' &&
+ sortedPrimaryHeader[j] !== null &&
+ typeof sortedPrimaryHeader[j].key === 'string' &&
typeof row === 'object' &&
row !== null
) {
dataRow.push({
- ...primaryHeader[j],
+ ...sortedPrimaryHeader[j],
colSpan: undefined,
data: row,
- label: row[primaryHeader[j].key as unknown as string] as string,
+ label: row[sortedPrimaryHeader[j].key as unknown as string] as string,
rowSpan: undefined,
});
}
} else {
if (
- typeof primaryHeader[i] === 'object' &&
- primaryHeader[i] !== null &&
- typeof primaryHeader[i].key === 'string' &&
+ typeof sortedPrimaryHeader[i] === 'object' &&
+ sortedPrimaryHeader[i] !== null &&
+ typeof sortedPrimaryHeader[i].key === 'string' &&
typeof data[j] === 'object' &&
data[j] !== null
) {
dataRow.push({
- ...primaryHeader[i],
+ ...sortedPrimaryHeader[i],
colSpan: undefined,
data: data[j],
- label: data[j][primaryHeader[i].key as unknown as number] as string,
+ label: data[j][sortedPrimaryHeader[i].key as unknown as number] as string,
rowSpan: undefined,
});
}
@@ -415,6 +455,24 @@ export class KolTableStateless implements TableStatelessAPI {
}
}
+ private initializeTableSettings() {
+ if (this._tableSettings) {
+ return; // when tableSettings are defined via props, don't override them.
+ }
+ const primaryHeaders = this.getPrimaryHeaders(this.state._headerCells as KoliBriTableHeaders);
+ if (!this.state._tableSettings) {
+ this.state._tableSettings = { columns: [] };
+ }
+ this.state._tableSettings.columns = primaryHeaders
+ .filter((header) => header.key) // only headers with a key are supported
+ .map((header, index) => ({
+ key: header.key ?? nonce(),
+ label: header.label,
+ position: index,
+ visible: true,
+ }));
+ }
+
public componentWillLoad(): void {
this.validateData(this._data);
this.validateDataFoot(this._dataFoot);
@@ -423,6 +481,7 @@ export class KolTableStateless implements TableStatelessAPI {
this.validateMinWidth(this._minWidth);
this.validateOn(this._on);
this.validateSelection(this._selection);
+ this.validateTableSettings(this._tableSettings);
}
/**
@@ -535,6 +594,10 @@ export class KolTableStateless implements TableStatelessAPI {
);
};
+ private getColumnSettings(cell: KoliBriTableCell | KoliBriTableHeaderCell): ColumnSettings | undefined {
+ return this.state._tableSettings?.columns.find((setting) => setting.key === (cell as KoliBriTableHeaderCellWithLogic).key);
+ }
+
/**
* Renders a table cell, either as a data cell (``) or a header cell (` | `).
* If a custom `render` function is provided in the cell, it will be used to display content.
@@ -545,6 +608,12 @@ export class KolTableStateless implements TableStatelessAPI {
* @returns {JSX.Element} The rendered table cell (either ` | ` or ` | `).
*/
private readonly renderTableCell = (cell: KoliBriTableCell, rowIndex: number, colIndex: number, isVertical: boolean): JSX.Element => {
+ // Skip rendering if the column is not visible
+ const columnSetting = this.getColumnSettings(cell);
+ if (columnSetting && !columnSetting.visible) {
+ return '';
+ }
+
let key = `${rowIndex}-${colIndex}-${cell.label}`;
if (cell.data) {
const dataKey = this.getDataKey(cell.data);
@@ -564,7 +633,7 @@ export class KolTableStateless implements TableStatelessAPI {
rowSpan={cell.rowSpan}
style={{
textAlign: cell.textAlign,
- width: cell.width,
+ width: columnSetting?.width ? `${columnSetting.width}ch` : cell.width,
}}
ref={
typeof cell.render === 'function'
@@ -608,6 +677,18 @@ export class KolTableStateless implements TableStatelessAPI {
return selection;
}
+ /**
+ * Calculates and returns the minimum width for a table based on its settings and columns' visibility and widths.
+ *
+ * @return {string} The minimum width of the table as a string. If `_minWidth` is set to 'auto', the width is
+ * calculated based on the total visible column widths in characters. Otherwise, it returns the greater value
+ * between `_minWidth` and the calculated total visible column widths.
+ */
+ private getTableMinWidth(): string {
+ const totalColumnWidth = this.state._tableSettings?.columns.filter((col) => col.visible).reduce((total, col) => total + (col.width ?? 0), 0) ?? 0;
+ return this.state._minWidth === 'auto' ? `${totalColumnWidth}ch` : `max(${this.state._minWidth}, ${totalColumnWidth}ch)`;
+ }
+
/**
* Renders the header cell for row selection. This cell contains a checkbox for selecting
* all rows when selection is enabled. If multiple selection is allowed, the checkbox allows
@@ -697,6 +778,12 @@ export class KolTableStateless implements TableStatelessAPI {
* @returns {JSX.Element} The rendered header cell with possible sorting controls.
*/
private renderHeadingCell(cell: KoliBriTableHeaderCell, rowIndex: number, colIndex: number, isVertical: boolean): JSX.Element {
+ // Skip rendering if the column is not visible
+ const columnSettings = this.getColumnSettings(cell);
+ if (columnSettings && !columnSettings.visible) {
+ return '';
+ }
+
let ariaSort = undefined;
let sortButtonIcon = 'codicon codicon-fold';
@@ -726,7 +813,7 @@ export class KolTableStateless implements TableStatelessAPI {
colSpan={cell.colSpan}
rowSpan={cell.rowSpan}
style={{
- width: cell.width,
+ width: columnSettings?.width ? `${columnSettings.width}ch` : cell.width,
}}
aria-sort={ariaSort}
data-sort={`sort-${cell.sortDirection}`}
@@ -793,51 +880,61 @@ export class KolTableStateless implements TableStatelessAPI {
const dataField = this.createDataField(this.state._data, this.state._headerCells);
this.checkboxRefs = [];
+ const sortedHorizontalHeaders = this.state._headerCells.horizontal?.map((row) => this.sortByColumnPosition(row));
+
return (
- /* Firefox automatically makes the following div focusable when it has a scrollbar. We implement a similar behavior cross-browser by allowing the
- * to receive focus. Hence, we disable focus for the div to avoid having two focusable elements by setting `tabindex="-1"`
- */
- /* eslint-disable-next-line jsx-a11y/no-static-element-interactions */
- (this.tableDivElement = element)} class="kol-table" tabindex={this.tableDivElementHasScrollbar ? '-1' : undefined}>
-
+
+
+ {/* Firefox automatically makes the following div focusable when it has a scrollbar. We implement a similar behavior cross-browser by allowing the
+ * to receive focus. Hence, we disable focus for the div to avoid having two focusable elements by setting `tabindex="-1"`
+ */}
+ {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
+ (this.tableDivElement = element)}
+ class="kol-table__scroll-container"
+ tabindex={this.tableDivElementHasScrollbar ? '-1' : undefined}
>
- {/*
- * The following element allows the table to receive focus without providing redundant content to screen readers.
- * The `div` is technically not allowed here. But any allowed element would mutate the table semantics. Additionally, the ` ` is necessary to
- * prevent screen readers from just reading "blank".
- */}
- {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
-
-
-
-
-
- {this.state._label}
-
-
- {Array.isArray(this.state._headerCells.horizontal) && (
-
- {[
- this.state._headerCells.horizontal.map((cols, rowIndex) => (
-
- {this.state._selection && this.renderHeadingSelectionCell()}
- {rowIndex === 0 && this.renderHeaderTdCell()}
- {Array.isArray(cols) && cols.map((cell, colIndex) => this.renderHeadingCell(cell, rowIndex, colIndex, false))}
-
- )),
- this.renderSpacer('head', this.state._headerCells.horizontal),
- ]}
-
- )}
-
- {dataField.map((row: (KoliBriTableCell & KoliBriTableDataType)[], rowIndex: number) => this.renderTableRow(row, rowIndex, true))}
-
- {this.renderFoot()}
-
+
+ {/*
+ * The following element allows the table to receive focus without providing redundant content to screen readers.
+ * The `div` is technically not allowed here. But any allowed element would mutate the table semantics. Additionally, the ` ` is necessary to
+ * prevent screen readers from just reading "blank".
+ */}
+ {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
+
+
+
+
+
+ {this.state._label}
+
+
+ {Array.isArray(sortedHorizontalHeaders) && (
+
+ {[
+ sortedHorizontalHeaders.map((cols, rowIndex) => (
+
+ {this.state._selection && this.renderHeadingSelectionCell()}
+ {rowIndex === 0 && this.renderHeaderTdCell()}
+ {Array.isArray(cols) && cols.map((cell, colIndex) => this.renderHeadingCell(cell, rowIndex, colIndex, false))}
+
+ )),
+ this.renderSpacer('head', sortedHorizontalHeaders),
+ ]}
+
+ )}
+
+ {dataField.map((row: (KoliBriTableCell & KoliBriTableDataType)[], rowIndex: number) => this.renderTableRow(row, rowIndex, true))}
+
+ {this.renderFoot()}
+
+
);
}
diff --git a/packages/components/src/components/table-stateless/shadow.tsx b/packages/components/src/components/table-stateless/shadow.tsx
index 8e8f09f7745..343a36e19b0 100644
--- a/packages/components/src/components/table-stateless/shadow.tsx
+++ b/packages/components/src/components/table-stateless/shadow.tsx
@@ -10,6 +10,7 @@ import type {
TableStatelessProps,
} from '../../schema';
import type { MinWidthPropType } from '../../schema/props/min-width';
+import type { TableSettingsPropType } from '../../schema/props/table-settings';
@Component({
tag: 'kol-table-stateless',
@@ -54,6 +55,11 @@ export class KolTableStateless implements TableStatelessProps {
*/
@Prop() public _selection?: TableSelectionPropType;
+ /**
+ * Defines the table settings including column visibility, order and width.
+ */
+ @Prop() public _tableSettings?: TableSettingsPropType;
+
public render(): JSX.Element {
return (
);
}
diff --git a/packages/components/src/components/table-stateless/style.scss b/packages/components/src/components/table-stateless/style.scss
index 6a14645b5ec..0f67700f3e1 100644
--- a/packages/components/src/components/table-stateless/style.scss
+++ b/packages/components/src/components/table-stateless/style.scss
@@ -1,6 +1,13 @@
-@use '../@shared/mixins' as *;
@use '../../styles/global' as *;
+@use '../../styles/kol-alert-mixin' as *;
+@use '../@shared/kol-button-mixin' as *;
+@use '../@shared/kol-popover-button-mixin' as *;
@use '../@shared/kol-table-stateless-mixin' as *;
+@use '../@shared/mixins' as *;
@use '../host-display-block' as *;
+@use '../tooltip/style' as *;
+@include kol-alert;
+@include kol-button-styles('kol-button');
+@include kol-popover-button-styles;
@include kol-table-stateless-styles;
diff --git a/packages/components/src/components/table-stateless/table-settings.e2e.ts b/packages/components/src/components/table-stateless/table-settings.e2e.ts
new file mode 100644
index 00000000000..e0f35a46e75
--- /dev/null
+++ b/packages/components/src/components/table-stateless/table-settings.e2e.ts
@@ -0,0 +1,243 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import type { TableHeaderCellsPropType, TableSettings } from '../../schema';
+import { KolEvent } from '../../utils/events';
+
+const DATA = [
+ { id: '1001', name: 'John', age: 30 },
+ { id: '1002', name: 'Jane', age: 25 },
+ { id: '1003', name: 'Bob', age: 35 },
+];
+
+const HEADERS: TableHeaderCellsPropType = {
+ horizontal: [
+ [
+ { key: 'id', label: 'ID' },
+ { key: 'name', label: 'Name' },
+ { key: 'age', label: 'Age' },
+ ],
+ ],
+};
+
+test.describe('kol-table-settings', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.setContent(``);
+ await page.waitForChanges();
+ });
+
+ test.describe('Basic Settings Popover Tests', () => {
+ test('it opens the settings popover when clicking the settings button', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+ const popover = page.getByTestId('popover-content');
+ await expect(popover).toBeVisible();
+ });
+
+ test('it closes the popover when clicking the cancel button', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+ const cancelButton = page.getByTestId('table-settings-cancel');
+ await cancelButton.click();
+ const popover = page.getByTestId('popover-content');
+ await expect(popover).not.toBeVisible();
+ });
+
+ test('it persists settings after closing and reopening the popover', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ // Hide the name column
+ const nameCheckbox = page.getByRole('checkbox', { name: 'Name' });
+ await nameCheckbox.click();
+
+ // Apply changes
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ // Reopen settings
+ await settingsButton.click();
+
+ // Verify name column is still hidden
+ await expect(nameCheckbox).not.toBeChecked();
+ });
+
+ test('it emits an DOM event when settings change', async ({ page }) => {
+ const tableStateless = page.locator('kol-table-stateless');
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ const eventPromise = tableStateless.evaluate((element: HTMLKolTableStatelessElement, KolEvent) => {
+ return new Promise((resolve) => {
+ element.addEventListener(KolEvent.settingsChange, (event: Event) => {
+ resolve((event as CustomEvent).detail as TableSettings);
+ });
+ });
+ }, KolEvent);
+
+ // Apply changes
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ await expect(eventPromise).resolves.toEqual({
+ columns: [
+ {
+ key: 'id',
+ label: 'ID',
+ position: 0,
+ visible: true,
+ },
+ {
+ key: 'name',
+ label: 'Name',
+ position: 1,
+ visible: true,
+ },
+ {
+ key: 'age',
+ label: 'Age',
+ position: 2,
+ visible: true,
+ },
+ ],
+ });
+ });
+ });
+
+ test.describe('Column Visibility Management', () => {
+ test('it lists all columns in the settings', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ const columnLabels = page.locator('.kol-table-settings__column > span');
+ await expect(columnLabels).toHaveText(['ID', 'Name', 'Age']);
+ });
+
+ test('it toggles visibility of individual columns', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ const nameCheckbox = page.getByRole('checkbox', { name: 'Name' });
+ await nameCheckbox.click();
+
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ // Verify name column is hidden in the table
+ const nameColumn = page.locator('kol-table-stateless-wc th').filter({ hasText: 'Name' });
+ await expect(nameColumn).not.toBeVisible();
+ });
+
+ test('it shows error message when all columns are hidden', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+ await page.waitForChanges();
+
+ // Hide all columns
+ const checkboxes = page.getByRole('checkbox');
+ for (const checkbox of await checkboxes.all()) {
+ await checkbox.click();
+ }
+
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ const errorMessage = page.locator('kol-table-settings-wc kol-alert-wc');
+ await expect(errorMessage).toBeVisible();
+ });
+
+ test('it removes error message when at least one column is visible', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+ await page.waitForChanges();
+
+ // Hide all columns
+ const checkboxes = page.getByRole('checkbox');
+ for (const checkbox of await checkboxes.all()) {
+ await checkbox.click();
+ }
+
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ // Show one column
+ await checkboxes.first().click();
+ await applyButton.click();
+
+ const errorMessage = page.locator('kol-table-settings-wc kol-alert-wc');
+ await expect(errorMessage).not.toBeVisible();
+ });
+ });
+
+ test.describe('Column Width Management', () => {
+ test('it accepts valid width values', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ const idWidthInput = page.getByRole('spinbutton', { name: 'ID' });
+ await idWidthInput.fill('50');
+
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ // Verify width is applied
+ const idColumn = page.locator('kol-table-stateless-wc th').filter({ hasText: 'ID' });
+ await expect(idColumn).toHaveAttribute('style', 'width: 50ch;');
+ });
+ });
+
+ test.describe('Column Order Management', () => {
+ test('it disables up button for first column', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ const firstUpButton = page.getByTestId('table-settings-move-up').first().locator('button');
+ await expect(firstUpButton).toBeDisabled();
+ });
+
+ test('it disables down button for last column', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ const lastDownButton = page.getByTestId('table-settings-move-down').last().locator('button');
+ await expect(lastDownButton).toBeDisabled();
+ });
+
+ test('it moves a column up', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ // Move name column up
+ const nameUpButton = page.getByTestId('table-settings-move-up').filter({ hasText: 'Name' });
+ await nameUpButton.click();
+
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ // Verify column order in table
+ const columns = page.locator('kol-table-stateless-wc th');
+ await expect(columns.nth(0)).toHaveText('Name');
+ await expect(columns.nth(1)).toHaveText('ID');
+ });
+
+ test('it moves a column down', async ({ page }) => {
+ const settingsButton = page.getByTestId('popover-button').locator('button');
+ await settingsButton.click();
+
+ // Move ID column down
+ const idDownButton = page.getByTestId('table-settings-move-down').filter({ hasText: 'ID' });
+ await idDownButton.click();
+
+ const applyButton = page.getByTestId('table-settings-apply');
+ await applyButton.click();
+
+ // Verify column order in table
+ const columns = page.locator('kol-table-stateless-wc th');
+ await expect(columns.nth(0)).toHaveText('Name');
+ await expect(columns.nth(1)).toHaveText('ID');
+ });
+ });
+});
diff --git a/packages/components/src/components/table-stateless/table-settings.tsx b/packages/components/src/components/table-stateless/table-settings.tsx
new file mode 100644
index 00000000000..eaf4d6d3305
--- /dev/null
+++ b/packages/components/src/components/table-stateless/table-settings.tsx
@@ -0,0 +1,169 @@
+import type { JSX } from '@stencil/core';
+import { Component, Element, h, Prop, State, Watch } from '@stencil/core';
+import { translate } from '../../i18n';
+import { KolAlertWcTag, KolButtonWcTag, KolHeadingTag, KolInputCheckboxTag, KolInputNumberTag, KolPopoverButtonWcTag } from '../../core/component-names';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+import type { TableSettingsPropType } from '../../schema/props/table-settings';
+import type { ColumnSettings } from '../../schema';
+
+/**
+ * @internal
+ */
+@Component({
+ tag: 'kol-table-settings-wc',
+ shadow: false,
+})
+export class KolTableSettings {
+ @Element() private readonly host?: HTMLKolTableSettingsWcElement;
+ @State() tableSettings: TableSettingsPropType = { columns: [] };
+ @State() errorMessage: string | null = null;
+ @Prop() _tableSettings: TableSettingsPropType = { columns: [] };
+
+ @Watch('_tableSettings')
+ handleTableSettingsChange(newValue: TableSettingsPropType) {
+ this.tableSettings = {
+ ...newValue,
+ columns: this.sortColumnsByPosition(newValue.columns),
+ };
+ }
+
+ public componentWillLoad() {
+ this.handleTableSettingsChange(this._tableSettings);
+ }
+
+ private popoverRef: HTMLKolPopoverButtonWcElement | undefined;
+
+ private sortColumnsByPosition(columns: ColumnSettings[]): ColumnSettings[] {
+ return [...columns].sort((colA, colB) => colA.position - colB.position);
+ }
+
+ private moveColumn(columnId: string, direction: 'up' | 'down'): void {
+ const columnSettings = [...this.tableSettings.columns];
+
+ const sourceIndex = columnSettings.findIndex((col) => col.key === columnId);
+ const targetIndex = direction === 'up' ? sourceIndex - 1 : sourceIndex + 1;
+
+ const source = columnSettings[sourceIndex];
+ const target = columnSettings[targetIndex];
+
+ const newCols = columnSettings.map((col) => {
+ if (col.key === source.key) return { ...col, position: target.position };
+ if (col.key === target.key) return { ...col, position: source.position };
+ return col;
+ });
+
+ // re-sort by position and update
+ this.tableSettings = {
+ ...this.tableSettings,
+ columns: this.sortColumnsByPosition(newCols),
+ };
+ }
+
+ private handleVisibilityChange(key: string, visible: unknown): void {
+ this.tableSettings = {
+ ...this.tableSettings,
+ columns: this.tableSettings.columns.map((col) => (col.key === key ? { ...col, visible: Boolean(visible) } : col)),
+ };
+ }
+
+ private handleWidthChange(key: string, width: unknown): void {
+ this.tableSettings = {
+ ...this.tableSettings,
+ columns: this.tableSettings.columns.map((col) => (col.key === key ? { ...col, width: Number(width) } : col)),
+ };
+ }
+
+ private handleCancel() {
+ void this.popoverRef?.hidePopover();
+ }
+
+ private handleSubmit(event: Event): void {
+ event.preventDefault();
+
+ const hasVisibleColumn = this.tableSettings.columns.some((column) => column.visible);
+
+ if (!hasVisibleColumn) {
+ this.errorMessage = translate('kol-table-settings-error-all-invisible');
+ return;
+ } else if (this.host) {
+ this.errorMessage = null;
+ dispatchDomEvent(this.host, KolEvent.settingsChange, this.tableSettings);
+ void this.popoverRef?.hidePopover();
+ }
+ }
+
+ public render(): JSX.Element {
+ const sortedColumns = [...this.tableSettings.columns].sort((a, b) => a.position - b.position);
+
+ return (
+ (this.popoverRef = el)}
+ class="kol-table-settings"
+ _icons="codicon codicon-settings-gear"
+ _label={translate('kol-table-settings')}
+ _popoverAlign="top"
+ _hideLabel
+ >
+
+
+
+ {this.errorMessage && }
+
+
+
+
+ );
+ }
+}
diff --git a/packages/components/src/components/table-stateless/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/table-stateless/test/__snapshots__/snapshot.spec.tsx.snap
index d375b646702..dcde1ad55a6 100644
--- a/packages/components/src/components/table-stateless/test/__snapshots__/snapshot.spec.tsx.snap
+++ b/packages/components/src/components/table-stateless/test/__snapshots__/snapshot.spec.tsx.snap
@@ -3,73 +3,76 @@
exports[`kol-table-stateless-wc should render with _label="Table with horizontal and vertical headers" _minWidth="400px" _headerCells={"horizontal":[[{"key":"header1","label":"Header1","textAlign":"left"},{"key":"header2","label":"Header2","textAlign":"center"},{"key":"header3","label":"Header3","textAlign":"right"}]],"vertical":[[{"key":"row1","label":"Row 1","textAlign":"left"},{"key":"row2","label":"Row 2","textAlign":"center"},{"key":"row3","label":"Row 3","textAlign":"right"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2","header3":"Cell 1.3"},{"header1":"Cell 2.1","header2":"Cell 2.2","header3":"Cell 2.3"},{"header1":"Cell 3.1","header2":"Cell 3.2","header3":"Cell 3.3"}] 1`] = `
-
-
-
- Table with horizontal and vertical headers
-
-
-
- |
-
-
-
-
-
- |
-
-
-
-
-
- |
- Cell 1.1
- |
-
- Cell 1.2
- |
-
- Cell 1.3
- |
-
-
-
- |
- Cell 2.1
- |
-
- Cell 2.2
- |
-
- Cell 2.3
- |
-
-
-
- |
- Cell 3.1
- |
-
- Cell 3.2
- |
-
- Cell 3.3
- |
-
-
-
+
+
`;
@@ -77,43 +80,46 @@ exports[`kol-table-stateless-wc should render with _label="Table with horizontal
exports[`kol-table-stateless-wc should render with _label="Table with only horizontal headers" _minWidth="400px" _headerCells={"horizontal":[[{"key":"header1","label":"Header 1","textAlign":"left"},{"key":"header2","label":"Header 2","textAlign":"center"}]],"vertical":[]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
-
-
-
- Table with only horizontal headers
-
-
-
-
-
-
-
- |
-
-
-
-
- |
- Cell 1.1
- |
-
- Cell 1.2
- |
-
-
- |
- Cell 2.1
- |
-
- Cell 2.2
- |
-
-
-
+
+
`;
@@ -121,58 +127,61 @@ exports[`kol-table-stateless-wc should render with _label="Table with only horiz
exports[`kol-table-stateless-wc should render with _label="Table with two horizontal header rows" _minWidth="400px" _headerCells={"horizontal":[[{"label":"Header 1","textAlign":"left"},{"label":"Header 2","textAlign":"center"}],[{"key":"header1","label":"Sub Header 1","textAlign":"left"},{"key":"header2","label":"Sub Header 2","textAlign":"center"}]],"vertical":[[{"key":"row-1","label":"Row 1","textAlign":"left"},{"key":"row-2","label":"Row 2","textAlign":"center"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
-
-
-
- Table with two horizontal header rows
-
-
-
- |
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
- |
- Cell 1.1
- |
-
- Cell 1.2
- |
-
-
-
- |
- Cell 2.1
- |
-
- Cell 2.2
- |
-
-
-
+
+
`;
@@ -180,58 +189,61 @@ exports[`kol-table-stateless-wc should render with _label="Table with two horizo
exports[`kol-table-stateless-wc should render with _label="Table with two spanned horizontal and vertical headers" _minWidth="400px" _headerCells={"horizontal":[[{"label":"H-Header","colSpan":2}],[{"key":"header1","label":"Sub H-Header 1"},{"key":"header2","label":"Sub H-Header 2"}]],"vertical":[[{"label":"V-Header","rowSpan":2}],[{"label":"Sub V-Header 1"},{"label":"Sub V-Header 2"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
-
-
-
- Table with two spanned horizontal and vertical headers
-
-
-
- |
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
- |
- Cell 1.1
- |
-
- Cell 1.2
- |
-
-
-
- |
- Cell 2.1
- |
-
- Cell 2.2
- |
-
-
-
+
+
`;
diff --git a/packages/components/src/core/component-names.ts b/packages/components/src/core/component-names.ts
index a3e84b4897d..ff604c52054 100644
--- a/packages/components/src/core/component-names.ts
+++ b/packages/components/src/core/component-names.ts
@@ -37,6 +37,7 @@ export let KolNavTag = 'kol-nav' as const;
export let KolPaginationTag = 'kol-pagination' as const;
export let KolPopoverWcTag = 'kol-popover-wc' as const;
export let KolPopoverButtonTag = 'kol-popover-button' as const;
+export let KolPopoverButtonWcTag = 'kol-popover-button-wc' as const;
export let KolProgressTag = 'kol-progress' as const;
export let KolQuoteTag = 'kol-quote' as const;
export let KolSelectTag = 'kol-select' as const;
@@ -44,6 +45,7 @@ export let KolSingleSelectTag = 'kol-single-select' as const;
export let KolSkipNavTag = 'kol-skip-nav' as const;
export let KolSpinTag = 'kol-spin' as const;
export let KolSplitButtonTag = 'kol-split-button' as const;
+export let KolTableSettingsWcTag = 'kol-table-settings-wc' as const;
export let KolTableStatefulTag = 'kol-table-stateful';
export let KolTableStatelessTag = 'kol-table-stateless' as const;
export let KolTableStatelessWcTag = 'kol-table-stateless-wc' as const;
@@ -98,6 +100,7 @@ export const setCustomTagNames = (transformTagName: (tagName: string) => string)
KolPaginationTag = transformTagName(KolPaginationTag as string) as 'kol-pagination';
KolPopoverWcTag = transformTagName(KolPopoverWcTag as string) as 'kol-popover-wc';
KolPopoverButtonTag = transformTagName(KolPopoverButtonTag as string) as 'kol-popover-button';
+ KolPopoverButtonWcTag = transformTagName(KolPopoverButtonWcTag as string) as 'kol-popover-button-wc';
KolProgressTag = transformTagName(KolProgressTag as string) as 'kol-progress';
KolQuoteTag = transformTagName(KolQuoteTag as string) as 'kol-quote';
KolSelectTag = transformTagName(KolSelectTag as string) as 'kol-select';
@@ -105,6 +108,7 @@ export const setCustomTagNames = (transformTagName: (tagName: string) => string)
KolSkipNavTag = transformTagName(KolSkipNavTag as string) as 'kol-skip-nav';
KolSpinTag = transformTagName(KolSpinTag as string) as 'kol-spin';
KolSplitButtonTag = transformTagName(KolSplitButtonTag as string) as 'kol-split-button';
+ KolTableSettingsWcTag = transformTagName(KolTableSettingsWcTag) as 'kol-table-settings-wc';
KolTableStatefulTag = transformTagName(KolTableStatefulTag) as 'kol-table-stateful';
KolTableStatelessTag = transformTagName(KolTableStatelessTag as string) as 'kol-table-stateless';
KolTableStatelessWcTag = transformTagName(KolTableStatelessWcTag as string) as 'kol-table-stateless-wc';
diff --git a/packages/components/src/locales/de.ts b/packages/components/src/locales/de.ts
index 9c2796df78f..3f5fffac42a 100644
--- a/packages/components/src/locales/de.ts
+++ b/packages/components/src/locales/de.ts
@@ -40,6 +40,14 @@ export default {
'table-selection-all': 'Alle auswählen',
'table-selection-none': 'Alle abwählen',
'table-selection-indeterminate': 'Alle auswählen bei teilweiser Auswahl',
+ 'table-settings': 'Tabellenkonfiguration',
+ 'table-settings-cancel': 'Abbrechen',
+ 'table-settings-apply': 'Übernehmen',
+ 'table-settings-show-column': 'Spalte {{column}} anzeigen',
+ 'table-settings-column-width': 'Breite von {{column}}',
+ 'table-settings-move-up': 'Spalte {{column}} nach oben verschieben',
+ 'table-settings-move-down': 'Spalte {{column}} nach unten verschieben',
+ 'table-settings-error-all-invisible': 'Mindestens eine Spalte muss sichtbar sein.',
dropdown: 'Auswahlliste',
'nav-label-open': 'Untermenü zu {{label}} öffnen',
'nav-label-close': 'Untermenü zu {{label}} schließen',
diff --git a/packages/components/src/locales/en.ts b/packages/components/src/locales/en.ts
index 38468a2909d..921d15cc59f 100644
--- a/packages/components/src/locales/en.ts
+++ b/packages/components/src/locales/en.ts
@@ -40,6 +40,14 @@ export default {
'table-selection-all': 'Select all',
'table-selection-none': 'Deselect all',
'table-selection-indeterminate': 'Select all with partial selection',
+ 'table-settings': 'Table configuration',
+ 'table-settings-cancel': 'Cancel',
+ 'table-settings-apply': 'Apply',
+ 'table-settings-show-column': 'Show column {{column}}',
+ 'table-settings-column-width': '{{column}} width',
+ 'table-settings-move-up': 'Move {{column}} column up',
+ 'table-settings-move-down': 'Move {{column}} column down',
+ 'table-settings-error-all-invisible': 'At least one column must be visible.',
dropdown: 'Dropdown',
'nav-label-open': 'Submenu for {{label}} open',
'nav-label-close': 'Submenu for {{label}} close',
diff --git a/packages/components/src/schema/components/table.ts b/packages/components/src/schema/components/table.ts
index 661b65a75e6..380f186b30e 100644
--- a/packages/components/src/schema/components/table.ts
+++ b/packages/components/src/schema/components/table.ts
@@ -5,6 +5,7 @@ import type { PropMinWidth } from '../props/min-width';
import type { PropPaginationPosition } from '../props/pagination-position';
import type { KoliBriSortDirection, KoliBriTableDataType, KoliBriTableHeaderCell, KoliBriTableSelection, Stringified } from '../types';
import type { KoliBriPaginationProps } from './pagination';
+import type { PropTableSettings } from '../props/table-settings';
export type KoliBriDataCompareFn = (a: KoliBriTableDataType, b: KoliBriTableDataType) => number;
@@ -44,7 +45,8 @@ type OptionalProps = {
} & PropTableDataFoot &
PropPaginationPosition &
PropTableSelection &
- StatefulPropTableCallbacks;
+ StatefulPropTableCallbacks &
+ PropTableSettings;
type RequiredStates = {
allowMultiSort: boolean;
@@ -59,7 +61,8 @@ type RequiredStates = {
type OptionalStates = {
sortDirection: KoliBriSortDirection;
selection: KoliBriTableSelection;
-} & StatefulPropTableCallbacks;
+} & StatefulPropTableCallbacks &
+ PropTableSettings;
export type TableStates = Generic.Element.Members;
export type TableAPI = Generic.Element.ComponentApi;
diff --git a/packages/components/src/schema/components/tableStateless.ts b/packages/components/src/schema/components/tableStateless.ts
index 56f5ea19f7c..cb02286a0f3 100644
--- a/packages/components/src/schema/components/tableStateless.ts
+++ b/packages/components/src/schema/components/tableStateless.ts
@@ -3,10 +3,11 @@ import type { PropLabel, PropTableCallbacks, PropTableData, PropTableDataFoot, P
import type { PropMinWidth } from '../props/min-width';
import type { PropTableHeaderCells } from '../props/table-header-cells';
import type { KoliBriTableDataType, KoliBriTableSelection } from '../types';
+import type { PropTableSettings } from '../props/table-settings';
type RequiredProps = PropLabel & PropMinWidth & PropTableData & PropTableHeaderCells;
-type OptionalProps = PropTableCallbacks & PropTableDataFoot & PropTableSelection;
+type OptionalProps = PropTableCallbacks & PropTableDataFoot & PropTableSelection & PropTableSettings;
type RequiredStates = {
headerCells: TableHeaderCells;
@@ -17,7 +18,8 @@ type RequiredStates = {
type OptionalStates = {
dataFoot: KoliBriTableDataType[];
selection: KoliBriTableSelection;
-} & PropTableCallbacks;
+} & PropTableCallbacks &
+ PropTableSettings;
export type TableStatelessProps = Generic.Element.Members;
export type TableStatelessStates = Generic.Element.Members;
diff --git a/packages/components/src/schema/props/table-settings.ts b/packages/components/src/schema/props/table-settings.ts
new file mode 100644
index 00000000000..3bc335ccb7a
--- /dev/null
+++ b/packages/components/src/schema/props/table-settings.ts
@@ -0,0 +1,19 @@
+import type { Generic } from 'adopted-style-sheets';
+
+import { watchValidator } from '../utils';
+import type { TableSettings } from '../types/table-settings';
+
+/* types */
+export type TableSettingsPropType = TableSettings;
+
+/**
+ * Defines the table settings including column visibility, order and width.
+ */
+export type PropTableSettings = {
+ tableSettings: TableSettingsPropType;
+};
+
+/* validator */
+export const validateTableSettings = (component: Generic.Element.Component, value?: TableSettingsPropType): void => {
+ watchValidator(component, `_tableSettings`, (value) => typeof value === 'object' && value !== null, new Set(['TableSettings']), value);
+};
diff --git a/packages/components/src/schema/types/index.ts b/packages/components/src/schema/types/index.ts
index 474dc2c3001..9d7432cc718 100644
--- a/packages/components/src/schema/types/index.ts
+++ b/packages/components/src/schema/types/index.ts
@@ -12,3 +12,4 @@ export * from './progress';
export * from './unknown';
export * from './w3c';
export * from './table';
+export * from './table-settings';
diff --git a/packages/components/src/schema/types/table-settings.ts b/packages/components/src/schema/types/table-settings.ts
new file mode 100644
index 00000000000..ba7fb46e1b9
--- /dev/null
+++ b/packages/components/src/schema/types/table-settings.ts
@@ -0,0 +1,11 @@
+export interface ColumnSettings {
+ key: string;
+ label: string;
+ visible: boolean;
+ position: number;
+ width?: number;
+}
+
+export interface TableSettings {
+ columns: ColumnSettings[];
+}
diff --git a/packages/components/src/utils/events.ts b/packages/components/src/utils/events.ts
index e0b4ce6b390..4d8b3005ec3 100644
--- a/packages/components/src/utils/events.ts
+++ b/packages/components/src/utils/events.ts
@@ -14,6 +14,7 @@ enum KolEvent {
sort = 'kolSort',
submit = 'kolSubmit',
toggle = 'kolToggle',
+ settingsChange = 'settingsChange',
}
function createKoliBriEvent(event: KolEvent, detail?: T): CustomEvent {
diff --git a/packages/components/stencil.config.ts b/packages/components/stencil.config.ts
index 2ed2641749c..9c9f9f81703 100644
--- a/packages/components/stencil.config.ts
+++ b/packages/components/stencil.config.ts
@@ -48,6 +48,7 @@ const TAGS = [
'kol-skip-nav',
'kol-spin',
'kol-split-button',
+ 'kol-table-settings-wc',
'kol-table-stateful',
'kol-table-stateless',
'kol-tabs',
@@ -71,6 +72,7 @@ const EXCLUDE_TAGS = [
'kol-link-wc',
'kol-popover-wc',
'kol-span-wc',
+ 'kol-table-settings-wc',
'kol-table-stateless-wc',
'kol-tooltip-wc',
];
diff --git a/packages/samples/react/src/components/table/predefined-settings.tsx b/packages/samples/react/src/components/table/predefined-settings.tsx
new file mode 100644
index 00000000000..19bacd39e4b
--- /dev/null
+++ b/packages/samples/react/src/components/table/predefined-settings.tsx
@@ -0,0 +1,41 @@
+import { SampleDescription } from '../SampleDescription';
+import { KolTableStateful } from '@public-ui/react';
+import type { FC } from 'react';
+import React from 'react';
+
+const DATA = [{ columnA: 'Column A', columnB: 'Column B', columnC: 'Column C' }];
+
+export const PredefinedSettings: FC = () => {
+ return (
+ <>
+
+ This example shows the table with predefined settings.
+
+
+
+ >
+ );
+};
diff --git a/packages/samples/react/src/components/table/render-cell.tsx b/packages/samples/react/src/components/table/render-cell.tsx
index cc378ebc4f2..64272431e8e 100644
--- a/packages/samples/react/src/components/table/render-cell.tsx
+++ b/packages/samples/react/src/components/table/render-cell.tsx
@@ -84,7 +84,7 @@ const HEADERS: KoliBriTableHeaders = {
},
{
label: 'Action (react)',
- key: 'order',
+ key: 'action',
width: '20em',
/* Example 4: Render function using React */
diff --git a/packages/samples/react/src/components/table/routes.ts b/packages/samples/react/src/components/table/routes.ts
index 7f0d80f36bc..4224acdfd9e 100644
--- a/packages/samples/react/src/components/table/routes.ts
+++ b/packages/samples/react/src/components/table/routes.ts
@@ -14,23 +14,25 @@ import { TableStatelessWithSingleSelection } from './stateless-with-single-selec
import { TableWithPagination } from './with-pagination';
import { InteractiveChildElements } from './interactive-child-elements';
import { MultiSortTable } from './multi-sort';
+import { PredefinedSettings } from './predefined-settings';
export const TABLE_ROUTES: Routes = {
table: {
'column-alignment': TableColumnAlignment,
'complex-headers': TableComplexHeaders,
'horizontal-scrollbar': TableHorizontalScrollbar,
+ 'interactive-child-elements': InteractiveChildElements,
+ 'multi-sort': MultiSortTable,
'pagination-position': PaginationPosition,
+ 'predefined-settings': PredefinedSettings,
'render-cell': TableRenderCell,
'sort-data': TableSortData,
- 'with-footer': TableWithFooter,
'stateful-with-selection': TableStatefulWithSelection,
'stateful-with-single-selection': TableStatefulWithSingleSelection,
+ stateless: TableStateless,
'stateless-with-selection': TableStatelessWithSelection,
'stateless-with-single-selection': TableStatelessWithSingleSelection,
+ 'with-footer': TableWithFooter,
'with-pagination': TableWithPagination,
- 'interactive-child-elements': InteractiveChildElements,
- stateless: TableStateless,
- 'multi-sort': MultiSortTable,
},
};
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png
index a94363f5007..efc5eb065c1 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png
index ac54223bc0e..9b641ee094e 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png
index 335d84ed7fb..99411e94068 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png
index 8690103f082..43d320aedb1 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png
index a3e81536b6a..1aa1c281c94 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png
index 7f78601f30b..7db703b2882 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png
index 0ad54085305..c3d8de64f63 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png
index b29600642ad..2f46b24c3e7 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png
index fe79f15b460..602df487c6e 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png
index 21c04cfb45c..3017fdbe5f3 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png
index 6e7e2372a06..25d81ab6487 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png
index 1d3d5c2f4cf..de6897ca604 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png
index a03d4056161..0116f32ca16 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png
index 35b8c5b4407..4efdca6c179 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png
index c886f202c2e..7f132186d87 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png
index a67cec894d9..d99cfd1c9cf 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png
index 1473f64749d..f55d771b024 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png
index f70c1dd5f6d..c05e929d683 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png
index 0a5b1e0d233..0d59f3645fe 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png
index 67d13a04f9c..ac0aa90cbd5 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png
index a31fd00c7b4..1d87be00a28 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png
index d568d70b929..f1c94229ac4 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png
index c54d0a7c16f..317902002f9 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png differ
diff --git a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png
index 89ef6dcf060..a5bfa2895f5 100644
Binary files a/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png and b/packages/test-tag-name-transformer/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png
index a94363f5007..efc5eb065c1 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png
index ac54223bc0e..9b641ee094e 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-button-short-key-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png
index 335d84ed7fb..99411e94068 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png
index 8690103f082..43d320aedb1 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-column-alignment-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png
index a3e81536b6a..1aa1c281c94 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png
index 7f78601f30b..7db703b2882 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-complex-headers-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png
index 0ad54085305..c3d8de64f63 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png
index b29600642ad..2f46b24c3e7 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-pagination-position-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png
index fe79f15b460..602df487c6e 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png
index 21c04cfb45c..3017fdbe5f3 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-sort-data-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png
index 6e7e2372a06..25d81ab6487 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png
index 1d3d5c2f4cf..de6897ca604 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-selection-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png
index a03d4056161..0116f32ca16 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png
index 35b8c5b4407..4efdca6c179 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateful-with-single-selection-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png
index c886f202c2e..7f132186d87 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png
index a67cec894d9..d99cfd1c9cf 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png
index 1473f64749d..f55d771b024 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-selection-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png
index f70c1dd5f6d..c05e929d683 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png
index 0a5b1e0d233..0d59f3645fe 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-with-single-selection-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png
index 67d13a04f9c..ac0aa90cbd5 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-stateless-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png
index a31fd00c7b4..1d87be00a28 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png
index d568d70b929..f1c94229ac4 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-footer-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png
index c54d0a7c16f..317902002f9 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-firefox-linux.png differ
diff --git a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png
index 89ef6dcf060..a5bfa2895f5 100644
Binary files a/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png and b/packages/themes/default/snapshots/theme-default/snapshot-for-table-with-pagination-zoom-firefox-linux.png differ
diff --git a/packages/themes/default/src/components/table-stateful.scss b/packages/themes/default/src/components/table-stateful.scss
index 6603835e939..afa5f7af1b1 100644
--- a/packages/themes/default/src/components/table-stateful.scss
+++ b/packages/themes/default/src/components/table-stateful.scss
@@ -1,7 +1,7 @@
@use '../mixins/kol-table-stateless-wc' as *;
@layer kol-theme-component {
- @include kol-table-stateless-wc;
+ @include kol-table-stateless-theme;
.kol-table-stateful {
&__pagination {
diff --git a/packages/themes/default/src/components/table-stateless.scss b/packages/themes/default/src/components/table-stateless.scss
index e9289aede74..72f0ae9f4fa 100644
--- a/packages/themes/default/src/components/table-stateless.scss
+++ b/packages/themes/default/src/components/table-stateless.scss
@@ -1,5 +1,5 @@
@use '../mixins/kol-table-stateless-wc' as *;
@layer kol-theme-component {
- @include kol-table-stateless-wc;
+ @include kol-table-stateless-theme;
}
diff --git a/packages/themes/default/src/mixins/kol-table-settings-wc.scss b/packages/themes/default/src/mixins/kol-table-settings-wc.scss
new file mode 100644
index 00000000000..1721cf7d795
--- /dev/null
+++ b/packages/themes/default/src/mixins/kol-table-settings-wc.scss
@@ -0,0 +1,37 @@
+@use './rem' as *;
+@use './button' as *;
+@use './focus-outline' as *;
+
+@mixin kol-table-settings-theme {
+ .kol-table-settings {
+ right: rem(8);
+ top: rem(8);
+
+ &__content {
+ padding: rem(24);
+ @include kol-button('kol-button'); // use buttons styles only in the content, not for the popover button
+ }
+
+ &__error-message {
+ display: block;
+ margin-top: rem(16);
+ }
+
+ &__columns {
+ padding: rem(8); // some space for hover and focus styles
+ }
+
+ &__actions {
+ border-top: var(--border-width) solid var(--color-mute-variant);
+ display: flex;
+ gap: rem(8);
+ justify-content: flex-end;
+ margin-top: rem(16);
+ padding-top: rem(16);
+ }
+ }
+
+ .kol-button:focus {
+ @include focus-outline;
+ }
+}
diff --git a/packages/themes/default/src/mixins/kol-table-stateless-wc.scss b/packages/themes/default/src/mixins/kol-table-stateless-wc.scss
index 3912d23521a..18c2787b3b8 100644
--- a/packages/themes/default/src/mixins/kol-table-stateless-wc.scss
+++ b/packages/themes/default/src/mixins/kol-table-stateless-wc.scss
@@ -1,6 +1,11 @@
@use './rem' as *;
+@use './kol-table-settings-wc' as *;
+@use './alert-wc' as *;
+
+@mixin kol-table-stateless-theme {
+ @include kol-table-settings-theme;
+ @include kol-alert-theme;
-@mixin kol-table-stateless-wc {
.kol-table {
$root: &;
@@ -26,7 +31,8 @@
}
&__caption {
- padding: rem(8);
+ padding: rem(8) var(--a11y-min-size) rem(8) rem(8);
+ min-height: calc(var(--a11y-min-size) + 2px); // leave some extra space so the settings button doesn't overlap the table borders
}
&__focus-element {
diff --git a/packages/themes/ecl/src/ecl-ec/mixins/kol-table-stateless-wc.scss b/packages/themes/ecl/src/ecl-ec/mixins/kol-table-stateless-wc.scss
index bc23ac1ba17..5e57a9c31de 100644
--- a/packages/themes/ecl/src/ecl-ec/mixins/kol-table-stateless-wc.scss
+++ b/packages/themes/ecl/src/ecl-ec/mixins/kol-table-stateless-wc.scss
@@ -1,15 +1,20 @@
@use '../../mixins/rem' as *;
+@use './alert-wc' as *;
@mixin kol-table-stateless-wc {
+ @include kol-alert-theme;
+
.kol-table {
$root: &;
display: block;
font-family: var(--font-family);
- overflow-x: auto;
- overflow-y: hidden;
- padding: 0.5em;
+ &__scroll-container {
+ overflow-x: auto;
+ overflow-y: hidden;
+ padding: 0.5em;
+ }
&__caption {
padding: 0.5em;
diff --git a/packages/themes/ecl/src/ecl-eu/mixins/kol-table-stateless-wc.scss b/packages/themes/ecl/src/ecl-eu/mixins/kol-table-stateless-wc.scss
index fa6466442bd..4630cb5bd32 100644
--- a/packages/themes/ecl/src/ecl-eu/mixins/kol-table-stateless-wc.scss
+++ b/packages/themes/ecl/src/ecl-eu/mixins/kol-table-stateless-wc.scss
@@ -1,6 +1,9 @@
@use '../../mixins/rem' as *;
+@use './alert-wc' as *;
@mixin kol-table-stateless-wc {
+ @include kol-alert-theme;
+
.kol-table {
$root: &;
|