Table: Frozen columns (#109276)

* Table: Frozen columns

* i18n extract

* clamp the frozen columns by the total number of cols visible

* future-proof a bit: frozenColumns.left, add to kitchenSink
This commit is contained in:
Paul Marbach
2025-08-08 14:55:53 +00:00
committed by GitHub
parent 4e94e463cf
commit 992d189c0f
9 changed files with 56 additions and 5 deletions
@@ -410,6 +410,9 @@
"id": 1,
"options": {
"cellHeight": "sm",
"frozenColumns": {
"left": 1
},
"footer": {
"countRows": false,
"enablePagination": false,
@@ -1670,5 +1673,5 @@
"timezone": "",
"title": "Panel Tests - Table - Kitchen Sink",
"uid": "dcb9f5e9-8066-4397-889e-864b99555dbb",
"version": 7
"version": 8
}
@@ -87,6 +87,7 @@ export function TableNG(props: TableNGProps) {
enableSharedCrosshair = false,
enableVirtualization,
footerOptions,
frozenColumns = 0,
getActions = () => [],
height,
initialSortBy,
@@ -184,6 +185,19 @@ export function TableNG(props: TableNGProps) {
[theme]
);
const widths = useMemo(() => computeColWidths(visibleFields, availableWidth), [visibleFields, availableWidth]);
const numColsFullyInView = useMemo(
() =>
widths.reduce(
([count, remainingWidth], nextWidth) => {
if (remainingWidth - nextWidth >= 0) {
return [count + 1, remainingWidth - nextWidth];
}
return [count, 0];
},
[0, availableWidth]
)[0],
[widths, availableWidth]
);
const headerHeight = useHeaderHeight({
columnWidths: widths,
fields: visibleFields,
@@ -476,6 +490,7 @@ export function TableNG(props: TableNGProps) {
name: displayName,
width,
headerCellClass,
frozen: Math.min(frozenColumns, numColsFullyInView) > i,
renderCell: renderCellContent,
renderHeaderCell: ({ column, sortDirection }) => (
<HeaderCell
@@ -617,8 +632,11 @@ export function TableNG(props: TableNGProps) {
expandedRows,
filter,
footerCalcs,
frozenColumns,
getCellActions,
hasNestedFrames,
isCountRowsSet,
numColsFullyInView,
onCellFilterAdded,
panelContext,
rowHeight,
@@ -631,7 +649,6 @@ export function TableNG(props: TableNGProps) {
theme,
visibleFields,
widths,
getCellActions,
]);
// invalidate columns on every structureRev change. this supports width editing in the fieldConfig.
@@ -46,12 +46,20 @@ export const getGridStyles = (
'& > :not(.rdg-summary-row, .rdg-header-row) > .rdg-cell': {
'&:hover, &[aria-selected=true]': { boxShadow: theme.shadows.z2 },
// selected cells should appear below hovered cells.
'&:hover': { zIndex: theme.zIndex.tooltip - 2 },
'&[aria-selected=true]': { zIndex: theme.zIndex.tooltip - 3 },
'&:hover': { zIndex: theme.zIndex.tooltip - 4 },
'&[aria-selected=true]': { zIndex: theme.zIndex.tooltip - 5 },
},
'.rdg-cell.rdg-cell-frozen': { zIndex: theme.zIndex.tooltip - 2 },
'.rdg-header-row, .rdg-summary-row': {
'.rdg-cell': { zIndex: theme.zIndex.tooltip - 1 },
'.rdg-cell': {
zIndex: theme.zIndex.tooltip - 3,
'&.rdg-cell-frozen': {
zIndex: theme.zIndex.tooltip - 1,
},
},
},
}),
gridNested: css({
@@ -129,6 +129,7 @@ export interface BaseTableProps {
onCellFilterAdded?: TableFilterActionCallback;
footerOptions?: TableFooterCalc;
footerValues?: FooterItem[];
frozenColumns?: number;
enablePagination?: boolean;
cellHeight?: TableCellHeight;
structureRev?: number;
@@ -77,6 +77,7 @@ export function TablePanel(props: Props) {
onColumnResize={(displayName, resizedWidth) => onColumnResize(displayName, resizedWidth, props)}
onCellFilterAdded={panelContext.onAddAdHocFilter}
footerOptions={options.footer}
frozenColumns={options.frozenColumns?.left}
enablePagination={options.footer?.enablePagination}
cellHeight={options.cellHeight}
timeRange={timeRange}
@@ -128,6 +128,15 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
category,
defaultValue: defaultOptions.showHeader,
})
.addNumberInput({
path: 'frozenColumns.left',
name: t('table-new.name-frozen-columns', 'Frozen columns'),
description: t('table-new.description-frozen-columns', 'Columns are frozen from the left side of the table'),
settings: {
placeholder: 'none',
},
category,
})
.addRadio({
path: 'cellHeight',
name: t('table-new.name-cell-height', 'Cell height'),
@@ -44,6 +44,10 @@ composableKinds: PanelCfg: {
}
// Controls the height of the rows
cellHeight?: ui.TableCellHeight & (*"sm" | _)
// Defines the number of columns to freeze on the left side of the table
frozenColumns?: {
left?: number | *0
}
} @cuetsy(kind="interface")
FieldConfig: {
ui.TableFieldOptions
@@ -23,6 +23,12 @@ export interface Options {
* Represents the index of the selected frame
*/
frameIndex: number;
/**
* number of columns on the left side of the table that should be frozen
*/
frozenColumns?: {
left?: number;
};
/**
* Controls whether the panel should show the header
*/
+2
View File
@@ -12717,6 +12717,7 @@
"description-column-filter": "Enables/disables field filters in table",
"description-count-rows": "Display a single count for all data rows",
"description-fields": "Select the fields that should be calculated",
"description-frozen-columns": "Columns are frozen from the left side of the table",
"description-min-column-width": "The minimum width for column auto resizing",
"name-calculation": "Calculation",
"name-cell-height": "Cell height",
@@ -12728,6 +12729,7 @@
"name-count-rows": "Count rows",
"name-enable-pagination": "Enable pagination",
"name-fields": "Fields",
"name-frozen-columns": "Frozen columns",
"name-hide-in-table": "Hide in table",
"name-min-column-width": "Minimum column width",
"name-show-table-footer": "Show table footer",