diff --git a/.changeset/itchy-moments-live.md b/.changeset/itchy-moments-live.md
new file mode 100644
index 0000000000..a3f55ff431
--- /dev/null
+++ b/.changeset/itchy-moments-live.md
@@ -0,0 +1,5 @@
+---
+"sit-onyx": minor
+---
+
+Implemented basic expandable row feature for DataGrid
diff --git a/packages/sit-onyx/src/components/OnyxDataGrid/examples/ExpandableRowExample.vue b/packages/sit-onyx/src/components/OnyxDataGrid/examples/ExpandableRowExample.vue
new file mode 100644
index 0000000000..3239573f77
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxDataGrid/examples/ExpandableRowExample.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
diff --git a/packages/sit-onyx/src/components/OnyxDataGrid/examples/OnyxDataGridFeatureExamples.stories.ts b/packages/sit-onyx/src/components/OnyxDataGrid/examples/OnyxDataGridFeatureExamples.stories.ts
index 011d77672e..2d41ca89a3 100644
--- a/packages/sit-onyx/src/components/OnyxDataGrid/examples/OnyxDataGridFeatureExamples.stories.ts
+++ b/packages/sit-onyx/src/components/OnyxDataGrid/examples/OnyxDataGridFeatureExamples.stories.ts
@@ -28,6 +28,10 @@ export const Editing: Story = {
...createAdvancedStoryExample("OnyxDataGrid", "EditingExample"),
};
+export const ExpandableRow: Story = {
+ ...createAdvancedStoryExample("OnyxDataGrid", "ExpandableRowExample"),
+};
+
export const LazyLoading: Story = {
...createAdvancedStoryExample("OnyxDataGrid", "LazyLoadingExample"),
};
diff --git a/packages/sit-onyx/src/components/OnyxDataGrid/features/all.ts b/packages/sit-onyx/src/components/OnyxDataGrid/features/all.ts
index d7da80f05e..437a287388 100644
--- a/packages/sit-onyx/src/components/OnyxDataGrid/features/all.ts
+++ b/packages/sit-onyx/src/components/OnyxDataGrid/features/all.ts
@@ -1,3 +1,4 @@
+export * from "./expandableRows/types.js";
export * from "./filtering/types.js";
export * from "./hideColumns/types.js";
export * from "./pagination/types.js";
@@ -7,6 +8,7 @@ export * from "./sorting/types.js";
export * from "./stickyColumns/types.js";
export { useEditing } from "./editing/editing.js";
+export { useExpandableRows } from "./expandableRows/expandableRows.js";
export { useFiltering } from "./filtering/filtering.js";
export { useHideColumns } from "./hideColumns/hideColumns.js";
export { usePagination } from "./pagination/pagination.js";
diff --git a/packages/sit-onyx/src/components/OnyxDataGrid/features/expandableRows/expandableRows.ts b/packages/sit-onyx/src/components/OnyxDataGrid/features/expandableRows/expandableRows.ts
new file mode 100644
index 0000000000..8d26bc91a1
--- /dev/null
+++ b/packages/sit-onyx/src/components/OnyxDataGrid/features/expandableRows/expandableRows.ts
@@ -0,0 +1,120 @@
+import { iconChevronDown, iconChevronUp } from "@sit-onyx/icons";
+import { h, ref } from "vue";
+import { DataGridFeatures } from "../../../../index.js";
+import OnyxSystemButton from "../../../OnyxSystemButton/OnyxSystemButton.vue";
+import { DataGridRowOptionsSymbol, type DataGridEntry } from "../../types.js";
+import { createFeature, type DataGridFeature, type InternalColumnConfig } from "../index.js";
+import type { UseExpandableRowsOptions } from "./types.js";
+
+const EXPANDABLE_ROWS_FEATURE = Symbol("ExpandableRowsFeature");
+const EXPAND_BUTTON_COLUMN = Symbol("ExpandButtonColumn");
+const EXPAND_BUTTON_RENDERER = Symbol("ExpandButtonRenderer");
+const DETAILS_COLUMN = Symbol("DetailsColumn");
+const DETAILS_RENDERER = Symbol("DetailsRenderer");
+
+export const useExpandableRows = (
+ options: UseExpandableRowsOptions,
+) =>
+ createFeature(() => {
+ const columnConfig = ref[]>>([]);
+
+ const expandedRows = ref>(new Set());
+ const toggleExpanded = (id: PropertyKey) => {
+ if (expandedRows.value.has(id)) {
+ expandedRows.value.delete(id);
+ } else {
+ expandedRows.value.add(id);
+ }
+ };
+
+ /**
+ * Adds the detail row for expandedd columns
+ */
+ const mapRow = (row: TEntry) => {
+ if (!expandedRows.value.has(row.id))
+ return [
+ // don't change anything
+ {
+ ...row,
+ [DataGridRowOptionsSymbol]: {
+ columns: columnConfig.value,
+ },
+ },
+ ];
+ else
+ return [
+ {
+ ...row,
+ [DataGridRowOptionsSymbol]: {
+ columns: columnConfig.value,
+ },
+ },
+ // add hidden row to keep striped pattern
+ {
+ [DataGridRowOptionsSymbol]: {
+ trAttributes: {
+ style: { display: "none" },
+ },
+ },
+ },
+ // add row for details
+ {
+ ...row,
+ id: row.id,
+ [DataGridRowOptionsSymbol]: {
+ columns: [{ key: DETAILS_COLUMN, type: { name: DETAILS_RENDERER } }],
+ },
+ },
+ ];
+ };
+
+ return {
+ name: EXPANDABLE_ROWS_FEATURE,
+ watch: [expandedRows, columnConfig],
+ modifyColumns: {
+ func: (cols) => {
+ const config = [
+ {
+ key: EXPAND_BUTTON_COLUMN,
+ label: "",
+ type: { name: EXPAND_BUTTON_RENDERER },
+ width: "min-content",
+ },
+ ...cols,
+ ] as InternalColumnConfig[];
+
+ // Store the column configuration with column for expand button for later reference
+ columnConfig.value = config;
+ return config;
+ },
+ },
+ mutation: {
+ func: (rows) => {
+ return rows.flatMap(mapRow);
+ },
+ },
+
+ typeRenderer: {
+ [EXPAND_BUTTON_RENDERER]: DataGridFeatures.createTypeRenderer