diff --git a/src/__demo__/PivotTable.stories.js b/src/__demo__/PivotTable.stories.js
index b4c46f346..e06782146 100644
--- a/src/__demo__/PivotTable.stories.js
+++ b/src/__demo__/PivotTable.stories.js
@@ -1119,3 +1119,44 @@ storiesOf('PivotTable', module).add('DEGS', (_, { pivotTableOptions }) => {
)
})
+
+storiesOf('PivotTable', module).add(
+ 'Truncated header cell',
+ (_, { pivotTableOptions }) => {
+ const widths = [250, 200, 500]
+ const [width, setWidth] = useState(250)
+ const toggleWidth = () =>
+ setWidth(
+ (currentWidth) =>
+ widths[widths.indexOf(currentWidth) + 1] ?? widths[0]
+ )
+ const visualization = {
+ ...narrativeVisualization,
+ ...visualizationReset,
+ ...pivotTableOptions,
+ columns: narrativeVisualization.filters,
+ filters: narrativeVisualization.columns,
+ rowTotals: true,
+ colTotals: true,
+ }
+
+ const data = {
+ ...narrativeData,
+ rows: [narrativeData.rows[0]],
+ }
+
+ return (
+
+ )
+ }
+)
diff --git a/src/components/PivotTable/PivotTableTitleRow.js b/src/components/PivotTable/PivotTableTitleRow.js
index 681eaf1ab..ae9bfb576 100644
--- a/src/components/PivotTable/PivotTableTitleRow.js
+++ b/src/components/PivotTable/PivotTableTitleRow.js
@@ -1,5 +1,6 @@
+import { Tooltip } from '@dhis2/ui'
import PropTypes from 'prop-types'
-import React, { useState, useEffect } from 'react'
+import React, { useRef, useState, useEffect } from 'react'
import { PivotTableCell } from './PivotTableCell.js'
import { usePivotTableEngine } from './PivotTableEngineContext.js'
import { cell as cellStyle } from './styles/PivotTable.style.js'
@@ -8,34 +9,66 @@ export const PivotTableTitleRow = ({
title,
scrollPosition,
containerWidth,
- totalWidth,
}) => {
+ const containerRef = useRef(null)
+ const [scrollWidth, setScrollWidth] = useState(0)
+ const [isTitleTruncated, setIsTitleTruncated] = useState(false)
const engine = usePivotTableEngine()
const columnCount = engine.width + engine.rowDepth
+ const maxWidth = containerWidth - (engine.cellPadding * 2 + 2)
+ const marginLeft = Math.max(0, scrollPosition?.x ?? 0)
- const [position, setPosition] = useState(scrollPosition.x)
useEffect(() => {
- setPosition(
- Math.max(0, Math.min(scrollPosition.x, totalWidth - containerWidth))
- )
- }, [containerWidth, scrollPosition.x, totalWidth])
+ if (containerRef.current) {
+ /* Only set `scrollWidth` once, because during a CSS transition
+ * the reported value can sometimes be equal to `clientWidth`
+ * even though the text doesn't fit. Due to `white-space: nowrap`
+ * and `overflow: hidden` the `scrollWidth` should remain constant,
+ * so we can assume this initial value is correct. */
+ if (!scrollWidth) {
+ setScrollWidth(containerRef.current.scrollWidth)
+ }
+ const currentScrollWidth =
+ scrollWidth ?? containerRef.current.scrollWidth
+ const newIsTitleTruncated =
+ currentScrollWidth > containerRef.current.clientWidth
+ if (newIsTitleTruncated !== isTitleTruncated) {
+ setIsTitleTruncated(newIsTitleTruncated)
+ }
+ }
+ }, [containerWidth, scrollWidth, isTitleTruncated])
+
return (
- {title}
+ {isTitleTruncated ? (
+
+ {({ ref: tooltipRef, onMouseOver, onMouseOut }) => (
+
+ {title}
+
+ )}
+
+ ) : (
+ title
+ )}
@@ -47,5 +80,4 @@ PivotTableTitleRow.propTypes = {
scrollPosition: PropTypes.shape({ x: PropTypes.number.isRequired })
.isRequired,
title: PropTypes.string.isRequired,
- totalWidth: PropTypes.number.isRequired,
}
diff --git a/src/components/PivotTable/PivotTableTitleRows.js b/src/components/PivotTable/PivotTableTitleRows.js
index 34ad04e33..8a3439c9d 100644
--- a/src/components/PivotTable/PivotTableTitleRows.js
+++ b/src/components/PivotTable/PivotTableTitleRows.js
@@ -13,10 +13,6 @@ export const PivotTableTitleRows = ({ clippingResult, width }) => {
title={engine.options.title}
scrollPosition={clippingResult.scrollPosition}
containerWidth={width}
- totalWidth={
- engine.adaptiveClippingController.columns.totalSize +
- engine.adaptiveClippingController.columns.headerSize
- }
/>
) : null}
{engine.options.subtitle ? (
@@ -24,10 +20,6 @@ export const PivotTableTitleRows = ({ clippingResult, width }) => {
title={engine.options.subtitle}
scrollPosition={clippingResult.scrollPosition}
containerWidth={width}
- totalWidth={
- engine.adaptiveClippingController.columns.totalSize +
- engine.adaptiveClippingController.columns.headerSize
- }
/>
) : null}
{engine.visualization.filters?.length ? (
@@ -38,10 +30,6 @@ export const PivotTableTitleRows = ({ clippingResult, width }) => {
)}
scrollPosition={clippingResult.scrollPosition}
containerWidth={width}
- totalWidth={
- engine.adaptiveClippingController.columns.totalSize +
- engine.adaptiveClippingController.columns.headerSize
- }
/>
) : null}
>
diff --git a/src/components/PivotTable/styles/PivotTable.style.js b/src/components/PivotTable/styles/PivotTable.style.js
index 1390163e5..60466810a 100644
--- a/src/components/PivotTable/styles/PivotTable.style.js
+++ b/src/components/PivotTable/styles/PivotTable.style.js
@@ -111,9 +111,25 @@ export const cell = css`
align-items: center;
justify-content: center;
}
- .title {
+ .title-cell {
font-weight: bold;
background-color: #cddaed;
+ padding: 0;
+ }
+ .title-cell-content {
+ text-align: center;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .title-cell.displaydensity-COMPACT > .title-cell-content {
+ padding: ${DISPLAY_DENSITY_PADDING_COMPACT}px;
+ }
+ .title-cell.displaydensity-NORMAL > .title-cell-content {
+ padding: ${DISPLAY_DENSITY_PADDING_NORMAL}px;
+ }
+ .title-cell.displaydensity-COMFORTABLE > .title-cell-content {
+ padding: ${DISPLAY_DENSITY_PADDING_COMFORTABLE}px;
}
.row-header {
background-color: #dae6f8;