Skip to content

Commit

Permalink
fix(chartArea): ent-3601 tooltip hover and clipping, x-axis (#594)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdcabrera committed Mar 4, 2021
1 parent cde8893 commit e093009
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 55 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
},
"dependencies": {
"@patternfly/patternfly": "4.80.3",
"@patternfly/react-charts": "6.13.8",
"@patternfly/react-charts": "6.14.2",
"@patternfly/react-core": "4.90.2",
"@patternfly/react-icons": "4.8.4",
"@patternfly/react-styles": "4.7.29",
Expand Down Expand Up @@ -146,7 +146,7 @@
"redux-promise-middleware": "^6.1.2",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0",
"victory-create-container": "^35.4.8"
"victory-create-container": "^35.4.10"
},
"devDependencies": {
"apidoc-mock": "^3.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,13 +866,31 @@ exports[`ChartArea Component should handle custom chart tooltips: custom tooltip
"y": -10,
}
}
labelComponent={<FlyoutComponent />}
labelComponent={
<ChartCursorTooltip
flyout={
<ChartCursorFlyout
pathComponent={<Path />}
role="presentation"
shapeRendering="auto"
/>
}
flyoutStyle={
Object {
"fill": "transparent",
}
}
labelComponent={<FlyoutComponent />}
renderInPortal={true}
/>
}
labels={[Function]}
mouseFollowTooltips={true}
portalComponent={<Portal />}
portalZIndex={99}
responsive={true}
role="img"
voronoiPadding={60}
voronoiPadding={50}
/>
}
domain={
Expand Down Expand Up @@ -1094,13 +1112,31 @@ exports[`ChartArea Component should handle custom chart tooltips: renderTooltip:
"y": -10,
}
}
labelComponent={<FlyoutComponent />}
labelComponent={
<ChartCursorTooltip
flyout={
<ChartCursorFlyout
pathComponent={<Path />}
role="presentation"
shapeRendering="auto"
/>
}
flyoutStyle={
Object {
"fill": "transparent",
}
}
labelComponent={<FlyoutComponent />}
renderInPortal={true}
/>
}
labels={[Function]}
mouseFollowTooltips={true}
portalComponent={<Portal />}
portalZIndex={99}
responsive={true}
role="img"
voronoiPadding={60}
voronoiPadding={50}
/>
`;

Expand Down
82 changes: 42 additions & 40 deletions src/components/chartArea/chartArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import {
ChartStack,
ChartThreshold,
ChartThemeColor,
ChartArea as PfChartArea
ChartArea as PfChartArea,
ChartCursorFlyout,
ChartCursorTooltip
} from '@patternfly/react-charts';
import _cloneDeep from 'lodash/cloneDeep';
import { helpers } from '../../common';

/**
* FixMe: chart redraw issues, possibly related by...
* - resize setup,
* - internal caching of the graph, and
* - restructuring how the query props are passed through product view
* FixMe: chart redraw flash related to custom tooltips use
* Removing custom tooltips corrects redraw issues. As a temporary patch, caching at the selector alleviates
* the symptoms.
*/
/**
* A wrapper for Patternfly and Victory charts/graphs.
Expand Down Expand Up @@ -310,20 +311,6 @@ class ChartArea extends React.Component {
return tooltipDataSet;
}

/**
* ToDo: monitor Victory charts release version increment around Voronoi container attributes.
* Future updates could lead to additional unexpected behavior. Victory charts released a patch/fix
* around attribute behavior for Voronoi containers. The behavior was already "unexpected" in that there appears
* to be a need to provide the "label" attribute when using the "labelComponent" attribute, even if "label" is
* just a pass-through. Providing `label={() => ''}` was a work-around, that is now `label={obj => obj}`. See
* - https://github.com/FormidableLabs/victory/blob/master/CHANGELOG.md#3436-2020-05-18
* - https://github.com/FormidableLabs/victory/pull/1581
*/
/**
* FixMe: Victory charts voronoi containers throw inaccurate coordinates on large graph widths
* Issue is "patched" by removing the "x" dimension attribute for voronoi.
* - https://github.com/RedHatInsights/curiosity-frontend/issues/318
*/
/**
* Return a chart/graph tooltip Victory container component to allow custom HTML tooltips.
*
Expand All @@ -339,43 +326,48 @@ class ChartArea extends React.Component {

const VictoryVoronoiCursorContainer = createContainer('voronoi', 'cursor');
const parsedTooltipData = this.getTooltipData();
let globalContainerBounds = {};
let globalTooltipBounds = {};

const applyParsedTooltipData = ({ datum }) => {
const t = parsedTooltipData.find(v => v.x === datum.x) || {};
return t?.tooltip || '';
};

const FlyoutComponent = obj => {
const containerRef = this.containerRef.current;
const tooltipRef = this.tooltipRef.current;
const containerBounds = (containerRef && containerRef.getBoundingClientRect()) || {};
const tooltipBounds = (tooltipRef && tooltipRef.getBoundingClientRect()) || {};
const getXCoordinate = (x, width, tooltipWidth) => {
let xCoordinate = x + 10;

if (containerBounds.right) {
globalContainerBounds = containerBounds;
if (x > width / 2) {
xCoordinate = x - 10 - tooltipWidth / 2;
}

if (tooltipBounds.right) {
globalTooltipBounds = tooltipBounds;
}
return xCoordinate;
};

let xCoordinate = obj.x + 10;
const getYCoordinate = (y, height, tooltipHeight) => {
let yCoordinate = y + 10;

if (
globalContainerBounds.right < globalTooltipBounds.right ||
obj.x + globalTooltipBounds.width > globalContainerBounds.right / 2
) {
xCoordinate = obj.x - 10 - globalTooltipBounds.width;
if (y > height / 2) {
yCoordinate = y - 10 - tooltipHeight;
}

return yCoordinate;
};

const FlyoutComponent = obj => {
const containerRef = this.containerRef.current;
const tooltipRef = this.tooltipRef.current;
const containerBounds = (containerRef && containerRef.getBoundingClientRect()) || { width: 0, height: 0 };
const tooltipBounds = (tooltipRef && tooltipRef.getBoundingClientRect()) || { width: 0, height: 0 };
const htmlContent = applyParsedTooltipData({ ...obj });

if (htmlContent) {
return (
<g>
<foreignObject x={xCoordinate} y={obj.y / 2.2} width="100%" height="100%">
<foreignObject
x={getXCoordinate(obj.x, containerBounds.width, tooltipBounds.width)}
y={getYCoordinate(obj.y, containerBounds.height, tooltipBounds.height)}
width="100%"
height="100%"
>
<div ref={this.tooltipRef} style={{ display: 'inline-block' }} xmlns="http://www.w3.org/1999/xhtml">
{htmlContent}
</div>
Expand All @@ -387,12 +379,22 @@ class ChartArea extends React.Component {
return <g />;
};

const labelComponent = (
<ChartCursorTooltip
flyout={<ChartCursorFlyout />}
flyoutStyle={{ fill: 'transparent' }}
labelComponent={<FlyoutComponent />}
renderInPortal
/>
);

return (
<VictoryVoronoiCursorContainer
cursorDimension="x"
labels={obj => obj}
labelComponent={<FlyoutComponent />}
voronoiPadding={60}
labelComponent={labelComponent}
voronoiPadding={50}
mouseFollowTooltips
/>
);
}
Expand Down
Loading

0 comments on commit e093009

Please sign in to comment.