summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-05-22 17:39:39 +0200
committerArmand Philippot <git@armandphilippot.com>2022-05-22 17:39:39 +0200
commit3ed7f185e82c0cc87c63b75dc8cddfecc5c608ce (patch)
treeb1b314cec900ebb3f671269f6fc9560242e90a0a
parent321dae4a47594af83269fa560b375965d7f35763 (diff)
chore(storybook): use custom themes and add dark mode support
-rw-r--r--.storybook/main.js1
-rw-r--r--.storybook/manager.js6
-rw-r--r--.storybook/overrides/docs-container.js36
-rw-r--r--.storybook/preview.js40
-rw-r--r--.storybook/themes/common.js8
-rw-r--r--.storybook/themes/dark.js37
-rw-r--r--.storybook/themes/light.js36
-rw-r--r--package.json3
-rw-r--r--src/styles/base/_base.scss16
-rw-r--r--yarn.lock14
10 files changed, 184 insertions, 13 deletions
diff --git a/.storybook/main.js b/.storybook/main.js
index bedbd0e..477b09e 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -11,6 +11,7 @@ const storybookConfig = {
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'storybook-addon-next',
+ 'storybook-dark-mode',
],
framework: '@storybook/react',
core: {
diff --git a/.storybook/manager.js b/.storybook/manager.js
new file mode 100644
index 0000000..945c246
--- /dev/null
+++ b/.storybook/manager.js
@@ -0,0 +1,6 @@
+import { addons } from '@storybook/addons';
+import light from './themes/light';
+
+addons.setConfig({
+ theme: light,
+});
diff --git a/.storybook/overrides/docs-container.js b/.storybook/overrides/docs-container.js
new file mode 100644
index 0000000..f539986
--- /dev/null
+++ b/.storybook/overrides/docs-container.js
@@ -0,0 +1,36 @@
+import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks';
+import { useDarkMode } from 'storybook-dark-mode';
+import dark from '../themes/dark';
+import light from '../themes/light';
+
+/**
+ * Custom Docs Container to support dark theme.
+ *
+ * @see https://github.com/hipstersmoothie/storybook-dark-mode/issues/127#issuecomment-1070524402
+ */
+export const DocsContainer = ({ children, context }) => {
+ const isDark = useDarkMode();
+
+ return (
+ <BaseContainer
+ context={{
+ ...context,
+ storyById: (id) => {
+ const storyContext = context.storyById(id);
+ return {
+ ...storyContext,
+ parameters: {
+ ...storyContext?.parameters,
+ docs: {
+ ...storyContext?.parameters?.docs,
+ theme: isDark ? dark : light,
+ },
+ },
+ };
+ },
+ }}
+ >
+ {children}
+ </BaseContainer>
+ );
+};
diff --git a/.storybook/preview.js b/.storybook/preview.js
index e30927b..9df7514 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -1,6 +1,12 @@
-import '@styles/globals.scss';
import * as NextImage from 'next/image';
+import { ThemeProvider, useTheme } from 'next-themes';
+import { useEffect } from 'react';
import { IntlProvider } from 'react-intl';
+import { useDarkMode } from 'storybook-dark-mode';
+import { DocsContainer } from './overrides/docs-container';
+import dark from './themes/dark';
+import light from './themes/light';
+import '@styles/globals.scss';
const OriginalNextImage = NextImage.default;
@@ -27,12 +33,42 @@ export const parameters = {
date: /Date$/,
},
},
+ darkMode: {
+ // Override the default dark theme
+ dark: { ...dark },
+ // Override the default light theme
+ light: { ...light },
+ stylePreview: true,
+ },
+ docs: {
+ container: DocsContainer,
+ },
+};
+
+// Create a component that listens for theme change.
+export const ThemeWrapper = (props) => {
+ const { setTheme } = useTheme();
+ const theme = useDarkMode() ? 'dark' : 'light';
+
+ useEffect(() => {
+ setTheme(theme);
+ }, [theme, setTheme]);
+
+ return <>{props.children}</>;
};
export const decorators = [
(Story) => (
<IntlProvider locale="en">
- <Story />
+ <ThemeProvider
+ defaultTheme="system"
+ enableColorScheme={true}
+ enableSystem={true}
+ >
+ <ThemeWrapper>
+ <Story />
+ </ThemeWrapper>
+ </ThemeProvider>
</IntlProvider>
),
];
diff --git a/.storybook/themes/common.js b/.storybook/themes/common.js
new file mode 100644
index 0000000..17619c2
--- /dev/null
+++ b/.storybook/themes/common.js
@@ -0,0 +1,8 @@
+export const brand = {
+ title: 'Design system',
+};
+
+export const fontFamilies = {
+ mono: '"Cousine", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace',
+ primary: '"Inter", "Liberation Sans", Arial, sans-serif',
+};
diff --git a/.storybook/themes/dark.js b/.storybook/themes/dark.js
new file mode 100644
index 0000000..e23703b
--- /dev/null
+++ b/.storybook/themes/dark.js
@@ -0,0 +1,37 @@
+import { create } from '@storybook/theming';
+import { brand, fontFamilies } from './common';
+
+const colors = {
+ black: 'hsl(208, 25%, 11%)',
+ blackBright: 'hsl(208, 21%, 15%)',
+ blue: 'hsl(200, 50%, 68%)',
+ blueBright: 'hsl(200, 55%, 70%)',
+ grey: 'hsl(208, 10%, 70%)',
+ greyDark: 'hsl(208, 20%, 25%)',
+ greyDarker: 'hsl(208, 18%, 20%)',
+ white: 'hsl(208, 25%, 92%)',
+ whiteDark: 'hsl(206, 20%, 93%)',
+};
+
+export default create({
+ base: 'dark',
+ brandTitle: brand.title,
+ colorPrimary: colors.blue,
+ colorSecondary: colors.blueBright,
+ appBg: colors.black,
+ appContentBg: colors.black,
+ appBorderColor: colors.greyDark,
+ appBorderRadius: 3,
+ fontBase: fontFamilies.primary,
+ fontCode: fontFamilies.mono,
+ textColor: colors.white,
+ textInverseColor: colors.black,
+ textMutedColor: colors.grey,
+ barTextColor: colors.white,
+ barSelectedColor: colors.blueBright,
+ barBg: colors.blackBright,
+ inputBg: colors.greyDarker,
+ inputBorder: colors.greyDark,
+ inputTextColor: colors.white,
+ inputBorderRadius: 0,
+});
diff --git a/.storybook/themes/light.js b/.storybook/themes/light.js
new file mode 100644
index 0000000..d445272
--- /dev/null
+++ b/.storybook/themes/light.js
@@ -0,0 +1,36 @@
+import { create } from '@storybook/theming';
+import { brand, fontFamilies } from './common';
+
+const colors = {
+ black: 'hsl(207, 47%, 11%)',
+ blue: 'hsl(206, 75%, 31%)',
+ blueBright: 'hsl(206, 77%, 36%)',
+ grey: 'hsl(206, 15%, 80%)',
+ greyBright: 'hsl(206, 20%, 86%)',
+ greyDark: 'hsl(206, 30%, 30%)',
+ white: 'hsl(206, 15%, 97%)',
+ whiteDark: 'hsl(206, 20%, 93%)',
+};
+
+export default create({
+ base: 'light',
+ brandTitle: brand.title,
+ colorPrimary: colors.blue,
+ colorSecondary: colors.blueBright,
+ appBg: colors.white,
+ appContentBg: colors.white,
+ appBorderColor: colors.grey,
+ appBorderRadius: 3,
+ fontBase: fontFamilies.primary,
+ fontCode: fontFamilies.mono,
+ textColor: colors.black,
+ textInverseColor: colors.white,
+ textMutedColor: colors.greyDark,
+ barTextColor: colors.black,
+ barSelectedColor: colors.blueBright,
+ barBg: colors.whiteDark,
+ inputBg: colors.greyBright,
+ inputBorder: colors.grey,
+ inputTextColor: colors.black,
+ inputBorderRadius: 0,
+});
diff --git a/package.json b/package.json
index 08f6140..447a372 100644
--- a/package.json
+++ b/package.json
@@ -65,10 +65,12 @@
"@storybook/addon-essentials": "^6.5.3",
"@storybook/addon-interactions": "^6.5.3",
"@storybook/addon-links": "^6.5.3",
+ "@storybook/addons": "^6.5.3",
"@storybook/builder-webpack5": "^6.5.3",
"@storybook/manager-webpack5": "^6.5.3",
"@storybook/react": "^6.5.3",
"@storybook/testing-library": "^0.0.11",
+ "@storybook/theming": "^6.5.3",
"@svgr/webpack": "^6.2.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
@@ -93,6 +95,7 @@
"sass": "^1.50.0",
"standard-version": "^9.3.2",
"storybook-addon-next": "^1.6.2",
+ "storybook-dark-mode": "^1.1.0",
"stylelint": "^14.7.0",
"stylelint-config-standard": "^25.0.0",
"stylelint-config-standard-scss": "^3.0.0",
diff --git a/src/styles/base/_base.scss b/src/styles/base/_base.scss
index 25ef393..1ec5494 100644
--- a/src/styles/base/_base.scss
+++ b/src/styles/base/_base.scss
@@ -70,14 +70,6 @@ body {
flex-flow: column nowrap;
min-height: 100vh;
background: var(--color-bg);
- border-top: max(0.4vw, fun.convert-px(6)) solid;
- border-bottom: max(0.4vw, fun.convert-px(6)) solid;
- border-image: radial-gradient(
- ellipse at center,
- var(--color-primary-lighter) 20%,
- var(--color-primary) 100%
- )
- 1;
color: var(--color-fg);
font-family: var(--font-family-primary);
font-size: var(--font-size-md);
@@ -89,4 +81,12 @@ body {
display: flex;
flex-flow: column nowrap;
height: 100%;
+ border-top: max(0.4vw, fun.convert-px(6)) solid;
+ border-bottom: max(0.4vw, fun.convert-px(6)) solid;
+ border-image: radial-gradient(
+ ellipse at center,
+ var(--color-primary-lighter) 20%,
+ var(--color-primary) 100%
+ )
+ 1;
}
diff --git a/yarn.lock b/yarn.lock
index 3c60c95..3388622 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2442,7 +2442,7 @@
global "^4.4.0"
regenerator-runtime "^0.13.7"
-"@storybook/addons@6.5.3":
+"@storybook/addons@6.5.3", "@storybook/addons@^6.5.3":
version "6.5.3"
resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.3.tgz#43dd276417edf74be0c465b968d35795f8cd994d"
integrity sha512-gzzkxZ7R4+EaEzIEBbTWmkA55JDEDQrDjg3nNY/SJklnRigYdStz41KSPx6HGkF2CaI5BYVd5vZCawYvG16gyg==
@@ -3239,7 +3239,7 @@
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
-"@storybook/theming@6.5.3":
+"@storybook/theming@6.5.3", "@storybook/theming@^6.5.3":
version "6.5.3"
resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.3.tgz#a8df53df2812d49453a3410346123231e028c103"
integrity sha512-2tM46jahAhKRUzCcoaqPoqs+4imXqbze0dCPZ0cdVnfs14jhMB1lAfGE+diodCCaUcXUu8r2c5dTPKqqM1lHqQ==
@@ -7673,7 +7673,7 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+fast-deep-equal@^3.0.0, fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
@@ -13914,6 +13914,14 @@ storybook-addon-next@^1.6.2:
sass-loader "^12.4.0"
semver "^7.3.5"
+storybook-dark-mode@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/storybook-dark-mode/-/storybook-dark-mode-1.1.0.tgz#4aca307a9c09f1b95743da2db6b07c8eea99ed24"
+ integrity sha512-F+hG02zYGBzxGTUonA1XDV/CtMYm3OjF38Tu1CIUN+w+8hwUrwLcOtgtLLw6VjSrZdJ/ECK+tjXdKTV4oZqAXw==
+ dependencies:
+ fast-deep-equal "^3.0.0"
+ memoizerific "^1.11.3"
+
stream-browserify@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"