diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 7a5ee45aa3..cb4d4f3d15 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -28,7 +28,7 @@ The `start` task used in our turbo configuration is now marked as `persistent` a
=== Improvements
-
+- https://github.com/eclipse-sirius/sirius-web/issues/4345[#4345] [table] Make table cells independently selectable
== v2025.1.0
diff --git a/packages/tables/frontend/sirius-components-tables/src/cells/Cell.tsx b/packages/tables/frontend/sirius-components-tables/src/cells/Cell.tsx
index 10b5e2e4a1..fa75fe90d1 100644
--- a/packages/tables/frontend/sirius-components-tables/src/cells/Cell.tsx
+++ b/packages/tables/frontend/sirius-components-tables/src/cells/Cell.tsx
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2024 Obeo.
+ * Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
@@ -11,8 +11,10 @@
* Obeo - initial API and implementation
*******************************************************************************/
+import { Selection, useSelection } from '@eclipse-sirius/sirius-components-core';
import Typography from '@mui/material/Typography';
import { memo } from 'react';
+import { makeStyles } from 'tss-react/mui';
import {
GQLCell,
GQLCheckboxCell,
@@ -34,10 +36,23 @@ const isMultiSelectCell = (cell: GQLCell): cell is GQLMultiSelectCell => cell.__
const isTextfieldCell = (cell: GQLCell): cell is GQLTextfieldCell => cell.__typename === 'TextfieldCell';
const isIconLabelCell = (cell: GQLCell): cell is GQLIconLabelCell => cell.__typename === 'IconLabelCell';
+const useStyles = makeStyles()(() => ({
+ cell: {
+ width: '100%',
+ },
+}));
+
export const Cell = memo(({ editingContextId, representationId, tableId, cell, disabled }: CellProps) => {
+ const { classes } = useStyles();
+ const { setSelection } = useSelection();
if (cell) {
+ const onClick = () => {
+ const newSelection: Selection = { entries: [{ id: cell.targetObjectId, kind: cell.targetObjectKind }] };
+ setSelection(newSelection);
+ };
+ let cellContent: JSX.Element | undefined;
if (isCheckboxCell(cell)) {
- return (
+ cellContent = (
);
} else if (isTextfieldCell(cell)) {
- return (
+ cellContent = (
);
} else if (isSelectCell(cell)) {
- return (
+ cellContent = (
);
} else if (isMultiSelectCell(cell)) {
- return (
+ cellContent = (
);
} else if (isIconLabelCell(cell)) {
- return (
+ cellContent = (
);
}
+ if (cellContent) {
+ return (
+
+ {cellContent}
+
+ );
+ }
}
return ;
});
diff --git a/packages/tables/frontend/sirius-components-tables/src/table/TableContent.tsx b/packages/tables/frontend/sirius-components-tables/src/table/TableContent.tsx
index c85bf29492..c5131a3c14 100644
--- a/packages/tables/frontend/sirius-components-tables/src/table/TableContent.tsx
+++ b/packages/tables/frontend/sirius-components-tables/src/table/TableContent.tsx
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2024 Obeo.
+ * Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
*******************************************************************************/
import { Selection, useSelection } from '@eclipse-sirius/sirius-components-core';
import Box from '@mui/material/Box';
+import { Theme, useTheme } from '@mui/material/styles';
import { MaterialReactTable, MRT_DensityState, MRT_TableOptions, useMaterialReactTable } from 'material-react-table';
import { memo, useEffect, useState } from 'react';
import { SettingsButton } from '../actions/SettingsButton';
@@ -43,6 +44,7 @@ export const TableContent = memo(
enablePagination,
}: TableProps) => {
const { selection, setSelection } = useSelection();
+ const theme: Theme = useTheme();
const { columns } = useTableColumns(
editingContextId,
@@ -165,10 +167,6 @@ export const TableContent = memo(
state: { columnSizing, columnVisibility, globalFilter, density, columnFilters },
muiTableBodyRowProps: ({ row }) => {
return {
- onClick: () => {
- const newSelection: Selection = { entries: [{ id: row.original.targetObjectId, kind: 'Object' }] };
- setSelection(newSelection);
- },
selected: selection.entries.map((entry) => entry.id).includes(row.original.targetObjectId),
sx: {
backgroundColor: 'transparent', // required to remove the default mui backgroundColor that is defined as !important
@@ -177,6 +175,19 @@ export const TableContent = memo(
},
};
},
+ muiTableBodyCellProps: ({ cell, row }) => {
+ const rowSelected = selection.entries.map((entry) => entry.id).includes(row.original.targetObjectId);
+ const cellTargetObjectId = row.original.cells.find(
+ (originalCell) => originalCell.columnId === cell.column.id
+ )?.targetObjectId;
+ const cellSelected =
+ cellTargetObjectId && selection.entries.map((entry) => entry.id).includes(cellTargetObjectId);
+ return {
+ sx: {
+ border: !rowSelected && cellSelected ? `2px dashed ${theme.palette.action.selected}` : undefined,
+ },
+ };
+ },
renderTopToolbarCustomActions: () => (
@@ -200,7 +211,18 @@ export const TableContent = memo(
},
},
renderRowActions: ({ row }) => (
- <>
+ {
+ const newSelection: Selection = {
+ entries: [
+ {
+ id: row.original.targetObjectId,
+ kind: row.original.targetObjectKind,
+ },
+ ],
+ };
+ setSelection(newSelection);
+ }}>
{enableRowSizing ? (
) : null}
- >
+
),
};
diff --git a/packages/tables/frontend/sirius-components-tables/src/table/TableContent.types.ts b/packages/tables/frontend/sirius-components-tables/src/table/TableContent.types.ts
index b7259cd642..a189ad202d 100644
--- a/packages/tables/frontend/sirius-components-tables/src/table/TableContent.types.ts
+++ b/packages/tables/frontend/sirius-components-tables/src/table/TableContent.types.ts
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2024 Obeo.
+ * Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
@@ -86,6 +86,7 @@ export interface GQLColumn {
export interface GQLLine {
id: string;
targetObjectId: string;
+ targetObjectKind: string;
cells: GQLCell[];
headerLabel: string;
headerIconURLs: string[];
@@ -104,6 +105,8 @@ export interface GQLCell {
__typename: string;
id: string;
columnId: string;
+ targetObjectId: string;
+ targetObjectKind: string;
}
export interface GQLTextfieldCell extends GQLCell {