TableNG: Follow-up style fixes (#107274)

* open cell inspect in code mode for JSON panels

* increase opacity of TableCellActions background for legibility in overlap cases

* fix nested grid width calculation

* fix 'jumping' on hover overflow

* route transparency through (needs a scenes update)

* base row hover color on transparency

* update the colors for table

* remove console.log

* reinstate header toggle for nested row transformation

* fix #59474 - graceful handling when subtable has no rows

* fix i18n

* use TABLE.LINE_HEIGHT

* change nestedData back to const
eleijonmarck/lbac-rules/pagination-of-rules
Paul Marbach 2 weeks ago committed by GitHub
parent ebe494c7e6
commit a63a9357bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx
  2. 63
      packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
  3. 1
      packages/grafana-ui/src/components/Table/TableNG/constants.ts
  4. 9
      packages/grafana-ui/src/components/Table/TableNG/hooks.ts
  5. 1
      packages/grafana-ui/src/components/Table/TableNG/types.ts
  6. 3
      public/app/plugins/panel/table/table-new/TablePanel.tsx
  7. 3
      public/locales/en-US/grafana.json

@ -42,7 +42,8 @@ export function TableCellActions(props: TableCellActionsProps) {
dataProjection: 'EPSG:4326',
});
mode = TableCellInspectorMode.code;
} else if ('cellType' in cellOptions && cellOptions.cellType === TableCellDisplayMode.JSONView) {
}
if (cellOptions.type === TableCellDisplayMode.JSONView) {
mode = TableCellInspectorMode.code;
}

@ -81,13 +81,14 @@ export function TableNG(props: TableNGProps) {
onSortByChange,
showTypeIcons,
structureRev,
transparent,
width,
} = props;
const theme = useTheme2();
const styles = useStyles2(getGridStyles, {
enablePagination,
noHeader,
transparent,
});
const panelContext = usePanelContext();
@ -244,21 +245,9 @@ export function TableNG(props: TableNGProps) {
},
sortColumns,
rowHeight,
headerRowClass: styles.headerRow,
headerRowHeight: headerHeight,
bottomSummaryRows: hasFooter ? [{}] : undefined,
}) satisfies Partial<DataGridProps<TableRow, TableSummaryRow>>,
[
enableVirtualization,
resizeHandler,
sortColumns,
headerHeight,
styles.headerRow,
rowHeight,
hasFooter,
setSortColumns,
onSortByChange,
]
[enableVirtualization, resizeHandler, sortColumns, rowHeight, hasFooter, setSortColumns, onSortByChange]
);
interface Schema {
@ -437,6 +426,7 @@ export function TableNG(props: TableNGProps) {
return result;
}
const hasNestedHeaders = firstNestedData.meta?.custom?.noHeader !== true;
const renderRow = renderRowFactory(firstNestedData.fields, panelContext, expandedRows, enableSharedCrosshair);
const { columns: nestedColumns, cellRootRenderers: nestedCellRootRenderers } = fromFields(
firstNestedData.fields,
@ -486,11 +476,20 @@ export function TableNG(props: TableNGProps) {
}
const expandedRecords = applySort(frameToRecords(nestedData), nestedData.fields, sortColumns);
if (!expandedRecords.length) {
return (
<div className={styles.noDataNested}>
<Trans i18nKey="grafana-ui.table.nested-table.no-data">No data</Trans>
</div>
);
}
return (
<DataGrid<TableRow, TableSummaryRow>
{...commonDataGridProps}
className={cx(styles.grid, styles.gridNested)}
headerRowClass={cx(styles.headerRow, { [styles.displayNone]: !hasNestedHeaders })}
headerRowHeight={hasNestedHeaders ? defaultHeaderHeight : 0}
columns={nestedColumns}
rows={expandedRecords}
renderers={{ renderRow, renderCell: renderCellRoot }}
@ -509,6 +508,7 @@ export function TableNG(props: TableNGProps) {
crossFilterOrder,
crossFilterRows,
data,
defaultHeaderHeight,
defaultRowHeight,
enableSharedCrosshair,
expandedRows,
@ -552,6 +552,8 @@ export function TableNG(props: TableNGProps) {
className={styles.grid}
columns={structureRevColumns}
rows={paginatedRows}
headerRowClass={cx(styles.headerRow, { [styles.displayNone]: noHeader })}
headerRowHeight={headerHeight}
onCellClick={({ column, row }, { clientX, clientY, preventGridDefault }) => {
// Note: could be column.field; JS says yes, but TS says no!
const field = columns[column.idx].field;
@ -693,17 +695,20 @@ const renderRowFactory =
const getGridStyles = (
theme: GrafanaTheme2,
{ enablePagination, noHeader }: { enablePagination?: boolean; noHeader?: boolean }
{ enablePagination, transparent }: { enablePagination?: boolean; transparent?: boolean }
) => ({
grid: css({
'--rdg-background-color': theme.colors.background.primary,
'--rdg-header-background-color': theme.colors.background.primary,
'--rdg-border-color': theme.isDark ? '#282b30' : '#ebebec',
'--rdg-background-color': transparent ? theme.colors.background.canvas : theme.colors.background.primary,
'--rdg-header-background-color': transparent ? theme.colors.background.canvas : theme.colors.background.primary,
'--rdg-border-color': theme.colors.border.weak,
'--rdg-color': theme.colors.text.primary,
// note: this cannot have any transparency since default cells that
// overlay/overflow on hover inherit this background and need to occlude cells below
'--rdg-row-hover-background-color': theme.isDark ? '#212428' : '#f4f5f5',
'--rdg-row-background-color': transparent ? theme.colors.background.canvas : theme.colors.background.primary,
'--rdg-row-hover-background-color': transparent
? theme.colors.background.primary
: theme.colors.background.secondary,
// TODO: magic 32px number is unfortunate. it would be better to have the content
// flow using flexbox rather than hard-coding this size via a calc
@ -723,15 +728,24 @@ const getGridStyles = (
}),
gridNested: css({
height: '100%',
width: `calc(100% - ${COLUMN.EXPANDER_WIDTH - 1}px)`,
width: `calc(100% - ${COLUMN.EXPANDER_WIDTH - TABLE.CELL_PADDING * 2 - 1}px)`,
overflow: 'visible',
marginLeft: COLUMN.EXPANDER_WIDTH - 1,
marginLeft: COLUMN.EXPANDER_WIDTH - TABLE.CELL_PADDING - 1,
marginBlock: TABLE.CELL_PADDING,
}),
cellNested: css({
'&[aria-selected=true]': {
outline: 'none',
},
}),
noDataNested: css({
height: TABLE.NESTED_NO_DATA_HEIGHT,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: theme.colors.text.secondary,
fontSize: theme.typography.h4.fontSize,
}),
cellActions: css({
display: 'none',
position: 'absolute',
@ -739,7 +753,7 @@ const getGridStyles = (
margin: 'auto',
height: '100%',
color: theme.colors.text.primary,
background: theme.isDark ? 'rgba(0, 0, 0, 0.3)' : 'rgba(255, 255, 255, 0.7)',
background: theme.isDark ? 'rgba(0, 0, 0, 0.7)' : 'rgba(255, 255, 255, 0.7)',
padding: theme.spacing.x0_5,
paddingInlineStart: theme.spacing.x1,
}),
@ -752,12 +766,14 @@ const getGridStyles = (
headerRow: css({
paddingBlockStart: 0,
fontWeight: 'normal',
...(noHeader ? { display: 'none' } : {}),
'& .rdg-cell': {
height: '100%',
alignItems: 'flex-end',
},
}),
displayNone: css({
display: 'none',
}),
paginationContainer: css({
alignItems: 'center',
display: 'flex',
@ -835,6 +851,7 @@ const getCellStyles = (
whiteSpace: 'pre-line',
height: 'fit-content',
minWidth: 'fit-content',
paddingBlock: (rowHeight - TABLE.LINE_HEIGHT) / 2 - 1,
}),
},
}),

@ -14,5 +14,6 @@ export const TABLE = {
SCROLL_BAR_WIDTH: 8,
SCROLL_BAR_MARGIN: 2,
LINE_HEIGHT: 22,
NESTED_NO_DATA_HEIGHT: 60,
BORDER_RIGHT: 0.666667,
};

@ -503,9 +503,13 @@ export function useRowHeight({
return 0;
}
// Ensure we have a minimum height (defaultHeight) for the nested table even if data is empty
const rowCount = row.data?.length ?? 0;
return Math.max(defaultHeight, defaultHeight * rowCount + headerHeight);
if (rowCount === 0) {
return TABLE.NESTED_NO_DATA_HEIGHT + TABLE.CELL_PADDING * 2;
}
const nestedHeaderHeight = row.data?.meta?.custom?.noHeader ? 0 : defaultHeight;
return Math.max(defaultHeight, defaultHeight * rowCount + nestedHeaderHeight + TABLE.CELL_PADDING * 2);
}
// regular rows
@ -519,7 +523,6 @@ export function useRowHeight({
fields,
hasNestedFrames,
hasWrappedCols,
headerHeight,
maxWrapCellOptions,
colWidths,
]);

@ -131,6 +131,7 @@ export interface BaseTableProps {
enablePagination?: boolean;
cellHeight?: TableCellHeight;
structureRev?: number;
transparent?: boolean;
/** @alpha Used by SparklineCell when provided */
timeRange?: TimeRange;
enableSharedCrosshair?: boolean;

@ -26,7 +26,7 @@ import { Options } from './panelcfg.gen';
interface Props extends PanelProps<Options> {}
export function TablePanel(props: Props) {
const { data, height, width, options, fieldConfig, id, timeRange, replaceVariables } = props;
const { data, height, width, options, fieldConfig, id, timeRange, replaceVariables, transparent } = props;
useMemo(() => {
cacheFieldDisplayNames(data.series);
@ -82,6 +82,7 @@ export function TablePanel(props: Props) {
fieldConfig={fieldConfig}
getActions={_getActions}
structureRev={data.structureRev}
transparent={transparent}
/>
);

@ -8011,6 +8011,9 @@
"filter-popup-match-case": "Match case",
"inspect-drawer-title": "Inspect value",
"inspect-menu-label": "Inspect value",
"nested-table": {
"no-data": "No data"
},
"no-values-label": "No values",
"pagination-summary": "{{itemsRangeStart}} - {{displayedEnd}} of {{numRows}} rows"
},

Loading…
Cancel
Save