Skip to content
Merged
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ You can also check the

## Unreleased

Nothing yet.
- Features
- Added a way to make table columns responsive

### 6.2.5 - 2025-12-02

Expand Down
1 change: 1 addition & 0 deletions app/charts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ export const getInitialConfig = (
settings: {
showSearch: true,
showAllRows: false,
limitColumnWidths: false,
},
links: {
enabled: false,
Expand Down
29 changes: 24 additions & 5 deletions app/charts/table/cell-desktop.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Theme } from "@mui/material";
import { Box, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import { hcl } from "d3-color";
import { ScaleLinear } from "d3-scale";
Expand All @@ -10,6 +10,7 @@ import { LinkedCellWrapper } from "@/charts/table/linked-cell-wrapper";
import { ColumnMeta, TableChartState } from "@/charts/table/table-state";
import { Tag } from "@/charts/table/tag";
import { Flex } from "@/components/flex";
import { OverflowTooltip } from "@/components/overflow-tooltip";
import { Observation } from "@/domain/data";

const useStyles = makeStyles((theme: Theme) => ({
Expand Down Expand Up @@ -61,12 +62,15 @@ export const CellDesktop = ({
barShowBackground,
} = columnMeta;
const classes = useStyles();
const { links } = useChartState() as TableChartState;
const { links, shouldApplyWidthLimits } = useChartState() as TableChartState;

switch (columnMeta.type) {
case "text":
const textContent = columnMeta.formatter(cell);

return (
<Flex
{...cell.getCellProps()}
sx={{
alignItems: "center",
justifyContent:
Expand All @@ -78,19 +82,33 @@ export const CellDesktop = ({
fontWeight: textStyle,
px: 3,
}}
{...cell.getCellProps()}
>
<LinkedCellWrapper cell={cell} columnMeta={columnMeta} links={links}>
{columnMeta.formatter(cell)}
{shouldApplyWidthLimits ? (
<OverflowTooltip arrow title={textContent}>
<Typography
component="span"
variant="inherit"
noWrap
sx={{ lineHeight: 1.5 }}
>
{textContent}
</Typography>
</OverflowTooltip>
) : (
<Box component="span" sx={{ lineHeight: 1.5 }}>
{textContent}
</Box>
)}
</LinkedCellWrapper>
</Flex>
);
case "category":
const { colorScale: cColorScale } = columnMeta;
return (
<Flex
sx={{ alignItems: "center", fontWeight: textStyle, pl: 1, pr: 3 }}
{...cell.getCellProps()}
sx={{ alignItems: "center", fontWeight: textStyle, pl: 1, pr: 3 }}
>
<LinkedCellWrapper cell={cell} columnMeta={columnMeta} links={links}>
<Tag tagColor={cColorScale(cell.value)}>
Expand Down Expand Up @@ -128,6 +146,7 @@ export const CellDesktop = ({
sx={{
flexDirection: "column",
justifyContent: "center",
alignItems: "flex-end",
// Padding is a constant accounted for in the
// widthScale domain (see table state).
px: `${BAR_CELL_PADDING}px`,
Expand Down
1 change: 1 addition & 0 deletions app/charts/table/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const TABLE_HEIGHT = 600;
export const BAR_CELL_PADDING = 12;
export const SORTING_ARROW_WIDTH = 24;
export const LIMITED_COLUMN_WIDTH = 120;
2 changes: 2 additions & 0 deletions app/charts/table/linked-cell-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import { Icon } from "@/icons";

const useStyles = makeStyles((theme: Theme) => ({
link: {
overflow: "hidden",
display: "inline-flex",
alignItems: "center",
gap: theme.spacing(1),
minWidth: 0,
color: "inherit",
fontWeight: "inherit",
textDecoration: "none",
Expand Down
55 changes: 47 additions & 8 deletions app/charts/table/table-content.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Box, TableSortLabel, Theme } from "@mui/material";
import { Box, TableSortLabel, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import clsx from "clsx";
import { createContext, ReactNode, useContext, useMemo } from "react";
import { HeaderGroup } from "react-table";

import { SORTING_ARROW_WIDTH } from "@/charts/table/constants";
import { ColumnMeta } from "@/charts/table/table-state";
import { columnCanBeWidthLimited } from "@/charts/table/width-limit";
import { Flex } from "@/components/flex";
import { OpenMetadataPanelWrapper } from "@/components/metadata-panel";
import { OverflowTooltip } from "@/components/overflow-tooltip";
import { Observation } from "@/domain/data";

/** Workaround because react-window can't pass props to inner element */
Expand All @@ -16,6 +18,7 @@ type TableContentProps = {
tableColumnsMeta: Record<string, ColumnMeta>;
customSortCount: number;
totalColumnsWidth: number;
shouldApplyWidthLimits: boolean;
};

const TableContentContext = createContext<TableContentProps | undefined>(
Expand All @@ -27,6 +30,7 @@ export const TableContentProvider = ({
tableColumnsMeta,
customSortCount,
totalColumnsWidth,
shouldApplyWidthLimits,
children,
}: TableContentProps & { children: ReactNode }) => {
const value = useMemo(() => {
Expand All @@ -35,8 +39,15 @@ export const TableContentProvider = ({
tableColumnsMeta,
customSortCount,
totalColumnsWidth,
shouldApplyWidthLimits,
};
}, [headerGroups, tableColumnsMeta, customSortCount, totalColumnsWidth]);
}, [
headerGroups,
tableColumnsMeta,
customSortCount,
totalColumnsWidth,
shouldApplyWidthLimits,
]);

return (
<TableContentContext.Provider value={value}>
Expand Down Expand Up @@ -75,8 +86,13 @@ export const TableContent = ({ children }: { children: ReactNode }) => {
throw Error("Please wrap TableContent in TableContentProvider");
}

const { headerGroups, tableColumnsMeta, customSortCount, totalColumnsWidth } =
ctx;
const {
headerGroups,
tableColumnsMeta,
customSortCount,
totalColumnsWidth,
shouldApplyWidthLimits,
} = ctx;

return (
<>
Expand All @@ -87,10 +103,13 @@ export const TableContent = ({ children }: { children: ReactNode }) => {
// eslint-disable-next-line react/jsx-key
<Box {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => {
const { dim, columnComponentType } =
const { type, dim, columnComponentType } =
tableColumnsMeta[column.id];
// We assume that the customSortCount items are at the beginning of the sorted array, so any item with a lower index must be a custom sorted one
const isCustomSorted = column.sortedIndex < customSortCount;
const hasWidthLimit =
shouldApplyWidthLimits && columnCanBeWidthLimited(type);
const headerText = `${column.Header}`;

return (
// eslint-disable-next-line react/jsx-key
Expand All @@ -102,6 +121,7 @@ export const TableContent = ({ children }: { children: ReactNode }) => {
: undefined
)}
{...column.getHeaderProps(column.getSortByToggleProps())}
title={headerText}
>
<TableSortLabel
active={isCustomSorted}
Expand All @@ -110,12 +130,31 @@ export const TableContent = ({ children }: { children: ReactNode }) => {
"& svg": {
opacity: isCustomSorted ? 1 : 0.5,
},
...(hasWidthLimit && {
minWidth: 0,
}),
}}
>
<OpenMetadataPanelWrapper component={dim}>
<span style={{ fontWeight: "bold" }}>
{column.render("Header")}
</span>
{hasWidthLimit ? (
<OverflowTooltip arrow title={headerText}>
<Typography
component="span"
variant="inherit"
noWrap
sx={{ fontWeight: "bold", lineHeight: 1.5 }}
>
{column.render("Header")}
</Typography>
</OverflowTooltip>
) : (
<Box
component="span"
sx={{ fontWeight: "bold", lineHeight: 1.5 }}
>
{column.render("Header")}
</Box>
)}
</OpenMetadataPanelWrapper>
</TableSortLabel>
</Flex>
Expand Down
Loading