From 95dd0603f29b7b0109dce7c03e2af27dc0f7779b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Benitte?= Date: Thu, 24 Jan 2019 12:20:34 +0900 Subject: [PATCH] feat(theming): improve theming --- packages/axes/src/canvas.js | 3 +- .../bar/tests/__snapshots__/Bar.test.js.snap | 396 ++++++---- packages/circle-packing/src/BubbleCanvas.js | 3 +- .../cartesian/markers/CartesianMarkers.js | 7 +- packages/core/src/hocs/withTheme.js | 5 +- packages/core/src/theming/defaultTheme.js | 41 +- packages/core/src/theming/extend.js | 38 + packages/core/src/theming/index.js | 1 + packages/core/src/theming/propTypes.js | 39 +- packages/heatmap/src/canvas.js | 4 +- .../tests/__snapshots__/HeatMap.test.js.snap | 27 +- .../__snapshots__/LegendSvgItem.test.js.snap | 8 - .../tests/__snapshots__/Line.test.js.snap | 680 ++++++++++++------ packages/pie/src/canvas.js | 4 +- .../__snapshots__/ScatterPlot.test.js.snap | 375 ++++++---- packages/treemap/src/TreeMapCanvas.js | 3 +- website/src/nivoTheme.js | 19 +- 17 files changed, 1024 insertions(+), 629 deletions(-) create mode 100644 packages/core/src/theming/extend.js diff --git a/packages/axes/src/canvas.js b/packages/axes/src/canvas.js index 4445a040e..284464549 100644 --- a/packages/axes/src/canvas.js +++ b/packages/axes/src/canvas.js @@ -49,8 +49,7 @@ export const renderAxisToCanvas = ( ctx.textAlign = textAlign ctx.textBaseline = textBaseline - ctx.font = `${theme.axis.ticks.text.fontSize}px ${theme.axis.ticks.text.fontFamily || - 'sans-serif'}` + ctx.font = `${theme.axis.ticks.text.fontSize}px ${theme.axis.ticks.text.fontFamily}` ctx.lineWidth = theme.axis.domain.line.strokeWidth ctx.lineCap = 'square' diff --git a/packages/bar/tests/__snapshots__/Bar.test.js.snap b/packages/bar/tests/__snapshots__/Bar.test.js.snap index b27b88217..9b2c1c27a 100644 --- a/packages/bar/tests/__snapshots__/Bar.test.js.snap +++ b/packages/bar/tests/__snapshots__/Bar.test.js.snap @@ -26,7 +26,7 @@ exports[`should allow grouped horizontal layout 1`] = ` r > labelSkipRadius).forEach(node => { diff --git a/packages/core/src/components/cartesian/markers/CartesianMarkers.js b/packages/core/src/components/cartesian/markers/CartesianMarkers.js index 73bffa5b0..c262ab0df 100644 --- a/packages/core/src/components/cartesian/markers/CartesianMarkers.js +++ b/packages/core/src/components/cartesian/markers/CartesianMarkers.js @@ -41,8 +41,11 @@ CartesianMarkers.propTypes = { markers: PropTypes.shape({ lineColor: PropTypes.string.isRequired, lineStrokeWidth: PropTypes.number.isRequired, - textColor: PropTypes.string.isRequired, - fontSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + text: PropTypes.shape({ + fill: PropTypes.string.isRequired, + fontFamily: PropTypes.string.isRequired, + fontSize: PropTypes.number.isRequired, + }).isRequired, }).isRequired, }).isRequired, diff --git a/packages/core/src/hocs/withTheme.js b/packages/core/src/hocs/withTheme.js index 3045e5e83..111ee5d15 100644 --- a/packages/core/src/hocs/withTheme.js +++ b/packages/core/src/hocs/withTheme.js @@ -10,8 +10,7 @@ import PropTypes from 'prop-types' import compose from 'recompose/compose' import setPropTypes from 'recompose/setPropTypes' import withPropsOnChange from 'recompose/withPropsOnChange' -import merge from 'lodash/merge' -import { defaultTheme } from '../theming' +import { defaultTheme, extendDefaultTheme } from '../theming' /** * This HOC watch theme prop change @@ -25,6 +24,6 @@ export default ({ srcKey = 'theme', destKey = 'theme' } = {}) => [srcKey]: PropTypes.object, }), withPropsOnChange([srcKey], props => ({ - [destKey]: merge({}, defaultTheme, props[srcKey]), + [destKey]: extendDefaultTheme(defaultTheme, props[srcKey]), })) ) diff --git a/packages/core/src/theming/defaultTheme.js b/packages/core/src/theming/defaultTheme.js index 283e2cdd6..5fc1f0947 100644 --- a/packages/core/src/theming/defaultTheme.js +++ b/packages/core/src/theming/defaultTheme.js @@ -6,12 +6,11 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - -const defaultTextColor = '#333333' -const defaultFontSize = 11 - export const defaultTheme = { background: 'transparent', + fontFamily: 'sans-serif', + fontSize: 11, + textColor: '#333333', axis: { domain: { line: { @@ -21,50 +20,34 @@ export const defaultTheme = { }, ticks: { line: { - stroke: '#777', + stroke: '#777777', strokeWidth: 1, }, - text: { - fill: defaultTextColor, - fontSize: defaultFontSize, - }, + text: {}, }, legend: { - text: { - fill: defaultTextColor, - fontSize: defaultFontSize, - }, + text: {}, }, }, grid: { line: { - stroke: '#ddd', + stroke: '#dddddd', strokeWidth: 1, }, }, legends: { - text: { - fill: defaultTextColor, - fontSize: defaultFontSize, - }, + text: {}, }, labels: { - text: { - fill: defaultTextColor, - fontSize: defaultFontSize, - }, + text: {}, }, markers: { - lineColor: '#000', + lineColor: '#000000', lineStrokeWidth: 1, - textColor: defaultTextColor, - fontSize: defaultFontSize, + text: {}, }, dots: { - text: { - fill: defaultTextColor, - fontSize: defaultFontSize, - }, + text: {}, }, tooltip: { container: { diff --git a/packages/core/src/theming/extend.js b/packages/core/src/theming/extend.js new file mode 100644 index 000000000..dede6080c --- /dev/null +++ b/packages/core/src/theming/extend.js @@ -0,0 +1,38 @@ +/* + * This file is part of the nivo project. + * + * Copyright 2016-present, Raphaël Benitte. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +import merge from 'lodash/merge' +import get from 'lodash/get' +import set from 'lodash/set' + +const fontProps = [ + 'axis.ticks.text', + 'axis.legend.text', + 'legends.text', + 'labels.text', + 'dots.text', + 'markers.text', +] + +export const extendDefaultTheme = (defaultTheme, customTheme) => { + const theme = merge({}, defaultTheme, customTheme) + + fontProps.forEach(prop => { + if (get(theme, `${prop}.fontFamily`) === undefined) { + set(theme, `${prop}.fontFamily`, theme.fontFamily) + } + if (get(theme, `${prop}.fontSize`) === undefined) { + set(theme, `${prop}.fontSize`, theme.fontSize) + } + if (get(theme, `${prop}.fill`) === undefined) { + set(theme, `${prop}.fill`, theme.textColor) + } + }) + + return theme +} diff --git a/packages/core/src/theming/index.js b/packages/core/src/theming/index.js index eb8511915..530fcb9c8 100644 --- a/packages/core/src/theming/index.js +++ b/packages/core/src/theming/index.js @@ -8,3 +8,4 @@ */ export * from './propTypes' export * from './defaultTheme' +export * from './extend' diff --git a/packages/core/src/theming/propTypes.js b/packages/core/src/theming/propTypes.js index 6a981b453..7b873705f 100644 --- a/packages/core/src/theming/propTypes.js +++ b/packages/core/src/theming/propTypes.js @@ -8,6 +8,12 @@ */ import PropTypes from 'prop-types' +const textProps = { + fill: PropTypes.string, + fontSize: PropTypes.number, + fontFamily: PropTypes.string, +} + export const axisThemePropType = PropTypes.shape({ domain: PropTypes.shape({ line: PropTypes.shape({ @@ -22,16 +28,10 @@ export const axisThemePropType = PropTypes.shape({ strokeWidth: PropTypes.number.isRequired, strokeDasharray: PropTypes.string, }).isRequired, - text: PropTypes.shape({ - fill: PropTypes.string.isRequired, - fontSize: PropTypes.number.isRequired, - }).isRequired, + text: PropTypes.shape({ ...textProps }).isRequired, }).isRequired, legend: PropTypes.shape({ - text: PropTypes.shape({ - fill: PropTypes.string.isRequired, - fontSize: PropTypes.number.isRequired, - }).isRequired, + text: PropTypes.shape({ ...textProps }).isRequired, }).isRequired, }) @@ -44,31 +44,30 @@ export const gridThemePropType = PropTypes.shape({ }) export const legendsThemePropType = PropTypes.shape({ - text: PropTypes.shape({ - fill: PropTypes.string.isRequired, - fontSize: PropTypes.number.isRequired, - }).isRequired, + text: PropTypes.shape({ ...textProps }).isRequired, }) export const labelsThemePropType = PropTypes.shape({ - text: PropTypes.shape({ - fill: PropTypes.string.isRequired, - fontSize: PropTypes.number.isRequired, - }).isRequired, + text: PropTypes.shape({ ...textProps }).isRequired, }) export const dotsThemePropType = PropTypes.shape({ - text: PropTypes.shape({ - fill: PropTypes.string.isRequired, - fontSize: PropTypes.number.isRequired, - }).isRequired, + text: PropTypes.shape({ ...textProps }).isRequired, +}) + +export const markersThemePropType = PropTypes.shape({ + text: PropTypes.shape({ ...textProps }).isRequired, }) export const themePropType = PropTypes.shape({ background: PropTypes.string.isRequired, + fontFamily: PropTypes.string.isRequired, + fontSize: PropTypes.number.isRequired, + textColor: PropTypes.string.isRequired, axis: axisThemePropType.isRequired, grid: gridThemePropType.isRequired, legends: legendsThemePropType.isRequired, labels: labelsThemePropType.isRequired, dots: dotsThemePropType.isRequired, + markers: markersThemePropType, }) diff --git a/packages/heatmap/src/canvas.js b/packages/heatmap/src/canvas.js index e44f52b35..8d5976906 100644 --- a/packages/heatmap/src/canvas.js +++ b/packages/heatmap/src/canvas.js @@ -34,7 +34,7 @@ export const renderRect = ( if (enableLabels === true) { ctx.fillStyle = labelTextColor - ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily || 'sans-serif'}` + ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily}` ctx.fillText(value, x, y) } @@ -72,7 +72,7 @@ export const renderCircle = ( if (enableLabels === true) { ctx.fillStyle = labelTextColor - ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily || 'sans-serif'}` + ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily}` ctx.fillText(value, x, y) } diff --git a/packages/heatmap/tests/__snapshots__/HeatMap.test.js.snap b/packages/heatmap/tests/__snapshots__/HeatMap.test.js.snap index a23f38fa9..5f53ca7cd 100644 --- a/packages/heatmap/tests/__snapshots__/HeatMap.test.js.snap +++ b/packages/heatmap/tests/__snapshots__/HeatMap.test.js.snap @@ -37,7 +37,7 @@ exports[`should render a basic heat map chart 1`] = ` { ctx.textAlign = 'center' ctx.textBaseline = 'middle' - ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily || 'sans-serif'}` + ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily}` arcs.filter(arc => skipAngle === 0 || arc.angleDeg > skipAngle).forEach(arc => { const [centroidX, centroidY] = arcGenerator.centroid(arc) @@ -60,7 +60,7 @@ export const drawRadialLabels = ( }) ctx.textBaseline = 'middle' - ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily || 'sans-serif'}` + ctx.font = `${theme.labels.text.fontSize}px ${theme.labels.text.fontFamily}` radialLabels.forEach(label => { const dataWithColor = { diff --git a/packages/scatterplot/tests/__snapshots__/ScatterPlot.test.js.snap b/packages/scatterplot/tests/__snapshots__/ScatterPlot.test.js.snap index 13283f0a8..d6df432d3 100644 --- a/packages/scatterplot/tests/__snapshots__/ScatterPlot.test.js.snap +++ b/packages/scatterplot/tests/__snapshots__/ScatterPlot.test.js.snap @@ -26,7 +26,7 @@ exports[`should allow to customize symbol size 1`] = ` label !== undefined).forEach(node => { diff --git a/website/src/nivoTheme.js b/website/src/nivoTheme.js index 1e70a6559..ef5cf4b28 100644 --- a/website/src/nivoTheme.js +++ b/website/src/nivoTheme.js @@ -13,12 +13,12 @@ export const darkTheme = { }, text: { fill: '#F00', + fontSize: 11, }, }, legend: { text: { fill: '#eee', - fontSize: 12, fontWeight: 500, }, }, @@ -30,7 +30,6 @@ export const darkTheme = { }, legends: { text: { - fontSize: 12, fill: '#eee', }, }, @@ -44,19 +43,20 @@ export const darkTheme = { labels: { text: { fill: '#ddd', - fontSize: 12, fontWeight: 500, }, }, dots: { text: { fill: '#bbb', - fontSize: 12, }, }, } export const lightTheme = { + fontFamily: 'consolas, sans-serif', + fontSize: 12, + textColor: '#555', axis: { domain: { line: { @@ -70,16 +70,9 @@ export const lightTheme = { }, text: { fill: '#6a7c89', + fontSize: 11, }, }, - legend: { - fill: '#889eae', - }, - }, - legends: { - text: { - fontSize: 12, - }, }, tooltip: { container: { @@ -88,8 +81,6 @@ export const lightTheme = { }, labels: { text: { - fill: '#555', - fontSize: 12, fontWeight: 500, }, },