Skip to content

Commit

Permalink
feat(pivot-table): truncate title and show full in tooltip (#1579) (#…
Browse files Browse the repository at this point in the history
…1622)

* feat(pivot-table): truncate title and show full in tooltip

* fix(pivot-table): set padding on hoverable div instead of container th

* fix(pivot-table): correctly show tooltip after resizing the container

* chore: simplify code and remove redundant prop

Co-authored-by: Jan Henrik Øverland <janhenrik.overland@gmail.com>
  • Loading branch information
HendrikThePendric and janhenrikoverland authored Nov 4, 2024
1 parent 74444aa commit f62b0c2
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 28 deletions.
41 changes: 41 additions & 0 deletions src/__demo__/PivotTable.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -1119,3 +1119,44 @@ storiesOf('PivotTable', module).add('DEGS', (_, { pivotTableOptions }) => {
</div>
)
})

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 (
<div
style={{
width,
height: 600,
marginTop: 50,
transition: 'width 1s',
}}
>
<button onClick={toggleWidth}>Toggle width</button>
<PivotTable data={data} visualization={visualization} />
</div>
)
}
)
62 changes: 47 additions & 15 deletions src/components/PivotTable/PivotTableTitleRow.js
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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 (
<tr>
<style jsx>{cellStyle}</style>
<PivotTableCell
isHeader
classes={['column-header', 'title']}
classes={['column-header', 'title-cell']}
colSpan={columnCount}
>
<div
style={{
marginLeft: position,
maxWidth: containerWidth,
textAlign: 'center',
}}
style={{ marginLeft, maxWidth }}
ref={containerRef}
data-test="visualization-title"
className="title-cell-content"
>
{title}
{isTitleTruncated ? (
<Tooltip content={title}>
{({ ref: tooltipRef, onMouseOver, onMouseOut }) => (
<div
ref={tooltipRef}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
className="title-cell-content"
style={{ maxWidth }}
>
{title}
</div>
)}
</Tooltip>
) : (
title
)}
</div>
</PivotTableCell>
</tr>
Expand All @@ -47,5 +80,4 @@ PivotTableTitleRow.propTypes = {
scrollPosition: PropTypes.shape({ x: PropTypes.number.isRequired })
.isRequired,
title: PropTypes.string.isRequired,
totalWidth: PropTypes.number.isRequired,
}
12 changes: 0 additions & 12 deletions src/components/PivotTable/PivotTableTitleRows.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,13 @@ 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 ? (
<PivotTableTitleRow
title={engine.options.subtitle}
scrollPosition={clippingResult.scrollPosition}
containerWidth={width}
totalWidth={
engine.adaptiveClippingController.columns.totalSize +
engine.adaptiveClippingController.columns.headerSize
}
/>
) : null}
{engine.visualization.filters?.length ? (
Expand All @@ -38,10 +30,6 @@ export const PivotTableTitleRows = ({ clippingResult, width }) => {
)}
scrollPosition={clippingResult.scrollPosition}
containerWidth={width}
totalWidth={
engine.adaptiveClippingController.columns.totalSize +
engine.adaptiveClippingController.columns.headerSize
}
/>
) : null}
</>
Expand Down
18 changes: 17 additions & 1 deletion src/components/PivotTable/styles/PivotTable.style.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit f62b0c2

Please sign in to comment.