Skip to content

Commit a9ff5e1

Browse files
authored
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
1 parent abaa472 commit a9ff5e1

File tree

6 files changed

+71
-36
lines changed

6 files changed

+71
-36
lines changed

src/chart_types/xy_chart/store/chart_state.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { ChartStore } from './chart_state';
2020

2121
describe('Chart Store', () => {
2222
let store = new ChartStore();
23+
store.chartTheme = LIGHT_THEME;
2324

2425
const SPEC_ID = getSpecId('spec_1');
2526
const AXIS_ID = getAxisId('axis_1');
@@ -67,6 +68,7 @@ describe('Chart Store', () => {
6768
};
6869
beforeEach(() => {
6970
store = new ChartStore();
71+
store.chartTheme = LIGHT_THEME;
7072
store.updateParentDimensions(600, 600, 0, 0);
7173
store.computeChart();
7274
});

src/chart_types/xy_chart/store/chart_state.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ import {
4646
Rotation,
4747
} from '../utils/specs';
4848
import { formatTooltip, getSeriesTooltipValues } from '../tooltip/tooltip';
49-
import { LIGHT_THEME } from '../../../utils/themes/light_theme';
5049
import { mergeWithDefaultAnnotationLine, mergeWithDefaultAnnotationRect, Theme } from '../../../utils/themes/theme';
5150
import { compareByValueAsc } from '../../../utils/commons';
5251
import { computeChartDimensions } from '../utils/dimensions';
@@ -150,7 +149,10 @@ export class ChartStore {
150149

151150
chartRotation: Rotation = 0; // updated from jsx
152151
chartRendering: Rendering = 'canvas'; // updated from jsx
153-
chartTheme: Theme = LIGHT_THEME; // updated from jsx
152+
/**
153+
* Chart theme to be set from Settings.tsx
154+
*/
155+
chartTheme!: Theme;
154156
axesSpecs: Map<AxisId, AxisSpec> = new Map(); // readed from jsx
155157
axesTicksDimensions: Map<AxisId, AxisTicksDimensions> = new Map(); // computed
156158
axesPositions: Map<AxisId, Dimensions> = new Map(); // computed

src/specs/settings.test.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import { mount } from 'enzyme';
22
import * as React from 'react';
33
import { Position, Rendering, Rotation } from '../chart_types/xy_chart/utils/specs';
44
import { DARK_THEME } from '../utils/themes/dark_theme';
5-
import { LIGHT_THEME } from '../utils/themes/light_theme';
65
import { TooltipType } from '../chart_types/xy_chart/utils/interactions';
76
import { ChartStore } from '../chart_types/xy_chart/store/chart_state';
87
import { DEFAULT_TOOLTIP_SNAP, DEFAULT_TOOLTIP_TYPE, SettingsComponent, SettingSpecProps } from './settings';
9-
import { PartialTheme, BaseThemeTypes } from '../utils/themes/theme';
8+
import { PartialTheme } from '../utils/themes/theme';
109

1110
describe('Settings spec component', () => {
1211
test('should update store on mount if spec has a chart store', () => {
@@ -56,7 +55,7 @@ describe('Settings spec component', () => {
5655
test('should set chart properties on chart store', () => {
5756
const chartStore = new ChartStore();
5857

59-
expect(chartStore.chartTheme).toEqual(LIGHT_THEME);
58+
expect(chartStore.chartTheme).toBeUndefined();
6059
expect(chartStore.chartRotation).toBe(0);
6160
expect(chartStore.chartRendering).toBe('canvas');
6261
expect(chartStore.animateData).toBe(false);
@@ -163,11 +162,11 @@ describe('Settings spec component', () => {
163162
},
164163
};
165164

166-
expect(chartStore.chartTheme).toEqual(LIGHT_THEME);
165+
expect(chartStore.chartTheme).toBeUndefined();
167166

168167
const updatedProps: SettingSpecProps = {
169168
theme: partialTheme,
170-
baseThemeType: BaseThemeTypes.Dark,
169+
baseTheme: DARK_THEME,
171170
rotation: 90 as Rotation,
172171
rendering: 'svg' as Rendering,
173172
animateData: true,

src/specs/settings.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import { PureComponent } from 'react';
22
import { inject } from 'mobx-react';
33

44
import { DomainRange, Position, Rendering, Rotation } from '../chart_types/xy_chart/utils/specs';
5-
import { LIGHT_THEME } from '../utils/themes/light_theme';
6-
import { DARK_THEME } from '../utils/themes/dark_theme';
7-
import { BaseThemeType, mergeWithDefaultTheme, PartialTheme, Theme, BaseThemeTypes } from '../utils/themes/theme';
5+
import { mergeWithDefaultTheme, PartialTheme, Theme } from '../utils/themes/theme';
86
import { Domain } from '../utils/domain';
97
import { TooltipType, TooltipValueFormatter } from '../chart_types/xy_chart/utils/interactions';
108
import {
@@ -16,6 +14,7 @@ import {
1614
CursorUpdateListener,
1715
} from '../chart_types/xy_chart/store/chart_state';
1816
import { ScaleTypes } from '../utils/scales/scales';
17+
import { LIGHT_THEME } from '../utils/themes/light_theme';
1918

2019
export const DEFAULT_TOOLTIP_TYPE = TooltipType.VerticalCursor;
2120
export const DEFAULT_TOOLTIP_SNAP = true;
@@ -52,8 +51,16 @@ function isTooltipType(config: TooltipType | TooltipProps): config is TooltipTyp
5251

5352
export interface SettingSpecProps {
5453
chartStore?: ChartStore;
54+
/**
55+
* Full or partial theme to be merged with base
56+
*/
5557
theme?: Theme | PartialTheme;
56-
baseThemeType?: BaseThemeType;
58+
/**
59+
* Full default theme to use as base
60+
*
61+
* @default `LIGHT_THEME`
62+
*/
63+
baseTheme?: Theme;
5764
rendering: Rendering;
5865
rotation: Rotation;
5966
animateData: boolean;
@@ -76,20 +83,16 @@ export interface SettingSpecProps {
7683
xDomain?: Domain | DomainRange;
7784
}
7885

79-
function getTheme(theme?: Theme | PartialTheme, baseThemeType: BaseThemeType = BaseThemeTypes.Light): Theme {
80-
if (theme) {
81-
const baseTheme = baseThemeType === BaseThemeTypes.Light ? LIGHT_THEME : DARK_THEME;
82-
return mergeWithDefaultTheme(theme, baseTheme);
83-
}
84-
85-
return LIGHT_THEME;
86+
function getTheme(baseTheme?: Theme, theme?: Theme | PartialTheme): Theme {
87+
const base = baseTheme ? baseTheme : LIGHT_THEME;
88+
return theme ? mergeWithDefaultTheme(theme, base) : base;
8689
}
8790

8891
function updateChartStore(props: SettingSpecProps) {
8992
const {
9093
chartStore,
9194
theme,
92-
baseThemeType,
95+
baseTheme,
9396
rotation,
9497
rendering,
9598
animateData,
@@ -110,11 +113,12 @@ function updateChartStore(props: SettingSpecProps) {
110113
debug,
111114
xDomain,
112115
} = props;
116+
113117
if (!chartStore) {
114118
return;
115119
}
116120

117-
chartStore.chartTheme = getTheme(theme, baseThemeType);
121+
chartStore.chartTheme = getTheme(baseTheme, theme);
118122
chartStore.chartRotation = rotation;
119123
chartStore.chartRendering = rendering;
120124
chartStore.animateData = animateData;
@@ -176,7 +180,6 @@ export class SettingsComponent extends PureComponent<SettingSpecProps> {
176180
animateData: true,
177181
showLegend: false,
178182
debug: false,
179-
baseThemeType: BaseThemeTypes.Light,
180183
tooltip: {
181184
type: DEFAULT_TOOLTIP_TYPE,
182185
snap: DEFAULT_TOOLTIP_SNAP,

src/utils/themes/theme.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,6 @@ export interface Theme {
116116

117117
export type PartialTheme = RecursivePartial<Theme>;
118118

119-
export const BaseThemeTypes = Object.freeze({
120-
Light: 'light' as 'light',
121-
Dark: 'dark' as 'dark',
122-
});
123-
124-
export type BaseThemeType = typeof BaseThemeTypes.Dark | typeof BaseThemeTypes.Light;
125-
126119
export type DisplayValueStyle = TextStyle & {
127120
offsetX: number;
128121
offsetY: number;

stories/styling.tsx

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ import {
1919
Position,
2020
ScaleType,
2121
Settings,
22-
BaseThemeTypes,
2322
LineSeriesStyle,
2423
TooltipType,
2524
RecursivePartial,
2625
Theme,
26+
LIGHT_THEME,
27+
DARK_THEME,
2728
} from '../src/';
2829
import * as TestDatasets from '../src/utils/data_samples/test_dataset';
2930
import { palettes } from '../src/utils/themes/colors';
@@ -392,7 +393,7 @@ storiesOf('Stylings', module)
392393
<Chart className={className}>
393394
<Settings
394395
theme={theme}
395-
baseThemeType={darkmode ? 'dark' : 'light'}
396+
baseTheme={darkmode ? DARK_THEME : LIGHT_THEME}
396397
debug={boolean('debug', false)}
397398
showLegend={true}
398399
legendPosition={Position.Right}
@@ -442,7 +443,7 @@ storiesOf('Stylings', module)
442443
</Chart>
443444
);
444445
})
445-
.add('partial custom theme', () => {
446+
.add('partial custom theme with baseThemeType', () => {
446447
const customPartialTheme: PartialTheme = {
447448
barSeriesStyle: {
448449
rectBorder: {
@@ -454,12 +455,47 @@ storiesOf('Stylings', module)
454455

455456
return (
456457
<Chart className="story-chart">
457-
<Settings
458-
showLegend
459-
theme={customPartialTheme}
460-
baseThemeType={BaseThemeTypes.Light}
461-
legendPosition={Position.Right}
458+
<Settings showLegend theme={customPartialTheme} baseTheme={LIGHT_THEME} legendPosition={Position.Right} />
459+
<Axis id={getAxisId('bottom')} position={Position.Bottom} title="Bottom axis" showOverlappingTicks={true} />
460+
<Axis
461+
id={getAxisId('left2')}
462+
title="Left axis"
463+
position={Position.Left}
464+
tickFormat={(d) => Number(d).toFixed(2)}
465+
/>
466+
<Axis id={getAxisId('top')} position={Position.Top} title="Top axis" showOverlappingTicks={true} />
467+
<Axis
468+
id={getAxisId('right')}
469+
title="Right axis"
470+
position={Position.Right}
471+
tickFormat={(d) => Number(d).toFixed(2)}
462472
/>
473+
<BarSeries
474+
id={getSpecId('bars')}
475+
xScaleType={ScaleType.Linear}
476+
yScaleType={ScaleType.Linear}
477+
xAccessor="x"
478+
yAccessors={['y']}
479+
splitSeriesAccessors={['g']}
480+
stackAccessors={['x']}
481+
data={data1}
482+
/>
483+
</Chart>
484+
);
485+
})
486+
.add('partial custom theme with baseTheme', () => {
487+
const customPartialTheme: PartialTheme = {
488+
barSeriesStyle: {
489+
rectBorder: {
490+
stroke: color('BarBorderStroke', 'white'),
491+
visible: true,
492+
},
493+
},
494+
};
495+
496+
return (
497+
<Chart className="story-chart">
498+
<Settings showLegend theme={customPartialTheme} baseTheme={LIGHT_THEME} legendPosition={Position.Right} />
463499
<Axis id={getAxisId('bottom')} position={Position.Bottom} title="Bottom axis" showOverlappingTicks={true} />
464500
<Axis
465501
id={getAxisId('left2')}

0 commit comments

Comments
 (0)