Skip to content

Commit

Permalink
feat(tooltip): add support for tooltip theming
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte committed Aug 17, 2017
1 parent 5684abe commit 72f2f75
Show file tree
Hide file tree
Showing 15 changed files with 62 additions and 34 deletions.
14 changes: 14 additions & 0 deletions src/Nivo.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ export const defaultTheme = {
textColor: '#000',
fontSize: '11px',
},
tooltip: {
background: 'white',
color: 'inherit',
fontSize: 'inherit',
borderRadius: '2px',
boxShadow: '0 1px 2px rgba(0, 0, 0, 0.25)',
padding: '5px 9px',
table: {
fontSize: 'inherit',
},
tableCell: {
padding: '3px 5px',
},
},
}

export default {
Expand Down
14 changes: 5 additions & 9 deletions src/components/charts/Container.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@ const containerStyle = {

const tooltipStyle = {
position: 'absolute',
background: '#FFF',
zIndex: 10,
top: 0,
left: 0,
borderRadius: '2px',
boxShadow: '0 1px 2px rgba(0, 0, 0, 0.25)',
padding: '5px 9px',
fontSize: '14px',
}

const Tooltip = ({ x, y, children }) =>
<div style={{ ...tooltipStyle, top: y, left: x }}>
const Tooltip = ({ x, y, children, theme }) =>
<div style={{ ...tooltipStyle, top: y, left: x, ...theme.tooltip }}>
{children}
</div>

Expand All @@ -39,6 +34,7 @@ export default class Container extends Component {
static propTypes = {
children: PropTypes.func.isRequired,
isInteractive: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
}

static defaultProps = {
Expand Down Expand Up @@ -69,7 +65,7 @@ export default class Container extends Component {
}

render() {
const { children, isInteractive } = this.props
const { children, isInteractive, theme } = this.props
const { isTooltipVisible, tooltipContent, tooltipX, tooltipY } = this.state

if (!isInteractive) return children(noop)
Expand All @@ -86,7 +82,7 @@ export default class Container extends Component {
hideTooltip: this.hideTooltip,
})}
{isTooltipVisible &&
<Tooltip x={tooltipX} y={tooltipY}>
<Tooltip x={tooltipX} y={tooltipY} theme={theme}>
{tooltipContent}
</Tooltip>}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/charts/bar/Bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const Bar = ({
}

return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) => {
let bars
if (animate === true) {
Expand Down
9 changes: 6 additions & 3 deletions src/components/charts/bubble/BubblePlaceholders.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
* file that was distributed with this source code.
*/
import React, { Component } from 'react'
import { merge } from 'lodash'
import { TransitionMotion, spring } from 'react-motion'
import _ from 'lodash'
import Nivo from '../../../Nivo'
import Nivo, { defaultTheme } from '../../../Nivo'
import { getColorsGenerator, extractRGB } from '../../../lib/colorUtils'
import Container from '../Container'
import BubbleHelper from '../../../lib/charts/bubble/BubbleHelper'
Expand Down Expand Up @@ -65,6 +66,7 @@ export default class BubblePlaceholders extends Component {
identity: _identity,
value: _value,
padding,
theme: _theme,
colors,
colorBy,
animate,
Expand All @@ -77,6 +79,7 @@ export default class BubblePlaceholders extends Component {
const identity = convertGetter(_identity)
const value = convertGetter(_value)
const color = getColorsGenerator(colors, colorBy)
const theme = merge({}, defaultTheme, _theme)

const margin = Object.assign({}, Nivo.defaults.margin, this.props.margin)
const width = _width - margin.left - margin.right
Expand Down Expand Up @@ -124,7 +127,7 @@ export default class BubblePlaceholders extends Component {

if (!animate) {
return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) =>
React.createElement(
wrapperTag,
Expand Down Expand Up @@ -154,7 +157,7 @@ export default class BubblePlaceholders extends Component {
}

return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) =>
React.createElement(
wrapperTag,
Expand Down
1 change: 1 addition & 0 deletions src/components/charts/bubble/BubbleProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const bubbleDefaultProps = {
padding: 1,

// theming
theme: {},
colors: 'nivo',
colorBy: 'depth',

Expand Down
7 changes: 4 additions & 3 deletions src/components/charts/chord/Chord.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import pure from 'recompose/pure'
import { chord as d3Chord, ribbon as Ribbon } from 'd3-chord'
import { arc as Arc } from 'd3-shape'
import { rgb } from 'd3-color'
import { withDimensions } from '../../../hocs'
import { withTheme, withDimensions } from '../../../hocs'
import { getColorRange } from '../../../lib/colorUtils'
import Container from '../Container'
import SvgWrapper from '../SvgWrapper'
Expand All @@ -38,6 +38,7 @@ const Chord = ({
arcBorderWidth,

// theming
theme,
colors,

// interactivity
Expand All @@ -62,7 +63,7 @@ const Chord = ({
const arcs = ribbons.groups

return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) => {
return (
<SvgWrapper width={outerWidth} height={outerHeight} margin={margin}>
Expand Down Expand Up @@ -144,6 +145,6 @@ export const ChordDefaultProps = {
isInteractive: true,
}

const enhance = compose(defaultProps(ChordDefaultProps), withDimensions(), pure)
const enhance = compose(defaultProps(ChordDefaultProps), withTheme(), withDimensions(), pure)

export default enhance(Chord)
3 changes: 2 additions & 1 deletion src/components/charts/line/Line.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const Line = ({
}

return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) =>
<SvgWrapper width={outerWidth} height={outerHeight} margin={margin}>
<Grid
Expand Down Expand Up @@ -116,6 +116,7 @@ const Line = ({
height={height}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
/>}
{enableMarkers &&
<LineMarkers
Expand Down
4 changes: 3 additions & 1 deletion src/components/charts/line/LineSlices.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PropTypes from 'prop-types'
import pure from 'recompose/pure'
import LineSlicesItem from './LineSlicesItem'

const LineSlices = ({ slices, height, showTooltip, hideTooltip }) =>
const LineSlices = ({ slices, height, showTooltip, hideTooltip, theme }) =>
<g>
{slices.map(slice =>
<LineSlicesItem
Expand All @@ -20,6 +20,7 @@ const LineSlices = ({ slices, height, showTooltip, hideTooltip }) =>
height={height}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
/>
)}
</g>
Expand All @@ -41,6 +42,7 @@ LineSlices.propTypes = {
height: PropTypes.number.isRequired,
showTooltip: PropTypes.func.isRequired,
hideTooltip: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
}

export default pure(LineSlices)
8 changes: 6 additions & 2 deletions src/components/charts/line/LineSlicesItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ LineSlicesItem.propTypes = {
showTooltip: PropTypes.func.isRequired,
hideTooltip: PropTypes.func.isRequired,
isHover: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
}

const enhance = compose(
withState('isHover', 'setIsHover', false),
withPropsOnChange(['slice'], ({ slice }) => ({
withPropsOnChange(['slice', 'theme'], ({ slice, theme }) => ({
tooltip: (
<TableTooltip rows={slice.points.map(p => [<Chip color={p.color} />, p.id, p.value])} />
<TableTooltip
theme={theme}
rows={slice.points.map(p => [<Chip color={p.color} />, p.id, p.value])}
/>
),
})),
withHandlers({
Expand Down
2 changes: 1 addition & 1 deletion src/components/charts/pie/Pie.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const Pie = ({
arc.outerRadius(radius)

return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) =>
<SvgWrapper width={outerWidth} height={outerHeight} margin={margin}>
<Motion
Expand Down
3 changes: 2 additions & 1 deletion src/components/charts/stream/Stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const Stream = ({
}

return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) =>
<SvgWrapper width={outerWidth} height={outerHeight} margin={margin}>
<Grid
Expand Down Expand Up @@ -147,6 +147,7 @@ const Stream = ({
height={height}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
/>}
</SvgWrapper>}
</Container>
Expand Down
4 changes: 3 additions & 1 deletion src/components/charts/stream/StreamSlices.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PropTypes from 'prop-types'
import pure from 'recompose/pure'
import StreamSlicesItem from './StreamSlicesItem'

const StreamSlices = ({ slices, height, showTooltip, hideTooltip }) =>
const StreamSlices = ({ slices, height, showTooltip, hideTooltip, theme }) =>
<g>
{slices.map(slice =>
<StreamSlicesItem
Expand All @@ -20,6 +20,7 @@ const StreamSlices = ({ slices, height, showTooltip, hideTooltip }) =>
height={height}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
/>
)}
</g>
Expand All @@ -41,6 +42,7 @@ StreamSlices.propTypes = {
height: PropTypes.number.isRequired,
showTooltip: PropTypes.func.isRequired,
hideTooltip: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
}

export default pure(StreamSlices)
8 changes: 6 additions & 2 deletions src/components/charts/stream/StreamSlicesItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ StreamSlicesItem.propTypes = {
showTooltip: PropTypes.func.isRequired,
hideTooltip: PropTypes.func.isRequired,
isHover: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
}

const enhance = compose(
withState('isHover', 'setIsHover', false),
withPropsOnChange(['slice'], ({ slice }) => ({
withPropsOnChange(['slice', 'theme'], ({ slice, theme }) => ({
tooltip: (
<TableTooltip rows={slice.stack.map(p => [<Chip color={p.color} />, p.id, p.value])} />
<TableTooltip
theme={theme}
rows={slice.stack.map(p => [<Chip color={p.color} />, p.id, p.value])}
/>
),
})),
withHandlers({
Expand Down
5 changes: 4 additions & 1 deletion src/components/charts/sunburst/Sunburst.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ const Sunburst = ({
borderWidth,
borderColor,

// theming
theme,

// interactivity
isInteractive,
}) => {
return (
<Container isInteractive={isInteractive}>
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) =>
<SvgWrapper width={outerWidth} height={outerHeight} margin={margin}>
<g transform={`translate(${centerX}, ${centerY})`}>
Expand Down
12 changes: 4 additions & 8 deletions src/components/tooltip/TableTooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,20 @@ import PropTypes from 'prop-types'
import pure from 'recompose/pure'

const tableStyle = {
fontSize: '14px',
width: '100%',
borderCollapse: 'collapse',
}

const cellStyle = {
padding: '3px 5px',
}

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

return (
<table style={tableStyle}>
<table style={{ ...tableStyle, ...theme.tooltip.table }}>
<tbody>
{rows.map((row, i) =>
<tr key={i}>
{row.map((column, j) =>
<td key={j} style={cellStyle}>
<td key={j} style={theme.tooltip.tableCell}>
{column}
</td>
)}
Expand All @@ -42,6 +37,7 @@ const TableTooltip = ({ rows }) => {

TableTooltip.propTypes = {
rows: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.node)).isRequired,
theme: PropTypes.object.isRequired,
}

TableTooltip.defaultProps = {}
Expand Down

0 comments on commit 72f2f75

Please sign in to comment.