Skip to content

Commit

Permalink
feat(line): add support for custom tooltip
Browse files Browse the repository at this point in the history
  • Loading branch information
jbenua authored and Raphaël Benitte committed Aug 24, 2018
1 parent 5ac4214 commit 39fad12
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 41 deletions.
45 changes: 26 additions & 19 deletions packages/nivo-core/src/components/tooltip/TableTooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,33 @@ const tableStyle = {
borderCollapse: 'collapse',
}

const TableTooltip = ({ title, rows, theme }) => {
const TableTooltip = ({ title, rows, theme, renderContent }) => {
if (!rows.length) return null

return (
<div style={theme.tooltip.container}>
{title && title}
<table style={{ ...tableStyle, ...theme.tooltip.table }}>
<tbody>
{rows.map((row, i) => (
<tr key={i}>
{row.map((column, j) => (
<td key={j} style={theme.tooltip.tableCell}>
{column}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
let content
if (typeof renderContent === 'function') {
content = renderContent()
} else {
content = (
<div>
{title && title}
<table style={{ ...tableStyle, ...theme.tooltip.table }}>
<tbody>
{rows.map((row, i) => (
<tr key={i}>
{row.map((column, j) => (
<td key={j} style={theme.tooltip.tableCell}>
{column}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
}
return <div style={theme.tooltip.container}>{content}</div>
}

TableTooltip.propTypes = {
Expand All @@ -48,6 +54,7 @@ TableTooltip.propTypes = {
tableCell: PropTypes.object.isRequired,
}).isRequired,
}).isRequired,
renderContent: PropTypes.func,
}

TableTooltip.defaultProps = {}
Expand Down
2 changes: 2 additions & 0 deletions packages/nivo-line/src/Line.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const Line = ({
// interactivity
isInteractive,
tooltipFormat,
tooltip,

// stackTooltip
enableStackTooltip,
Expand Down Expand Up @@ -147,6 +148,7 @@ const Line = ({
hideTooltip={hideTooltip}
theme={theme}
tooltipFormat={tooltipFormat}
tooltip={tooltip}
/>
)}
{enableDots && (
Expand Down
13 changes: 12 additions & 1 deletion packages/nivo-line/src/LineSlices.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ import PropTypes from 'prop-types'
import pure from 'recompose/pure'
import LineSlicesItem from './LineSlicesItem'

const LineSlices = ({ slices, height, showTooltip, hideTooltip, theme, tooltipFormat }) => (
const LineSlices = ({
slices,
height,
showTooltip,
hideTooltip,
theme,
tooltip,
tooltipFormat,
}) => (
<g>
{slices.map(slice => (
<LineSlicesItem
Expand All @@ -22,6 +30,7 @@ const LineSlices = ({ slices, height, showTooltip, hideTooltip, theme, tooltipFo
hideTooltip={hideTooltip}
theme={theme}
tooltipFormat={tooltipFormat}
tooltip={tooltip}
/>
))}
</g>
Expand All @@ -45,6 +54,8 @@ LineSlices.propTypes = {
showTooltip: PropTypes.func.isRequired,
hideTooltip: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
tooltip: PropTypes.element,
tooltipFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
}

export default pure(LineSlices)
52 changes: 31 additions & 21 deletions packages/nivo-line/src/LineSlicesItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Chip = ({ color }) => (
<span style={{ display: 'block', width: '12px', height: '12px', background: color }} />
)

const LineSlicesItem = ({ slice, height, showTooltip, hideTooltip, isHover }) => (
const LineSlicesItem = ({ slice, height, showTooltip, hideTooltip, isHover, tooltip }) => (
<g transform={`translate(${slice.x}, 0)`}>
{isHover && (
<line
Expand Down Expand Up @@ -54,34 +54,44 @@ LineSlicesItem.propTypes = {
hideTooltip: PropTypes.func.isRequired,
isHover: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
tooltip: PropTypes.element,
}

const enhance = compose(
withState('isHover', 'setIsHover', false),
withPropsOnChange(['slice', 'theme', 'tooltipFormat'], ({ slice, theme, tooltipFormat }) => {
const format =
!tooltipFormat || isFunction(tooltipFormat) ? tooltipFormat : d3Format(tooltipFormat)
const hasValues = slice.points.some(p => p.value !== null)
withPropsOnChange(
['slice', 'theme', 'tooltip', 'tooltipFormat'],
({ slice, theme, tooltip, tooltipFormat }) => {
const format =
!tooltipFormat || isFunction(tooltipFormat)
? tooltipFormat
: d3Format(tooltipFormat)
const hasValues = slice.points.some(p => p.value !== null)

return {
tooltip: hasValues ? (
<TableTooltip
theme={theme}
rows={slice.points
.filter(p => p.value !== null)
.map(p => [
<Chip color={p.color} />,
p.id,
format ? format(p.value) : p.value,
])}
/>
) : null,
return {
tooltipElement: hasValues ? (
<TableTooltip
theme={theme}
rows={slice.points
.filter(p => p.value !== null)
.map(p => [
<Chip color={p.color} />,
p.id,
format ? format(p.value) : p.value,
])}
format={format}
renderContent={
typeof tooltip === 'function' ? tooltip.bind(null, { ...slice }) : null
}
/>
) : null,
}
}
}),
),
withHandlers({
showTooltip: ({ showTooltip, setIsHover, tooltip }) => e => {
showTooltip: ({ showTooltip, setIsHover, tooltipElement }) => e => {
setIsHover(true)
showTooltip(tooltip, e)
showTooltip(tooltipElement, e)
},
hideTooltip: ({ hideTooltip, setIsHover }) => () => {
setIsHover(false)
Expand Down
1 change: 1 addition & 0 deletions packages/nivo-line/src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const LinePropTypes = {
// interactivity
isInteractive: PropTypes.bool.isRequired,
enableStackTooltip: PropTypes.bool.isRequired,
tooltip: PropTypes.func,
tooltipFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),

legends: PropTypes.arrayOf(PropTypes.shape(LegendPropShape)).isRequired,
Expand Down
27 changes: 27 additions & 0 deletions packages/nivo-line/stories/line.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,30 @@ stories.add('with formatted values', () => (
}
/>
))

stories.add('with custom tooltip', () => (
<Line
{...commonProperties}
enableStackTooltip={true}
curve={select('curve', curveOptions, 'linear')}
tooltip={slice => {
return (
<div>
<h2>{slice.id}</h2>
{slice.points.map((e, i) => (
<p key={i}>
<strong>{e.id}:</strong> {e.value}
</p>
))}
</div>
)
}}
theme={{
tooltip: {
container: {
border: '1px solid red',
},
},
}}
/>
))
8 changes: 8 additions & 0 deletions website/src/components/charts/line/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,5 +378,13 @@ export default [
controlType: 'switch',
controlGroup: 'Interactivity',
},
{
key: 'tooltip',
scopes: ['Line'],
description: `Method to create custom tooltip`,
type: '{Function}',
required: false,
default: defaults.tooltip,
},
...motionProperties(['Line'], defaults),
]

0 comments on commit 39fad12

Please sign in to comment.