diff --git a/src/app/examples/datatable/datatable-bulk-actions-side-panel.html b/src/app/examples/datatable/datatable-bulk-actions-side-panel.html
new file mode 100644
index 000000000..6588b1caa
--- /dev/null
+++ b/src/app/examples/datatable/datatable-bulk-actions-side-panel.html
@@ -0,0 +1,123 @@
+
+
+
+ Bulk actions with side panel detail
+
+
+
+
+
+ 0"
+ [selectionType]="checked().size > 0 ? undefined : 'single'"
+ [summaryRow]="checked().size > 0"
+ [summaryHeight]="tableConfig.rowHeightSmall"
+ [rows]="rows()"
+ [columns]="columns"
+ [rowHeight]="tableConfig.rowHeightSmall"
+ [scrollbarV]="true"
+ [footerHeight]="0"
+ [(selected)]="selectedRow"
+ (siResizeObserver)="table.recalculate()"
+ (selectedChange)="panelCollapsed.set(false)"
+ />
+
+
+
+
+ @if (checked().size > 0) {
+
+ } @else if (selectedRow().length === 1) {
+ @let selectedRow = this.selectedRow()[0];
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ checked().size }} selected
+
+
+
+
+
diff --git a/src/app/examples/datatable/datatable-bulk-actions-side-panel.ts b/src/app/examples/datatable/datatable-bulk-actions-side-panel.ts
new file mode 100644
index 000000000..f8fb5326e
--- /dev/null
+++ b/src/app/examples/datatable/datatable-bulk-actions-side-panel.ts
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) Siemens 2016 - 2026
+ * SPDX-License-Identifier: MIT
+ */
+import {
+ ChangeDetectionStrategy,
+ Component,
+ computed,
+ OnInit,
+ signal,
+ TemplateRef,
+ viewChild
+} from '@angular/core';
+import {
+ SiApplicationHeaderComponent,
+ SiHeaderBrandDirective
+} from '@siemens/element-ng/application-header';
+import { SI_DATATABLE_CONFIG, SiDatatableModule } from '@siemens/element-ng/datatable';
+import { SiEmptyStateComponent } from '@siemens/element-ng/empty-state';
+import { SiResizeObserverDirective } from '@siemens/element-ng/resize-observer';
+import { SiSidePanelComponent, SiSidePanelContentComponent } from '@siemens/element-ng/side-panel';
+import { ActivateEvent, NgxDatatableModule, TableColumn } from '@siemens/ngx-datatable';
+
+interface Employee {
+ id: number;
+ name: string;
+ department: string;
+ role: string;
+ status: string;
+}
+
+@Component({
+ selector: 'app-sample',
+ imports: [
+ NgxDatatableModule,
+ SiApplicationHeaderComponent,
+ SiDatatableModule,
+ SiEmptyStateComponent,
+ SiHeaderBrandDirective,
+ SiResizeObserverDirective,
+ SiSidePanelComponent,
+ SiSidePanelContentComponent
+ ],
+ templateUrl: './datatable-bulk-actions-side-panel.html',
+ styleUrl: './datatable-bulk-actions.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class SampleComponent implements OnInit {
+ protected readonly tableConfig = SI_DATATABLE_CONFIG;
+ protected readonly panelCollapsed = signal(true);
+ protected readonly selectedRow = signal([]);
+
+ private readonly bulkActionsTemplate = viewChild.required('bulkActionsTemplate', {
+ read: TemplateRef
+ });
+ private readonly checkboxCellTemplate = viewChild.required('checkboxCellTmpl', {
+ read: TemplateRef
+ });
+ private readonly checkboxHeaderTemplate = viewChild.required('checkboxHeaderTmpl', {
+ read: TemplateRef
+ });
+
+ protected readonly checked = signal(new Set());
+ protected readonly rows = signal([]);
+ columns!: TableColumn[];
+
+ private readonly departments = ['Engineering', 'Marketing', 'Sales', 'Support'];
+ private readonly roles = ['Developer', 'Designer', 'Manager', 'Analyst'];
+ private readonly statuses = ['Active', 'Inactive', 'On Leave'];
+
+ protected readonly allChecked = computed(
+ () => this.rows().length > 0 && this.checked().size === this.rows().length
+ );
+ protected readonly someChecked = computed(
+ () => this.checked().size > 0 && this.checked().size < this.rows().length
+ );
+
+ constructor() {
+ const initial: Employee[] = [];
+ for (let i = 1; i <= 50; i++) {
+ initial.push({
+ id: i,
+ name: 'Employee ' + i,
+ department: this.departments[i % this.departments.length],
+ role: this.roles[i % this.roles.length],
+ status: this.statuses[i % this.statuses.length]
+ });
+ }
+ this.rows.set(initial);
+ }
+
+ ngOnInit(): void {
+ this.columns = [
+ {
+ name: '',
+ width: 50,
+ sortable: false,
+ resizeable: false,
+ canAutoResize: false,
+ headerTemplate: this.checkboxHeaderTemplate(),
+ cellTemplate: this.checkboxCellTemplate(),
+ summaryTemplate: this.bulkActionsTemplate(),
+ cellClass: 'bulk-actions'
+ },
+ { name: 'Name', prop: 'name', summaryFunc: null },
+ { name: 'Department', prop: 'department', summaryFunc: null },
+ { name: 'Role', prop: 'role', summaryFunc: null },
+ { name: 'Status', prop: 'status', summaryFunc: null }
+ ];
+ }
+
+ toggleAll(): void {
+ if (this.allChecked()) {
+ this.checked.set(new Set());
+ } else {
+ this.checked.set(new Set(this.rows().map(r => r.id)));
+ }
+ this.updatePanel();
+ }
+
+ toggleRow(row: Employee): void {
+ const next = new Set(this.checked());
+ if (next.has(row.id)) {
+ next.delete(row.id);
+ } else {
+ next.add(row.id);
+ }
+ this.checked.set(next);
+ this.updatePanel();
+ }
+
+ acknowledge(): void {
+ if (this.checked().size > 0) {
+ alert(`Acknowledged ${this.checked().size} items`);
+ } else if (this.selectedRow()) {
+ alert(`Acknowledged ${this.selectedRow()!.length} items`);
+ }
+ }
+
+ closePanel(): void {
+ this.panelCollapsed.set(true);
+ this.selectedRow.set([]);
+ }
+
+ private updatePanel(): void {
+ if (this.checked().size > 0) {
+ this.selectedRow.set([]);
+ }
+ }
+}
diff --git a/src/app/examples/datatable/datatable-bulk-actions.html b/src/app/examples/datatable/datatable-bulk-actions.html
new file mode 100644
index 000000000..725bb1204
--- /dev/null
+++ b/src/app/examples/datatable/datatable-bulk-actions.html
@@ -0,0 +1,78 @@
+
+ 0"
+ [selectionType]="checked().size > 0 ? undefined : 'single'"
+ [summaryRow]="checked().size > 0"
+ [summaryHeight]="tableConfig.rowHeightSmall"
+ [rows]="rows()"
+ [columns]="columns"
+ [rowHeight]="tableConfig.rowHeightSmall"
+ [scrollbarV]="true"
+ [footerHeight]="0"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ checked().size }} selected
+
+ @if (collapsed()) {
+
+ } @else {
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/examples/datatable/datatable-bulk-actions.scss b/src/app/examples/datatable/datatable-bulk-actions.scss
new file mode 100644
index 000000000..55baaa989
--- /dev/null
+++ b/src/app/examples/datatable/datatable-bulk-actions.scss
@@ -0,0 +1,21 @@
+::ng-deep {
+ .datatable-summary-row {
+ position: sticky;
+ inset-block-start: 0;
+ z-index: 1;
+ }
+
+ .datatable-summary-row .datatable-body-cell {
+ inline-size: 100% !important; // stylelint-disable-line declaration-no-important
+
+ &:not(.bulk-actions) {
+ display: none !important; // stylelint-disable-line declaration-no-important
+ }
+ }
+
+ .bulk-actions-mode {
+ .datatable-body-row:not(.datatable-summary-row *):hover {
+ background-color: revert !important; // stylelint-disable-line declaration-no-important
+ }
+ }
+}
diff --git a/src/app/examples/datatable/datatable-bulk-actions.ts b/src/app/examples/datatable/datatable-bulk-actions.ts
new file mode 100644
index 000000000..c0e809042
--- /dev/null
+++ b/src/app/examples/datatable/datatable-bulk-actions.ts
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) Siemens 2016 - 2026
+ * SPDX-License-Identifier: MIT
+ */
+import { CdkMenuTrigger } from '@angular/cdk/menu';
+import {
+ ChangeDetectionStrategy,
+ Component,
+ computed,
+ OnInit,
+ signal,
+ TemplateRef,
+ viewChild
+} from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { elementDown2, elementOptionsVertical } from '@siemens/element-icons';
+import { SI_DATATABLE_CONFIG, SiDatatableModule } from '@siemens/element-ng/datatable';
+import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
+import { MenuItem, SiMenuFactoryComponent } from '@siemens/element-ng/menu';
+import { ElementDimensions, SiResizeObserverDirective } from '@siemens/element-ng/resize-observer';
+import { NgxDatatableModule, TableColumn } from '@siemens/ngx-datatable';
+
+type Status = 'Active' | 'Inactive' | 'On Leave';
+
+interface Employee {
+ id: number;
+ name: string;
+ department: string;
+ role: string;
+ status: Status;
+}
+
+const COLLAPSED_BREAKPOINT = 400;
+
+@Component({
+ selector: 'app-sample',
+ imports: [
+ NgxDatatableModule,
+ SiDatatableModule,
+ SiIconComponent,
+ SiMenuFactoryComponent,
+ SiResizeObserverDirective,
+ CdkMenuTrigger,
+ FormsModule
+ ],
+ templateUrl: './datatable-bulk-actions.html',
+ styleUrl: './datatable-bulk-actions.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class SampleComponent implements OnInit {
+ protected readonly icons = addIcons({ elementDown2, elementOptionsVertical });
+ protected readonly tableConfig = SI_DATATABLE_CONFIG;
+ protected readonly collapsed = signal(false);
+ protected readonly statusMenuOpen = signal(false);
+
+ private readonly bulkActionsTemplate = viewChild.required('bulkActionsTemplate', {
+ read: TemplateRef
+ });
+ private readonly checkboxCellTemplate = viewChild.required('checkboxCellTmpl', {
+ read: TemplateRef
+ });
+ private readonly checkboxHeaderTemplate = viewChild.required('checkboxHeaderTmpl', {
+ read: TemplateRef
+ });
+
+ protected readonly checked = signal(new Set());
+ protected readonly rows = signal([]);
+ columns!: TableColumn[];
+
+ private readonly departments = ['Engineering', 'Marketing', 'Sales', 'Support'];
+ private readonly roles = ['Developer', 'Designer', 'Manager', 'Analyst'];
+ private readonly statuses: Status[] = ['Active', 'Inactive', 'On Leave'];
+
+ protected readonly allActions: MenuItem[] = [
+ { type: 'action', label: 'Delete', action: () => this.delete() },
+ { type: 'action', label: 'Export', action: () => this.export() },
+ {
+ type: 'group',
+ label: 'Change status',
+ children: this.statuses.map(status => ({
+ type: 'action',
+ label: status,
+ action: () => this.changeStatus(status)
+ }))
+ }
+ ];
+
+ protected readonly statusMenuItems: MenuItem[] = this.statuses.map(status => ({
+ type: 'action',
+ label: status,
+ action: () => this.changeStatus(status)
+ }));
+
+ protected readonly allChecked = computed(
+ () => this.rows().length > 0 && this.checked().size === this.rows().length
+ );
+ protected readonly someChecked = computed(
+ () => this.checked().size > 0 && this.checked().size < this.rows().length
+ );
+
+ constructor() {
+ const initial: Employee[] = [];
+ for (let i = 1; i <= 50; i++) {
+ initial.push({
+ id: i,
+ name: 'Employee ' + i,
+ department: this.departments[i % this.departments.length],
+ role: this.roles[i % this.roles.length],
+ status: this.statuses[i % this.statuses.length]
+ });
+ }
+ this.rows.set(initial);
+ }
+
+ ngOnInit(): void {
+ this.columns = [
+ {
+ name: '',
+ width: 50,
+ sortable: false,
+ resizeable: false,
+ canAutoResize: false,
+ headerTemplate: this.checkboxHeaderTemplate(),
+ cellTemplate: this.checkboxCellTemplate(),
+ summaryTemplate: this.bulkActionsTemplate(),
+ cellClass: 'bulk-actions'
+ },
+ { name: 'Name', prop: 'name', summaryFunc: null },
+ { name: 'Department', prop: 'department', summaryFunc: null },
+ { name: 'Role', prop: 'role', summaryFunc: null },
+ { name: 'Status', prop: 'status', summaryFunc: null }
+ ];
+ }
+
+ toggleAll(): void {
+ if (this.allChecked()) {
+ this.checked.set(new Set());
+ } else {
+ this.checked.set(new Set(this.rows().map(r => r.id)));
+ }
+ }
+
+ toggleRow(row: Employee): void {
+ const next = new Set(this.checked());
+ if (next.has(row.id)) {
+ next.delete(row.id);
+ } else {
+ next.add(row.id);
+ }
+ this.checked.set(next);
+ }
+
+ delete(): void {
+ this.rows.set(this.rows().filter(row => !this.checked().has(row.id)));
+ this.checked.set(new Set());
+ }
+
+ export(): void {
+ alert(`Exporting ${this.checked().size} items`);
+ }
+
+ onResize(dimensions: ElementDimensions): void {
+ this.collapsed.set(dimensions.width < COLLAPSED_BREAKPOINT);
+ }
+
+ private changeStatus(status: Status): void {
+ this.rows.set(this.rows().map(row => (this.checked().has(row.id) ? { ...row, status } : row)));
+ }
+}