Skip to content

Commit

Permalink
feat(tooltip): improve tooltip with global component
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte committed Aug 11, 2017
1 parent 2a5b075 commit 631265d
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 82 deletions.
14 changes: 11 additions & 3 deletions src/components/charts/bar/BarItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import pure from 'recompose/pure'
import BasicTooltip from '../../tooltip/BasicTooltip'

const BarItem = ({
serie,
Expand All @@ -22,9 +23,16 @@ const BarItem = ({
showTooltip,
hideTooltip,
}) => {
const handleTooltip = e => {
showTooltip(`${serie.id} - ${xValue}: ${yValue}`, e)
}
const handleTooltip = e =>
showTooltip(
<BasicTooltip
id={`${serie.id} - ${xValue}`}
value={yValue}
enableChip={true}
color={color}
/>,
e
)

return (
<rect
Expand Down
20 changes: 18 additions & 2 deletions src/components/charts/bubble/Bubble.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
import React, { Component } from 'react'
import _ from 'lodash'
import { getLabelGenerator } from '../../../lib/propertiesConverters'
import { getColorGenerator } from '../../../lib/colorUtils'
import { bubblePropTypes, bubbleDefaultProps } from './BubbleProps'
import BubblePlaceholders from './BubblePlaceholders'
import { getColorGenerator } from '../../../lib/colorUtils'
import BasicTooltip from '../../tooltip/BasicTooltip'

const createNodes = ({
borderWidth,
Expand All @@ -27,16 +28,30 @@ const createNodes = ({
const borderColorFn = getColorGenerator(borderColor)
const textColorFn = getColorGenerator(labelTextColor)

return nodes => {
return (nodes, { showTooltip, hideTooltip }) => {
const renderedNodes = []

nodes.filter(node => node.style.r > 0).forEach(node => {
const handleTooltip = e =>
showTooltip(
<BasicTooltip
id={node.data.data.name}
value={node.data.value}
enableChip={true}
color={node.style.color}
/>,
e
)

renderedNodes.push(
<circle
key={`${node.key}.circle`}
r={node.style.r}
className="nivo_bubble_node"
transform={`translate(${node.style.x},${node.style.y})`}
onMouseEnter={handleTooltip}
onMouseMove={handleTooltip}
onMouseLeave={hideTooltip}
style={{
fill: node.style.color,
stroke: borderColorFn(node.style),
Expand Down Expand Up @@ -64,6 +79,7 @@ const createNodes = ({
dy={labelTextDY}
style={{
fill: textColorFn(node.style),
pointerEvents: 'none',
}}
>
{label(node.data.data)}
Expand Down
85 changes: 48 additions & 37 deletions src/components/charts/bubble/BubblePlaceholders.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
*/
import React, { Component } from 'react'
import { TransitionMotion, spring } from 'react-motion'
import { rgb } from 'd3-color'
import _ from 'lodash'
import Nivo from '../../../Nivo'
import { getColorsGenerator, extractRGB } from '../../../lib/colorUtils'
import Container from '../Container'
import BubbleHelper from '../../../lib/charts/bubble/BubbleHelper'
import { convertGetter } from '../../../lib/propertiesConverters'
import { bubblePropTypes, bubbleDefaultProps } from './BubbleProps'
Expand Down Expand Up @@ -71,6 +71,7 @@ export default class BubblePlaceholders extends Component {
motionStiffness,
motionDamping,
children,
isInteractive,
} = this.props

const identity = convertGetter(_identity)
Expand Down Expand Up @@ -146,42 +147,52 @@ export default class BubblePlaceholders extends Component {
damping: motionDamping,
}

return React.createElement(
wrapperTag,
wrapperProps,
<TransitionMotion
willEnter={this.willEnter}
willLeave={this.willLeave}
styles={nodes.map(b => {
return {
key: b.data.key,
data: b,
style: {
r: spring(b.r, motionProps),
x: spring(b.x, motionProps),
y: spring(b.y, motionProps),
...extractRGB(b.color, motionProps),
},
}
})}
>
{interpolatedStyles => {
return React.createElement(
containerTag,
containerProps,
children(
interpolatedStyles.map(interpolatedStyle => {
const { colorR, colorG, colorB } = interpolatedStyle.style
interpolatedStyle.style.color = `rgb(${Math.round(
colorR
)},${Math.round(colorG)},${Math.round(colorB)})`

return interpolatedStyle
})
)
)
}}
</TransitionMotion>
return (
<Container isInteractive={isInteractive}>
{({ showTooltip, hideTooltip }) =>
React.createElement(
wrapperTag,
wrapperProps,
<TransitionMotion
willEnter={this.willEnter}
willLeave={this.willLeave}
styles={nodes.map(b => {
return {
key: b.data.key,
data: b,
style: {
r: spring(b.r, motionProps),
x: spring(b.x, motionProps),
y: spring(b.y, motionProps),
...extractRGB(b.color, motionProps),
},
}
})}
>
{interpolatedStyles => {
return React.createElement(
containerTag,
containerProps,
children(
interpolatedStyles.map(interpolatedStyle => {
const {
colorR,
colorG,
colorB,
} = interpolatedStyle.style
interpolatedStyle.style.color = `rgb(${Math.round(
colorR
)},${Math.round(colorG)},${Math.round(colorB)})`

return interpolatedStyle
}),
{ showTooltip, hideTooltip }
)
)
}}
</TransitionMotion>
)}
</Container>
)
}
}
14 changes: 11 additions & 3 deletions src/components/charts/pie/Pie.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import SvgWrapper from '../SvgWrapper'
import { pie as d3Pie, arc as d3Arc } from 'd3-shape'
import PieRadialLabels from './PieRadialLabels'
import PieSlicesLabels from './PieSlicesLabels'
import BasicTooltip from '../../tooltip/BasicTooltip'

export default class Pie extends Component {
static propTypes = {
Expand Down Expand Up @@ -237,9 +238,16 @@ export default class Pie extends Component {
transform={`translate(${interpolatingStyle.centerX}, ${interpolatingStyle.centerY})`}
>
{arcsData.map(d => {
const handleTooltip = e => {
showTooltip(`${d.data.label}: ${d.data.value}`, e)
}
const handleTooltip = e =>
showTooltip(
<BasicTooltip
id={d.data.label}
value={d.data.value}
enableChip={true}
color={d.data.color}
/>,
e
)

return (
<path
Expand Down
75 changes: 38 additions & 37 deletions src/components/charts/stream/StreamLayers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import { motionPropTypes } from '../../../props'
import SmartMotion from '../../SmartMotion'
import BasicTooltip from '../../tooltip/BasicTooltip'

const StreamLayers = ({
layers,
Expand All @@ -26,21 +27,21 @@ const StreamLayers = ({
if (animate !== true) {
return (
<g>
{layers.map(({ id, path, color }, i) =>
<path
key={i}
onMouseMove={e => {
showTooltip(id, e)
}}
onMouseEnter={e => {
showTooltip(id, e)
}}
onMouseLeave={hideTooltip}
d={path}
fill={color}
fillOpacity={fillOpacity}
/>
)}
{layers.map(({ id, path, color }, i) => {
const handleTooltip = e =>
showTooltip(<BasicTooltip id={id} enableChip={true} color={color} />, e)
return (
<path
key={i}
onMouseMove={handleTooltip}
onMouseEnter={handleTooltip}
onMouseLeave={hideTooltip}
d={path}
fill={color}
fillOpacity={fillOpacity}
/>
)
})}
</g>
)
}
Expand All @@ -52,28 +53,28 @@ const StreamLayers = ({

return (
<g>
{layers.map(({ id, path, color }, i) =>
<SmartMotion
key={i}
style={spring => ({
d: spring(path, springConfig),
fill: spring(color, springConfig),
fillOpacity: spring(fillOpacity, springConfig),
})}
>
{style =>
<path
onMouseMove={e => {
showTooltip(id, e)
}}
onMouseEnter={e => {
showTooltip(id, e)
}}
onMouseLeave={hideTooltip}
{...style}
/>}
</SmartMotion>
)}
{layers.map(({ id, path, color }, i) => {
const handleTooltip = e =>
showTooltip(<BasicTooltip id={id} enableChip={true} color={color} />, e)
return (
<SmartMotion
key={i}
style={spring => ({
d: spring(path, springConfig),
fill: spring(color, springConfig),
fillOpacity: spring(fillOpacity, springConfig),
})}
>
{style =>
<path
onMouseMove={handleTooltip}
onMouseEnter={handleTooltip}
onMouseLeave={hideTooltip}
{...style}
/>}
</SmartMotion>
)
})}
</g>
)
}
Expand Down
45 changes: 45 additions & 0 deletions src/components/tooltip/BasicTooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react'
import PropTypes from 'prop-types'
import pure from 'recompose/pure'

const tooltipStyle = {
display: 'flex',
alignItems: 'center',
}

const chipStyle = {
display: 'block',
width: '16px',
height: '16px',
marginRight: '9px',
borderRadius: '2px',
}

const textStyle = {
whiteSpace: 'pre',
}

const BasicTooltip = ({ id, value, enableChip, color }) =>
<div style={tooltipStyle}>
{enableChip && <span style={{ ...chipStyle, background: color }} />}
{value !== undefined
? <span style={textStyle}>
{id}: <strong>{value}</strong>
</span>
: <span style={textStyle}>
{id}
</span>}
</div>

BasicTooltip.propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
enableChip: PropTypes.bool.isRequired,
color: PropTypes.string,
}

BasicTooltip.defaultProps = {
enableChip: false,
}

export default pure(BasicTooltip)

0 comments on commit 631265d

Please sign in to comment.