From 02008323cb1096fbc0d96aa26d596559e5acac0b Mon Sep 17 00:00:00 2001 From: HendrikThePendric Date: Wed, 13 Sep 2023 09:25:44 +0200 Subject: [PATCH 1/4] feat(pivot-table): truncate title and show full in tooltip --- src/__demo__/PivotTable.stories.js | 26 ++++++++++ .../PivotTable/PivotTableTitleRow.js | 52 ++++++++++++++----- .../PivotTable/styles/PivotTable.style.js | 8 ++- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/__demo__/PivotTable.stories.js b/src/__demo__/PivotTable.stories.js index b4c46f346..2c631d079 100644 --- a/src/__demo__/PivotTable.stories.js +++ b/src/__demo__/PivotTable.stories.js @@ -1119,3 +1119,29 @@ storiesOf('PivotTable', module).add('DEGS', (_, { pivotTableOptions }) => { ) }) + +storiesOf('PivotTable', module).add( + 'Truncated header cell', + (_, { pivotTableOptions }) => { + 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..7ce48226a 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, useMemo } from 'react' import { PivotTableCell } from './PivotTableCell.js' import { usePivotTableEngine } from './PivotTableEngineContext.js' import { cell as cellStyle } from './styles/PivotTable.style.js' @@ -10,32 +11,55 @@ export const PivotTableTitleRow = ({ containerWidth, totalWidth, }) => { + const containerRef = useRef(null) const engine = usePivotTableEngine() const columnCount = engine.width + engine.rowDepth + const maxWidth = useMemo( + () => containerWidth - (engine.cellPadding * 2 + 2), + [containerWidth, engine.cellPadding] + ) + const marginLeft = useMemo( + () => + Math.max( + 0, + Math.min(scrollPosition?.x ?? 0, totalWidth - containerWidth) + ), + [containerWidth, scrollPosition.x, totalWidth] + ) + const titleIsTruncated = + containerRef.current?.scrollWidth > containerRef.current?.clientWidth - const [position, setPosition] = useState(scrollPosition.x) - useEffect(() => { - setPosition( - Math.max(0, Math.min(scrollPosition.x, totalWidth - containerWidth)) - ) - }, [containerWidth, scrollPosition.x, totalWidth]) return (
- {title} + {titleIsTruncated ? ( + + {({ ref: tooltipRef, onMouseOver, onMouseOut }) => ( +
+ {title} +
+ )} +
+ ) : ( + title + )}
diff --git a/src/components/PivotTable/styles/PivotTable.style.js b/src/components/PivotTable/styles/PivotTable.style.js index 23cfab64b..74bf840ec 100644 --- a/src/components/PivotTable/styles/PivotTable.style.js +++ b/src/components/PivotTable/styles/PivotTable.style.js @@ -109,10 +109,16 @@ export const cell = css` align-items: center; justify-content: center; } - .title { + .title-cell { font-weight: bold; background-color: #cddaed; } + .title-cell-content { + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } .row-header { background-color: #dae6f8; } From db184cda27406220422f5e4cb3dc76942ffd0979 Mon Sep 17 00:00:00 2001 From: HendrikThePendric Date: Thu, 14 Sep 2023 17:07:30 +0200 Subject: [PATCH 2/4] fix(pivot-table): set padding on hoverable div instead of container th --- src/components/PivotTable/styles/PivotTable.style.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/PivotTable/styles/PivotTable.style.js b/src/components/PivotTable/styles/PivotTable.style.js index 74bf840ec..00bf7c6a6 100644 --- a/src/components/PivotTable/styles/PivotTable.style.js +++ b/src/components/PivotTable/styles/PivotTable.style.js @@ -112,6 +112,7 @@ export const cell = css` .title-cell { font-weight: bold; background-color: #cddaed; + padding: 0; } .title-cell-content { text-align: center; @@ -119,6 +120,15 @@ export const cell = css` 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; } From c6a4d9b9900c1cddb74ffbc5a69586d82fb23049 Mon Sep 17 00:00:00 2001 From: HendrikThePendric Date: Wed, 27 Sep 2023 11:07:40 +0200 Subject: [PATCH 3/4] fix(pivot-table): correctly show tooltip after resizing the container --- src/__demo__/PivotTable.stories.js | 17 ++++++++++- .../PivotTable/PivotTableTitleRow.js | 28 ++++++++++++++++--- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/__demo__/PivotTable.stories.js b/src/__demo__/PivotTable.stories.js index 2c631d079..e06782146 100644 --- a/src/__demo__/PivotTable.stories.js +++ b/src/__demo__/PivotTable.stories.js @@ -1123,6 +1123,13 @@ 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, @@ -1139,7 +1146,15 @@ storiesOf('PivotTable', module).add( } return ( -
+
+
) diff --git a/src/components/PivotTable/PivotTableTitleRow.js b/src/components/PivotTable/PivotTableTitleRow.js index 7ce48226a..902a1e3b8 100644 --- a/src/components/PivotTable/PivotTableTitleRow.js +++ b/src/components/PivotTable/PivotTableTitleRow.js @@ -1,6 +1,6 @@ import { Tooltip } from '@dhis2/ui' import PropTypes from 'prop-types' -import React, { useRef, useMemo } from 'react' +import React, { useRef, useMemo, useState, useEffect } from 'react' import { PivotTableCell } from './PivotTableCell.js' import { usePivotTableEngine } from './PivotTableEngineContext.js' import { cell as cellStyle } from './styles/PivotTable.style.js' @@ -12,6 +12,8 @@ export const PivotTableTitleRow = ({ 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 = useMemo( @@ -26,8 +28,26 @@ export const PivotTableTitleRow = ({ ), [containerWidth, scrollPosition.x, totalWidth] ) - const titleIsTruncated = - containerRef.current?.scrollWidth > containerRef.current?.clientWidth + + useEffect(() => { + 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 ( @@ -43,7 +63,7 @@ export const PivotTableTitleRow = ({ data-test="visualization-title" className="title-cell-content" > - {titleIsTruncated ? ( + {isTitleTruncated ? ( {({ ref: tooltipRef, onMouseOver, onMouseOut }) => (
Date: Tue, 3 Oct 2023 12:02:32 +0200 Subject: [PATCH 4/4] chore: simplify code and remove redundant prop --- .../PivotTable/PivotTableTitleRow.js | 18 +++--------------- .../PivotTable/PivotTableTitleRows.js | 12 ------------ 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/components/PivotTable/PivotTableTitleRow.js b/src/components/PivotTable/PivotTableTitleRow.js index 902a1e3b8..ae9bfb576 100644 --- a/src/components/PivotTable/PivotTableTitleRow.js +++ b/src/components/PivotTable/PivotTableTitleRow.js @@ -1,6 +1,6 @@ import { Tooltip } from '@dhis2/ui' import PropTypes from 'prop-types' -import React, { useRef, useMemo, 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' @@ -9,25 +9,14 @@ 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 = useMemo( - () => containerWidth - (engine.cellPadding * 2 + 2), - [containerWidth, engine.cellPadding] - ) - const marginLeft = useMemo( - () => - Math.max( - 0, - Math.min(scrollPosition?.x ?? 0, totalWidth - containerWidth) - ), - [containerWidth, scrollPosition.x, totalWidth] - ) + const maxWidth = containerWidth - (engine.cellPadding * 2 + 2) + const marginLeft = Math.max(0, scrollPosition?.x ?? 0) useEffect(() => { if (containerRef.current) { @@ -91,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}