Skip to content

Commit c80c6a8

Browse files
committed
feat(dark): enabled showing the dark theme if desired by the visitor
1 parent 421f327 commit c80c6a8

File tree

7 files changed

+216
-43
lines changed

7 files changed

+216
-43
lines changed

.storybook/config.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import React from 'react';
2+
import {useMediaQuery} from '@material-ui/core';
23
import {addDecorator, configure, getStorybook, setAddon} from '@storybook/react';
34
import {withInfo} from '@storybook/addon-info';
45
import createPercyAddon from '@percy-io/percy-storybook';
56
import {MuiThemeProvider} from '@material-ui/core/styles';
67
import createTheme from '../src/theme';
78

8-
addDecorator(story => (
9-
<MuiThemeProvider theme={createTheme()}>
10-
{story()}
11-
</MuiThemeProvider>
12-
));
9+
const Wrapper = ({story}) => {
10+
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
11+
12+
return (
13+
<MuiThemeProvider theme={createTheme(prefersDarkMode ? 'dark' : 'light')}>
14+
{story()}
15+
</MuiThemeProvider>
16+
);
17+
};
18+
19+
addDecorator(story => <Wrapper story={story} />);
1320

1421
function loadStories() {
1522
const req = require.context('../src', true, /stories.js$/);

package-lock.json

+116
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"rollup-plugin-babel": "4.3.3",
8787
"rollup-plugin-json": "4.0.0",
8888
"rollup-plugin-node-resolve": "5.2.0",
89+
"sinon": "^7.5.0",
8990
"start-server-and-test": "^1.9.1"
9091
},
9192
"peerDependencies": {

src/organisms/layout/presentational.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {bool, func, node, shape, string} from 'prop-types';
33
import {CssBaseline, withStyles} from '@material-ui/core';
44
import {ThemeProvider} from '@material-ui/styles';
55
import classNames from 'classnames';
6+
import {useMediaQuery} from '../../../thirdparty-wrappers/material-ui';
67
import Header from '../../molecules/header';
78
import NavigationDrawer from '../../molecules/navigation';
89
import createTheme from '../../theme';
@@ -30,8 +31,10 @@ function styles(theme) {
3031
}
3132

3233
export function Layout({children, navigationOpen, onNavigationDrawerToggle, classes}) {
34+
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
35+
3336
return (
34-
<ThemeProvider theme={createTheme()}>
37+
<ThemeProvider theme={createTheme(prefersDarkMode ? 'dark' : 'light')}>
3538
<CssBaseline />
3639
<div css={{display: 'flex'}}>
3740
<Header navigationOpen={navigationOpen} onNavigationDrawerToggle={onNavigationDrawerToggle} />

src/theme.js

+39-34
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,51 @@
11
import {createMuiTheme} from '@material-ui/core';
22

33
// palette generated at http://mcg.mbitson.com/ from #c80000
4-
export default function createTheme() {
4+
export default function createTheme(colorScheme = 'light') {
55
return createMuiTheme({
66
typography: {
77
useNextVariants: true
88
},
99
palette: {
10+
type: colorScheme,
1011
primary: {
11-
50: '#f8e0e0',
12-
100: '#efb3b3',
13-
200: '#e48080',
14-
300: '#d94d4d',
15-
400: '#d02626',
16-
500: '#c80000',
17-
600: '#c20000',
18-
700: '#bb0000',
19-
800: '#b40000',
20-
900: '#a70000',
21-
A100: '#ffd1d1',
22-
A200: '#ff9e9e',
23-
A400: '#ff6b6b',
24-
A700: '#ff5252',
25-
contrastDefaultColor: 'light',
26-
contrastDarkColors: [
27-
'50',
28-
'100',
29-
'200',
30-
'A100',
31-
'A200',
32-
'A400',
33-
'A700'
34-
],
35-
contrastLightColors: [
36-
'300',
37-
'400',
38-
'500',
39-
'600',
40-
'700',
41-
'800',
42-
'900'
43-
]
12+
main: '#c80000'
13+
// 50: '#f8e0e0',
14+
// 100: '#efb3b3',
15+
// 200: '#e48080',
16+
// 300: '#d94d4d',
17+
// 400: '#d02626',
18+
// 500: '#c80000',
19+
// 600: '#c20000',
20+
// 700: '#bb0000',
21+
// 800: '#b40000',
22+
// 900: '#a70000',
23+
// A100: '#ffd1d1',
24+
// A200: '#ff9e9e',
25+
// A400: '#ff6b6b',
26+
// A700: '#ff5252',
27+
// contrastDefaultColor: 'light',
28+
// contrastDarkColors: [
29+
// '50',
30+
// '100',
31+
// '200',
32+
// 'A100',
33+
// 'A200',
34+
// 'A400',
35+
// 'A700'
36+
// ],
37+
// contrastLightColors: [
38+
// '300',
39+
// '400',
40+
// '500',
41+
// '600',
42+
// '700',
43+
// '800',
44+
// '900'
45+
// ]
46+
},
47+
secondary: {
48+
main: '#666'
4449
}
4550
}
4651
});

test/unit/organisms/layout/presentational-test.js

+39-3
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,69 @@ import {CssBaseline} from '@material-ui/core';
33
import {shallow} from 'enzyme';
44
import {assert} from 'chai';
55
import any from '@travi/any';
6+
import sinon from 'sinon';
7+
import * as wrappedMaterial from '../../../../thirdparty-wrappers/material-ui';
68
import {Layout} from '../../../../src/organisms/layout/presentational';
79
import Header from '../../../../src/molecules/header';
810
import NavigationDrawer from '../../../../src/molecules/navigation';
11+
import * as themeCreator from '../../../../src/theme';
912

1013
suite('layout', () => {
14+
let sandbox;
1115
const Child = () => null;
1216
Child.displayName = 'Child';
1317

18+
setup(() => {
19+
sandbox = sinon.createSandbox();
20+
21+
sandbox.stub(themeCreator, 'default');
22+
sandbox.stub(wrappedMaterial, 'useMediaQuery');
23+
});
24+
25+
teardown(() => sandbox.restore());
26+
1427
test('that the layout includes the header and children', () => {
1528
const navigationToggleHandler = () => undefined;
1629
const navigationOpen = any.boolean();
30+
const theme = any.simpleObject();
31+
wrappedMaterial.useMediaQuery.returns(false);
32+
themeCreator.default.withArgs('light').returns(theme);
1733

1834
const wrapper = shallow(
1935
<Layout navigationOpen={navigationOpen} onNavigationDrawerToggle={navigationToggleHandler}>
2036
<Child />
2137
</Layout>
2238
);
23-
const header = wrapper.find(Header);
24-
const navDrawer = wrapper.find(NavigationDrawer);
39+
const themeProvider = wrapper.find('ThemeProvider');
40+
const header = themeProvider.find(Header);
41+
const navDrawer = themeProvider.find(NavigationDrawer);
42+
43+
assert.equal(themeProvider.prop('theme'), theme);
2544

2645
assert.isTrue(wrapper.find(CssBaseline).exists());
27-
assert.isTrue(wrapper.find('Child').exists());
46+
assert.isTrue(themeProvider.find('Child').exists());
2847

2948
assert.equal(header.prop('onNavigationDrawerToggle'), navigationToggleHandler);
3049
assert.equal(header.prop('navigationOpen'), navigationOpen);
3150

3251
assert.equal(navDrawer.prop('onToggle'), navigationToggleHandler);
3352
assert.equal(navDrawer.prop('open'), navigationOpen);
3453
});
54+
55+
test('that dark mode is enabled when preferred', () => {
56+
const navigationToggleHandler = () => undefined;
57+
const navigationOpen = any.boolean();
58+
const theme = any.simpleObject();
59+
wrappedMaterial.useMediaQuery.withArgs('(prefers-color-scheme: dark)').returns(true);
60+
themeCreator.default.withArgs('dark').returns(theme);
61+
62+
const wrapper = shallow(
63+
<Layout navigationOpen={navigationOpen} onNavigationDrawerToggle={navigationToggleHandler}>
64+
<Child />
65+
</Layout>
66+
);
67+
const themeProvider = wrapper.find('ThemeProvider');
68+
69+
assert.equal(themeProvider.prop('theme'), theme);
70+
});
3571
});

thirdparty-wrappers/material-ui.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import {useMediaQuery as materialUseMediaQuery} from '@material-ui/core';
2+
3+
export function useMediaQuery(...args) {
4+
return materialUseMediaQuery(...args);
5+
}

0 commit comments

Comments
 (0)