Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add useTooltip hook #631

Merged
merged 5 commits into from
Feb 24, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 123 additions & 123 deletions packages/vx-demo/src/components/tiles/BarStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { AxisBottom } from '@vx/axis';
import cityTemperature, { CityTemperature } from '@vx/mock-data/lib/mocks/cityTemperature';
import { scaleBand, scaleLinear, scaleOrdinal } from '@vx/scale';
import { timeParse, timeFormat } from 'd3-time-format';
import { withTooltip, Tooltip } from '@vx/tooltip';
import { WithTooltipProvidedProps } from '@vx/tooltip/lib/enhancers/withTooltip';
import { useTooltip, Tooltip } from '@vx/tooltip';
import { LegendOrdinal } from '@vx/legend';
import { ShowProvidedProps } from '../../types';

Expand Down Expand Up @@ -64,137 +63,138 @@ const colorScale = scaleOrdinal<CityName, string>({

let tooltipTimeout: number;

export default withTooltip<ShowProvidedProps, TooltipData>(
({
width,
height,
events = false,
margin = {
top: 40,
right: 0,
bottom: 0,
left: 0,
},
export default ({
width,
height,
events = false,
margin = {
top: 40,
right: 0,
bottom: 0,
left: 0,
},
}: ShowProvidedProps) => {
const {
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
}: ShowProvidedProps & WithTooltipProvidedProps<TooltipData>) => {
if (width < 10) return null;
// bounds
const xMax = width;
const yMax = height - margin.top - 100;
} = useTooltip<TooltipData>();

if (width < 10) return null;
// bounds
const xMax = width;
const yMax = height - margin.top - 100;

dateScale.rangeRound([0, xMax]);
temperatureScale.range([yMax, 0]);
dateScale.rangeRound([0, xMax]);
temperatureScale.range([yMax, 0]);

return (
<div style={{ position: 'relative' }}>
<svg width={width} height={height}>
<rect x={0} y={0} width={width} height={height} fill={bg} rx={14} />
<Grid<string, number>
top={margin.top}
left={margin.left}
return (
<div style={{ position: 'relative' }}>
<svg width={width} height={height}>
<rect x={0} y={0} width={width} height={height} fill={bg} rx={14} />
<Grid<string, number>
top={margin.top}
left={margin.left}
xScale={dateScale}
yScale={temperatureScale}
width={xMax}
height={yMax}
stroke="black"
strokeOpacity={0.1}
xOffset={dateScale.bandwidth() / 2}
/>
<Group top={margin.top}>
<BarStack<CityTemperature, CityName>
data={data}
keys={keys}
x={getDate}
xScale={dateScale}
yScale={temperatureScale}
width={xMax}
height={yMax}
stroke="black"
strokeOpacity={0.1}
xOffset={dateScale.bandwidth() / 2}
/>
<Group top={margin.top}>
<BarStack<CityTemperature, CityName>
data={data}
keys={keys}
x={getDate}
xScale={dateScale}
yScale={temperatureScale}
color={colorScale}
>
{barStacks =>
barStacks.map(barStack =>
barStack.bars.map(bar => (
<rect
key={`bar-stack-${barStack.index}-${bar.index}`}
x={bar.x}
y={bar.y}
height={bar.height}
width={bar.width}
fill={bar.color}
onClick={() => {
if (events) alert(`clicked: ${JSON.stringify(bar)}`);
}}
onMouseLeave={() => {
tooltipTimeout = window.setTimeout(() => {
hideTooltip();
}, 300);
}}
onMouseMove={event => {
if (tooltipTimeout) clearTimeout(tooltipTimeout);
const top = event.clientY - margin.top - bar.height;
const offset = (dateScale.paddingInner() * dateScale.step()) / 2;
const left = bar.x + bar.width + offset;
showTooltip({
tooltipData: bar,
tooltipTop: top,
tooltipLeft: left,
});
}}
/>
)),
)
}
</BarStack>
</Group>
<AxisBottom<string>
top={yMax + margin.top}
scale={dateScale}
tickFormat={formatDate}
stroke={purple3}
tickStroke={purple3}
tickLabelProps={() => ({
fill: purple3,
fontSize: 11,
textAnchor: 'middle',
})}
/>
</svg>
<div
color={colorScale}
>
{barStacks =>
barStacks.map(barStack =>
barStack.bars.map(bar => (
<rect
key={`bar-stack-${barStack.index}-${bar.index}`}
x={bar.x}
y={bar.y}
height={bar.height}
width={bar.width}
fill={bar.color}
onClick={() => {
if (events) alert(`clicked: ${JSON.stringify(bar)}`);
}}
onMouseLeave={() => {
tooltipTimeout = window.setTimeout(() => {
hideTooltip();
}, 300);
}}
onMouseMove={event => {
if (tooltipTimeout) clearTimeout(tooltipTimeout);
const top = event.clientY - margin.top - bar.height;
const offset = (dateScale.paddingInner() * dateScale.step()) / 2;
const left = bar.x + bar.width + offset;
showTooltip({
tooltipData: bar,
tooltipTop: top,
tooltipLeft: left,
});
}}
/>
)),
)
}
</BarStack>
</Group>
<AxisBottom<string>
top={yMax + margin.top}
scale={dateScale}
tickFormat={formatDate}
stroke={purple3}
tickStroke={purple3}
tickLabelProps={() => ({
fill: purple3,
fontSize: 11,
textAnchor: 'middle',
})}
/>
</svg>
<div
style={{
position: 'absolute',
top: margin.top / 2 - 10,
width: '100%',
display: 'flex',
justifyContent: 'center',
fontSize: '14px',
}}
>
<LegendOrdinal scale={colorScale} direction="row" labelMargin="0 15px 0 0" />
</div>

{tooltipOpen && tooltipData && (
<Tooltip
top={tooltipTop}
left={tooltipLeft}
style={{
position: 'absolute',
top: margin.top / 2 - 10,
width: '100%',
display: 'flex',
justifyContent: 'center',
fontSize: '14px',
minWidth: 60,
backgroundColor: 'rgba(0,0,0,0.9)',
color: 'white',
}}
>
<LegendOrdinal scale={colorScale} direction="row" labelMargin="0 15px 0 0" />
</div>

{tooltipOpen && tooltipData && (
<Tooltip
top={tooltipTop}
left={tooltipLeft}
style={{
minWidth: 60,
backgroundColor: 'rgba(0,0,0,0.9)',
color: 'white',
}}
>
<div style={{ color: colorScale(tooltipData.key) }}>
<strong>{tooltipData.key}</strong>
</div>
<div>{tooltipData.bar.data[tooltipData.key]}℉</div>
<div>
<small>{formatDate(getDate(tooltipData.bar.data))}</small>
</div>
</Tooltip>
)}
</div>
);
},
);
<div style={{ color: colorScale(tooltipData.key) }}>
<strong>{tooltipData.key}</strong>
</div>
<div>{tooltipData.bar.data[tooltipData.key]}℉</div>
<div>
<small>{formatDate(getDate(tooltipData.bar.data))}</small>
</div>
</Tooltip>
)}
</div>
);
};
25 changes: 13 additions & 12 deletions packages/vx-demo/src/pages/BarStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import { AxisBottom } from '@vx/axis';
import cityTemperature, { CityTemperature } from '@vx/mock-data/lib/mocks/cityTemperature';
import { scaleBand, scaleLinear, scaleOrdinal } from '@vx/scale';
import { timeParse, timeFormat } from 'd3-time-format';
import { withTooltip, Tooltip } from '@vx/tooltip';
import { WithTooltipProvidedProps } from '@vx/tooltip/lib/enhancers/withTooltip';
import { useTooltip, Tooltip } from '@vx/tooltip';
import { LegendOrdinal } from '@vx/legend';
import { ShowProvidedProps } from '../../types';
Expand Down Expand Up @@ -76,7 +75,7 @@ const colorScale = scaleOrdinal<CityName, string>({
let tooltipTimeout: number;
export default withTooltip<ShowProvidedProps, TooltipData>(
export default
({
width,
height,
Expand All @@ -87,13 +86,16 @@ export default withTooltip<ShowProvidedProps, TooltipData>(
bottom: 0,
left: 0,
},
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
}: ShowProvidedProps & WithTooltipProvidedProps<TooltipData>) => {
}: ShowProvidedProps) => {
const {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for updating the source file, too. working on an improvement to not need to duplicate source + this string (I've tried a few things but if you have any thoughts lmk 😄 )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stuck out to me as something to come back to as well. It might be doable with raw-loader or raw.macro but I didn't have time to dig into it more deeply. Now this has me curious so I'll look into it later in the week if I have a chance 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good! Created #632 to track this, I'll update status there if I start work on it. raw.macro looks interesting, linked to how react-window does it in the issue as well 👍

tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip
} = useTooltip<TooltipData>();
if (width < 10) return null;
// bounds
const xMax = width;
Expand Down Expand Up @@ -208,8 +210,7 @@ export default withTooltip<ShowProvidedProps, TooltipData>(
)}
</div>
);
},
);
}
`}
</Show>
);
Expand Down
Loading