Skip to content

Commit de7642e

Browse files
authored
Merge pull request #73 from williaster/chris--falsy-tooltip
add support to hide tooltips, key => seriesKey to avoid React prop clash.
2 parents 49733e9 + f88831a commit de7642e

File tree

12 files changed

+63
-23
lines changed

12 files changed

+63
-23
lines changed

packages/demo/examples/01-xy-chart/ResponsiveXYChart.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ export const formatDate = timeFormat('%b %d');
1313
export const dateFormatter = date => formatDate(parseDate(date));
1414

1515
// this is a little messy to handle all cases across series types
16-
function renderTooltip({ datum, key, color }) {
16+
function renderTooltip({ datum, seriesKey, color }) {
1717
const { x, x0, y, value } = datum;
1818
let xVal = x || x0;
1919
if (typeof xVal === 'string') {
2020
xVal = parseDate(xVal) === null ? xVal : dateFormatter(xVal);
2121
} else if (typeof xVal !== 'string' && Number(xVal) > 1000000) {
2222
xVal = formatDate(xVal);
2323
}
24-
const yVal = key && datum[key] ? datum[key] : (y || value || '--');
24+
const yVal = seriesKey && datum[seriesKey] ? datum[seriesKey] : (y || value || '--');
2525
return (
2626
<div>
27-
{key &&
27+
{seriesKey &&
2828
<div>
29-
<strong style={{ color }}>{key}</strong>
29+
<strong style={{ color }}>{seriesKey}</strong>
3030
</div>}
3131
<div>
3232
<strong style={{ color }}>x </strong>
@@ -44,8 +44,8 @@ function ResponsiveXYChart({ screenWidth, children, ...rest }) {
4444
return (
4545
<XYChart
4646
theme={theme}
47-
width={Math.min(1000, screenWidth / 1.5)}
48-
height={Math.min(1000 / 2, screenWidth / 1.5 / 2)}
47+
width={Math.min(700, screenWidth / 1.5)}
48+
height={Math.min(700 / 2, screenWidth / 1.5 / 2)}
4949
renderTooltip={renderTooltip}
5050
{...rest}
5151
>

packages/histogram/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ tickValues | PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.
155155
156156
157157
### Tooltips
158-
Tooltips are supported for histogram `BarSeries`. The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<Histogram />` as shown in the above example. This function takes an object with the shape `{ event, datum, data, color }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above. `datum` corresponds to the _binned_ data point, see the above-specified shapes which depend on whether your bins are categorical or numeric. `color` represents the bar fill.
158+
Tooltips are supported for histogram `BarSeries`. The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<Histogram />` as shown in the above example. This function takes an object with the shape `{ event, datum, data, color }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above. `datum` corresponds to the _binned_ data point, see the above-specified shapes which depend on whether your bins are categorical or numeric. `color` represents the bar fill. If this function returns a `falsy` value, a tooltip will not be rendered.
159159
160160
Under the covers this will wrap the `<Histogram />` component in the exported `<WithTooltip />` HOC, which wraps the `svg` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".
161161
@@ -169,7 +169,7 @@ Name | Type | Default | Description
169169
------------ | ------------- | ------- | ----
170170
children | PropTypes.func or PropTypes.object | - | Child function (to call) or element (to clone) with onMouseMove, onMouseLeave, and tooltipData props/keys
171171
className | PropTypes.string | - | Class name to add to the `<div>` container wrapper
172-
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color }) => node`
172+
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color }) => node`. If this function returns a `falsy` value, a tooltip will not be rendered.
173173
styles | PropTypes.object | {} | Styles to add to the `<div>` container wrapper
174174
TooltipComponent | PropTypes.func or PropTypes.object | `@vx`'s `TooltipWithBounds` | Component (not instance) to use as the tooltip container component. It is passed `top` and `left` numbers for positioning
175175
tooltipTimeout | PropTypes.number | 200 | Timeout in ms for the tooltip to hide upon calling `onMouseLeave`

packages/network/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ See the demo at <a href="https://williaster.github.io/data-ui" target="_blank">w
1212

1313

1414
### Tooltips
15-
Tooltips are controlled with the `renderTooltip` function passed to `<Network />`. This function takes an object with the shape `{ event, index, id, data }` as input and is expected to return the inner _contents_ of the tooltip (not the tooltip container!) as shown above. Under the covers this will wrap the `<Network />` component in the exported `<WithTooltip />` HOC, which wraps the `svg` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".
15+
Tooltips are controlled with the `renderTooltip` function passed to `<Network />`. This function takes an object with the shape `{ event, index, id, data }` as input and is expected to return the inner _contents_ of the tooltip (not the tooltip container!) as shown above. If this function returns a `falsy` value, a tooltip will not be rendered.
16+
17+
Under the covers this will wrap the `<Network />` component in the exported `<WithTooltip />` HOC, which wraps the `svg` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".
1618

1719
### Roadmap
1820
- more layout algorithms

packages/radial-chart/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ export default () => (
6161
```
6262

6363
### Tooltips
64-
The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<RadialChart />`. This function takes an object with the shape `{ event, datum, data, fraction }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above. Under the covers this will wrap the `<RadialChart />` component in the exported `<WithTooltip />` HOC, which wraps the `svg` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".
64+
The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<RadialChart />`. This function takes an object with the shape `{ event, datum, data, fraction }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above. If this function returns a `falsy` value, a tooltip will not be rendered.
65+
66+
Under the covers this will wrap the `<RadialChart />` component in the exported `<WithTooltip />` HOC, which wraps the `svg` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".
6567

6668
If you'd like more customizability over tooltip rendering you can do either of the following:
6769

@@ -74,7 +76,7 @@ Name | Type | Default | Description
7476
------------ | ------------- | ------- | ----
7577
children | PropTypes.func or PropTypes.object | - | Child function (to call) or element (to clone) with onMouseMove, onMouseLeave, and tooltipData props/keys
7678
className | PropTypes.string | - | Class name to add to the `<div>` container wrapper
77-
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, fraction }) => node`
79+
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, fraction }) => node`. If this function returns a `falsy` value, a tooltip will not be rendered.
7880
styles | PropTypes.object | {} | Styles to add to the `<div>` container wrapper
7981
TooltipComponent | PropTypes.func or PropTypes.object | `@vx`'s `TooltipWithBounds` | Component (not instance) to use as the tooltip container component. It is passed `top` and `left` numbers for positioning
8082
tooltipTimeout | PropTypes.number | 200 | Timeout in ms for the tooltip to hide upon calling `onMouseLeave`

packages/shared/src/enhancer/WithTooltip.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ class WithTooltip extends React.PureComponent {
9494
tooltipData,
9595
};
9696

97+
const tooltipContent = renderTooltip
98+
&& tooltipOpen
99+
&& TooltipComponent
100+
&& renderTooltip(tooltipData);
101+
97102
return (
98103
<div style={styles} className={className}>
99104

@@ -102,13 +107,13 @@ class WithTooltip extends React.PureComponent {
102107
? children(childProps)
103108
: React.cloneElement(React.Children.only(children), childProps)}
104109

105-
{tooltipOpen && TooltipComponent && renderTooltip &&
110+
{Boolean(tooltipContent) &&
106111
<TooltipComponent
107112
key={Math.random()}
108113
top={tooltipTop}
109114
left={tooltipLeft}
110115
>
111-
{renderTooltip(tooltipData)}
116+
{tooltipContent}
112117
</TooltipComponent>}
113118

114119
{HoverStyles && <HoverStyles />}

packages/shared/test/enhancer/WithTooltip.test.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,37 @@ describe('<WithTooltip />', () => {
8787
expect(wrapper.find('#test').length).toBe(1);
8888
});
8989

90+
test('it should not render a tooltip if renderTooltip returns a falsy value', () => {
91+
const renderTooltip = jest.fn();
92+
renderTooltip.mockReturnValue(<div id="test" />);
93+
94+
let mouseMove;
95+
const wrapper = mount(
96+
<WithTooltip
97+
TooltipComponent={({ children }) => <div id="tooltip">{children}</div>}
98+
renderTooltip={renderTooltip}
99+
>
100+
{({ onMouseMove }) => {
101+
mouseMove = onMouseMove;
102+
return <svg />;
103+
}}
104+
</WithTooltip>,
105+
);
106+
107+
mouseMove({});
108+
wrapper.update();
109+
expect(renderTooltip).toHaveBeenCalledTimes(1);
110+
expect(wrapper.find('#tooltip').length).toBe(1);
111+
expect(wrapper.find('#test').length).toBe(1);
112+
113+
renderTooltip.mockReturnValue(null);
114+
mouseMove({});
115+
wrapper.update();
116+
expect(renderTooltip).toHaveBeenCalledTimes(2);
117+
expect(wrapper.find('#tooltip').length).toBe(0);
118+
expect(wrapper.find('#test').length).toBe(0);
119+
});
120+
90121
test('it should hide the value of renderTooltip on mouse leave', () => {
91122
jest.useFakeTimers(); // needed for mouseLeave timeout
92123

@@ -126,7 +157,7 @@ describe('<WithTooltip />', () => {
126157
let mouseMove;
127158
const wrapper = mount(
128159
<WithTooltip
129-
renderTooltip={() => null}
160+
renderTooltip={() => 'test'}
130161
TooltipComponent={Tooltip}
131162
>
132163
{({ onMouseMove }) => {

packages/sparkline/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ Name | Type | Default | Description
162162
------------ | ------------- | ------- | ----
163163
children | PropTypes.func or PropTypes.object | - | Child function (to call) or element (to clone) with onMouseMove, onMouseLeave, and tooltipData props/keys
164164
className | PropTypes.string | - | Class name to add to the `<div>` container wrapper
165-
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color }) => node`
165+
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color }) => node`. If this function returns a `falsy` value, a tooltip will not be rendered.
166166
styles | PropTypes.object | {} | Styles to add to the `<div>` container wrapper
167167
TooltipComponent | PropTypes.func or PropTypes.object | `@vx`'s `TooltipWithBounds` | Component (not instance) to use as the tooltip container component. It is passed `top` and `left` numbers for positioning
168168
tooltipTimeout | PropTypes.number | 200 | Timeout in ms for the tooltip to hide upon calling `onMouseLeave`

packages/xy-chart/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ Note that only `x` values are needed for `CirclePackSeries`, `y` values are comp
188188

189189

190190
### Tooltips
191-
Tooltips are supported for all series types, but how you configure them will likely depend on which series combinations you're using and how much customization you need. The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<XYChart />` as shown in the above example. This function takes an object with the shape `{ event, datum, data, color }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above.
191+
Tooltips are supported for all series types, but how you configure them will likely depend on which series combinations you're using and how much customization you need. The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<XYChart />` as shown in the above example. This function takes an object with the shape `{ event, datum, data, color [, seriesKey] }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above. If this function returns a `falsy` value, a tooltip will not be rendered.
192192

193193
Under the covers this will wrap the `<XYChart />` component in the exported `<WithTooltip />` HOC, which wraps the `<svg />` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".
194194

@@ -202,7 +202,7 @@ Name | Type | Default | Description
202202
------------ | ------------- | ------- | ----
203203
children | PropTypes.func or PropTypes.object | - | Child function (to call) or element (to clone) with onMouseMove, onMouseLeave, and tooltipData props/keys
204204
className | PropTypes.string | - | Class name to add to the `<div>` container wrapper
205-
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color }) => node`
205+
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color }) => node`. If this function returns a `falsy` value, a tooltip will not be rendered.
206206
styles | PropTypes.object | {} | Styles to add to the `<div>` container wrapper
207207
TooltipComponent | PropTypes.func or PropTypes.object | `@vx`'s `TooltipWithBounds` | Component (not instance) to use as the tooltip container component. It is passed `top` and `left` numbers for positioning
208208
tooltipTimeout | PropTypes.number | 200 | Timeout in ms for the tooltip to hide upon calling `onMouseLeave`

packages/xy-chart/src/series/GroupedBarSeries.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export default class GroupedBarSeries extends React.PureComponent {
7777
strokeWidth={strokeWidth}
7878
onMouseMove={onMouseMove && (d => (event) => {
7979
const { key, data: datum } = d;
80-
onMouseMove({ event, data, datum, key, color: zScale(key) });
80+
onMouseMove({ event, data, datum, seriesKey: key, color: zScale(key) });
8181
})}
8282
onMouseLeave={onMouseLeave && (() => onMouseLeave)}
8383
/>

packages/xy-chart/src/series/StackedBarSeries.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export default class StackedBarSeries extends React.PureComponent {
6565
strokeWidth={strokeWidth}
6666
onMouseMove={onMouseMove && (d => (event) => {
6767
const { data: datum, key } = d;
68-
onMouseMove({ event, data, datum, key, color: zScale(key) });
68+
onMouseMove({ event, data, datum, seriesKey: key, color: zScale(key) });
6969
})}
7070
onMouseLeave={onMouseLeave && (() => onMouseLeave)}
7171
/>

0 commit comments

Comments
 (0)