From a9ff5e1cfcd1c88fa2b811bd59096de9dc74eead Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Wed, 21 Aug 2019 12:20:22 -0500 Subject: [PATCH] feat(theme): base theme prop (#333) * Allow `baseTheme` prop to set base theme, default is still `LIGHT_THEME` * refactor: theme type logic BREAKING CHANGE: remove `baseThemeType` prop on `Settings` component and `BaseThemeTypes` type. #292 --- .../xy_chart/store/chart_state.test.ts | 2 + src/chart_types/xy_chart/store/chart_state.ts | 6 ++- src/specs/settings.test.tsx | 9 ++-- src/specs/settings.tsx | 31 ++++++----- src/utils/themes/theme.ts | 7 --- stories/styling.tsx | 52 ++++++++++++++++--- 6 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/chart_types/xy_chart/store/chart_state.test.ts b/src/chart_types/xy_chart/store/chart_state.test.ts index d1d70f32d4..3a77008179 100644 --- a/src/chart_types/xy_chart/store/chart_state.test.ts +++ b/src/chart_types/xy_chart/store/chart_state.test.ts @@ -20,6 +20,7 @@ import { ChartStore } from './chart_state'; describe('Chart Store', () => { let store = new ChartStore(); + store.chartTheme = LIGHT_THEME; const SPEC_ID = getSpecId('spec_1'); const AXIS_ID = getAxisId('axis_1'); @@ -67,6 +68,7 @@ describe('Chart Store', () => { }; beforeEach(() => { store = new ChartStore(); + store.chartTheme = LIGHT_THEME; store.updateParentDimensions(600, 600, 0, 0); store.computeChart(); }); diff --git a/src/chart_types/xy_chart/store/chart_state.ts b/src/chart_types/xy_chart/store/chart_state.ts index 268378da3c..3d9a697cde 100644 --- a/src/chart_types/xy_chart/store/chart_state.ts +++ b/src/chart_types/xy_chart/store/chart_state.ts @@ -46,7 +46,6 @@ import { Rotation, } from '../utils/specs'; import { formatTooltip, getSeriesTooltipValues } from '../tooltip/tooltip'; -import { LIGHT_THEME } from '../../../utils/themes/light_theme'; import { mergeWithDefaultAnnotationLine, mergeWithDefaultAnnotationRect, Theme } from '../../../utils/themes/theme'; import { compareByValueAsc } from '../../../utils/commons'; import { computeChartDimensions } from '../utils/dimensions'; @@ -150,7 +149,10 @@ export class ChartStore { chartRotation: Rotation = 0; // updated from jsx chartRendering: Rendering = 'canvas'; // updated from jsx - chartTheme: Theme = LIGHT_THEME; // updated from jsx + /** + * Chart theme to be set from Settings.tsx + */ + chartTheme!: Theme; axesSpecs: Map = new Map(); // readed from jsx axesTicksDimensions: Map = new Map(); // computed axesPositions: Map = new Map(); // computed diff --git a/src/specs/settings.test.tsx b/src/specs/settings.test.tsx index 6844b86f55..0e1f3e7125 100644 --- a/src/specs/settings.test.tsx +++ b/src/specs/settings.test.tsx @@ -2,11 +2,10 @@ import { mount } from 'enzyme'; import * as React from 'react'; import { Position, Rendering, Rotation } from '../chart_types/xy_chart/utils/specs'; import { DARK_THEME } from '../utils/themes/dark_theme'; -import { LIGHT_THEME } from '../utils/themes/light_theme'; import { TooltipType } from '../chart_types/xy_chart/utils/interactions'; import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; import { DEFAULT_TOOLTIP_SNAP, DEFAULT_TOOLTIP_TYPE, SettingsComponent, SettingSpecProps } from './settings'; -import { PartialTheme, BaseThemeTypes } from '../utils/themes/theme'; +import { PartialTheme } from '../utils/themes/theme'; describe('Settings spec component', () => { test('should update store on mount if spec has a chart store', () => { @@ -56,7 +55,7 @@ describe('Settings spec component', () => { test('should set chart properties on chart store', () => { const chartStore = new ChartStore(); - expect(chartStore.chartTheme).toEqual(LIGHT_THEME); + expect(chartStore.chartTheme).toBeUndefined(); expect(chartStore.chartRotation).toBe(0); expect(chartStore.chartRendering).toBe('canvas'); expect(chartStore.animateData).toBe(false); @@ -163,11 +162,11 @@ describe('Settings spec component', () => { }, }; - expect(chartStore.chartTheme).toEqual(LIGHT_THEME); + expect(chartStore.chartTheme).toBeUndefined(); const updatedProps: SettingSpecProps = { theme: partialTheme, - baseThemeType: BaseThemeTypes.Dark, + baseTheme: DARK_THEME, rotation: 90 as Rotation, rendering: 'svg' as Rendering, animateData: true, diff --git a/src/specs/settings.tsx b/src/specs/settings.tsx index 1bd412aef9..754d2989aa 100644 --- a/src/specs/settings.tsx +++ b/src/specs/settings.tsx @@ -2,9 +2,7 @@ import { PureComponent } from 'react'; import { inject } from 'mobx-react'; import { DomainRange, Position, Rendering, Rotation } from '../chart_types/xy_chart/utils/specs'; -import { LIGHT_THEME } from '../utils/themes/light_theme'; -import { DARK_THEME } from '../utils/themes/dark_theme'; -import { BaseThemeType, mergeWithDefaultTheme, PartialTheme, Theme, BaseThemeTypes } from '../utils/themes/theme'; +import { mergeWithDefaultTheme, PartialTheme, Theme } from '../utils/themes/theme'; import { Domain } from '../utils/domain'; import { TooltipType, TooltipValueFormatter } from '../chart_types/xy_chart/utils/interactions'; import { @@ -16,6 +14,7 @@ import { CursorUpdateListener, } from '../chart_types/xy_chart/store/chart_state'; import { ScaleTypes } from '../utils/scales/scales'; +import { LIGHT_THEME } from '../utils/themes/light_theme'; export const DEFAULT_TOOLTIP_TYPE = TooltipType.VerticalCursor; export const DEFAULT_TOOLTIP_SNAP = true; @@ -52,8 +51,16 @@ function isTooltipType(config: TooltipType | TooltipProps): config is TooltipTyp export interface SettingSpecProps { chartStore?: ChartStore; + /** + * Full or partial theme to be merged with base + */ theme?: Theme | PartialTheme; - baseThemeType?: BaseThemeType; + /** + * Full default theme to use as base + * + * @default `LIGHT_THEME` + */ + baseTheme?: Theme; rendering: Rendering; rotation: Rotation; animateData: boolean; @@ -76,20 +83,16 @@ export interface SettingSpecProps { xDomain?: Domain | DomainRange; } -function getTheme(theme?: Theme | PartialTheme, baseThemeType: BaseThemeType = BaseThemeTypes.Light): Theme { - if (theme) { - const baseTheme = baseThemeType === BaseThemeTypes.Light ? LIGHT_THEME : DARK_THEME; - return mergeWithDefaultTheme(theme, baseTheme); - } - - return LIGHT_THEME; +function getTheme(baseTheme?: Theme, theme?: Theme | PartialTheme): Theme { + const base = baseTheme ? baseTheme : LIGHT_THEME; + return theme ? mergeWithDefaultTheme(theme, base) : base; } function updateChartStore(props: SettingSpecProps) { const { chartStore, theme, - baseThemeType, + baseTheme, rotation, rendering, animateData, @@ -110,11 +113,12 @@ function updateChartStore(props: SettingSpecProps) { debug, xDomain, } = props; + if (!chartStore) { return; } - chartStore.chartTheme = getTheme(theme, baseThemeType); + chartStore.chartTheme = getTheme(baseTheme, theme); chartStore.chartRotation = rotation; chartStore.chartRendering = rendering; chartStore.animateData = animateData; @@ -176,7 +180,6 @@ export class SettingsComponent extends PureComponent { animateData: true, showLegend: false, debug: false, - baseThemeType: BaseThemeTypes.Light, tooltip: { type: DEFAULT_TOOLTIP_TYPE, snap: DEFAULT_TOOLTIP_SNAP, diff --git a/src/utils/themes/theme.ts b/src/utils/themes/theme.ts index cddfb4b416..827f047b6f 100644 --- a/src/utils/themes/theme.ts +++ b/src/utils/themes/theme.ts @@ -116,13 +116,6 @@ export interface Theme { export type PartialTheme = RecursivePartial; -export const BaseThemeTypes = Object.freeze({ - Light: 'light' as 'light', - Dark: 'dark' as 'dark', -}); - -export type BaseThemeType = typeof BaseThemeTypes.Dark | typeof BaseThemeTypes.Light; - export type DisplayValueStyle = TextStyle & { offsetX: number; offsetY: number; diff --git a/stories/styling.tsx b/stories/styling.tsx index 7d3b3695b0..6e4625aaab 100644 --- a/stories/styling.tsx +++ b/stories/styling.tsx @@ -19,11 +19,12 @@ import { Position, ScaleType, Settings, - BaseThemeTypes, LineSeriesStyle, TooltipType, RecursivePartial, Theme, + LIGHT_THEME, + DARK_THEME, } from '../src/'; import * as TestDatasets from '../src/utils/data_samples/test_dataset'; import { palettes } from '../src/utils/themes/colors'; @@ -392,7 +393,7 @@ storiesOf('Stylings', module) ); }) - .add('partial custom theme', () => { + .add('partial custom theme with baseThemeType', () => { const customPartialTheme: PartialTheme = { barSeriesStyle: { rectBorder: { @@ -454,12 +455,47 @@ storiesOf('Stylings', module) return ( - + + Number(d).toFixed(2)} + /> + + Number(d).toFixed(2)} /> + + + ); + }) + .add('partial custom theme with baseTheme', () => { + const customPartialTheme: PartialTheme = { + barSeriesStyle: { + rectBorder: { + stroke: color('BarBorderStroke', 'white'), + visible: true, + }, + }, + }; + + return ( + +