Add theme and palette explorer

This commit is contained in:
Mark Sinclair
2022-03-08 14:54:06 +00:00
parent c791de426a
commit abc5dd8b92
11 changed files with 326 additions and 46 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
<svg width="210" height="56" viewBox="0 0 210 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M45.8829 0.142822H45.7169V0.28114V48.637L25.3289 0.225818L25.3012 0.142822H25.1905H13.6272H0.652966H0.514648V0.28114V55.7189V55.8572H0.652966H13.6272H13.7655V55.7189V7.28002L34.2365 55.7742L34.2642 55.8572H34.3748H45.8829H58.8294H58.9677V55.7189V0.28114V0.142822H58.8294H45.8829Z" fill="white"/>
<path d="M209.347 0.142822H184.616H184.477L184.45 0.253483L171.78 48.8583L159.082 0.253483L159.054 0.142822H158.944H134.157H133.991V0.28114V55.7189V55.8572H134.157H147.104H147.242V55.7189V7.66731L159.774 55.7466L159.801 55.8572H159.94H183.564H183.675L183.703 55.7466L196.234 7.66731V55.7189V55.8572H196.373H209.347H209.485V55.7189V0.28114V0.142822H209.347Z" fill="white"/>
<path d="M112.663 0.142822H112.58L112.552 0.198153L96.8116 27.5574L80.988 0.198153L80.9604 0.142822H80.8774H65.9114H65.6348L65.7731 0.364136L90.1447 42.5787V55.7189V55.8572H90.283H103.257H103.396V55.7189V42.5787L127.767 0.364136L127.905 0.142822H127.629H112.663Z" fill="white"/>
<path d="M45.8829 0.142822H45.7169V0.28114V48.637L25.3289 0.225818L25.3012 0.142822H25.1905H13.6272H0.652966H0.514648V0.28114V55.7189V55.8572H0.652966H13.6272H13.7655V55.7189V7.28002L34.2365 55.7742L34.2642 55.8572H34.3748H45.8829H58.8294H58.9677V55.7189V0.28114V0.142822H58.8294H45.8829Z"/>
<path d="M209.347 0.142822H184.616H184.477L184.45 0.253483L171.78 48.8583L159.082 0.253483L159.054 0.142822H158.944H134.157H133.991V0.28114V55.7189V55.8572H134.157H147.104H147.242V55.7189V7.66731L159.774 55.7466L159.801 55.8572H159.94H183.564H183.675L183.703 55.7466L196.234 7.66731V55.7189V55.8572H196.373H209.347H209.485V55.7189V0.28114V0.142822H209.347Z"/>
<path d="M112.663 0.142822H112.58L112.552 0.198153L96.8116 27.5574L80.988 0.198153L80.9604 0.142822H80.8774H65.9114H65.6348L65.7731 0.364136L90.1447 42.5787V55.7189V55.8572H90.283H103.257H103.396V55.7189V42.5787L127.767 0.364136L127.905 0.142822H127.629H112.663Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1,4 +1,5 @@
import { NymThemeProvider } from '@nymproject/mui-theme';
import { Box, Paper } from '@mui/material';
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
@@ -10,26 +11,32 @@ export const parameters = {
},
}
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Global theme for components',
defaultValue: 'light',
toolbar: {
icon: 'circlehollow',
// Array of plain string values or MenuItem shape (see below)
items: ['light', 'dark'],
// Property that specifies if the name of the item will be displayed
showName: true,
},
},
};
const withThemeProvider=(Story,context)=>{
return (
<NymThemeProvider mode={context.globals.theme}>
<Story {...context} />
</NymThemeProvider>
<div style={{ display: 'grid', height: '100%',
gridTemplateColumns: '50% 50%' }}>
<div>
<NymThemeProvider mode="light">
<Box p={4} sx={{ display: 'grid', gridTemplateRows: '80vh 2rem', background: (theme) => theme.palette.background.default, color: (theme) => theme.palette.text.primary }}>
<Box sx={{ overflowY: 'auto' }}>
<Story {...context} />
</Box>
<h4 style={{ textAlign: 'center'}}>Light mode</h4>
</Box>
</NymThemeProvider>
</div>
<div>
<NymThemeProvider mode="dark">
<Box p={4} sx={{ display: 'grid', gridTemplateRows: '80vh 2rem', background: (theme) => theme.palette.background.default, color: (theme) => theme.palette.text.primary }}>
<Box sx={{ overflowY: 'auto' }}>
<Story {...context} />
</Box>
<h4 style={{ textAlign: 'center'}}>Dark mode</h4>
</Box>
</NymThemeProvider>
</div>
</div>
)
}
export const decorators = [withThemeProvider];
+5 -4
View File
@@ -14,10 +14,8 @@
},
"devDependencies": {
"@babel/core": "^7.17.5",
"@mui/material": "^5.0.1",
"@mui/styles": "^5.0.1",
"@mui/system": "^5.0.1",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@mui/lab": "^5.0.0-alpha.72",
"@storybook/addon-actions": "^6.4.19",
"@storybook/addon-essentials": "^6.4.19",
"@storybook/addon-interactions": "^6.4.19",
@@ -27,6 +25,7 @@
"@storybook/react": "^6.4.19",
"@storybook/testing-library": "^0.0.9",
"@svgr/webpack": "^6.1.1",
"@types/flat": "^5.0.2",
"@types/react": "^17.0.39",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
@@ -58,5 +57,7 @@
"storybook": "start-storybook -p 6006",
"storybook:build": "build-storybook"
},
"dependencies": {}
"dependencies": {
"flat": "^5.0.2"
}
}
@@ -1,5 +1,9 @@
import * as React from 'react';
import Wordmark from '@assets/logo/logo-wordmark.svg';
import { useTheme } from '@mui/material';
import { LogoProps } from './LogoProps';
export const NymWordmark: React.FC<LogoProps> = ({ height, width }) => <Wordmark height={height} width={width} />;
export const NymWordmark: React.FC<LogoProps> = ({ height, width }) => {
const theme = useTheme();
return <Wordmark height={height} width={width} fill={theme.palette.text.primary} />;
};
@@ -3,6 +3,7 @@ import { PlaygroundButtons } from './buttons';
import { PlaygroundCheckboxes } from './checkboxes';
import { PlaygroundBasicSwitches } from './switches';
import { PlaygroundFonts } from './fonts';
import { PlaygroundTheme } from './theme';
export const Playground: React.FC = () => (
<>
@@ -15,6 +16,9 @@ export const Playground: React.FC = () => (
<h2>Switches</h2>
<PlaygroundBasicSwitches />
<h2>Theme</h2>
<PlaygroundTheme />
<h2>Fonts</h2>
<PlaygroundFonts />
</>
@@ -0,0 +1,21 @@
import * as React from 'react';
import { useTheme } from '@mui/material';
import { MUIThemeExplorer } from './theme/MUIThemeExplorer';
import { PaletteSwatches, PaletteSwatchesList } from './theme/PaletteSwatches';
export const PlaygroundTheme: React.FC = () => {
const theme = useTheme();
return (
<>
<h3>Palette</h3>
<PaletteSwatches theme={theme} />
<h3>Palette Explorer</h3>
<MUIThemeExplorer theme={theme} />
</>
);
};
export const PlaygroundPalette: React.FC = () => {
const theme = useTheme();
return <PaletteSwatchesList theme={theme} />;
};
@@ -0,0 +1,96 @@
import { Theme } from '@mui/material/styles';
import * as React from 'react';
import TreeView from '@mui/lab/TreeView';
import TreeItem from '@mui/lab/TreeItem';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
import { Box } from '@mui/material';
export const MUIThemeExplorer: React.FC<{
theme: Theme;
}> = ({ theme }) => (
<TreeView
defaultExpanded={['theme.palette', 'theme.palette.nym', 'theme.palette.nym.highlight']}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<div style={{ width: 24 }} />}
sx={{ height: 500, flexGrow: 1, width: '100%', overflowY: 'auto' }}
>
<MUIThemeExplorerItem theme={theme} item={theme.palette} parentKey="palette" path="theme.palette" />
</TreeView>
);
const MUIThemeExplorerItem: React.FC<{
path: string;
parentKey: string;
theme: Theme;
item: any;
isArrayItem?: boolean;
}> = ({ theme, item, parentKey, path, isArrayItem }) => {
if (!item) {
return null;
}
if (typeof item === 'string') {
return (
<TreeItem
nodeId={`${path}`}
label={
<Box sx={{ display: 'flex', alignItems: 'center', p: 0.5, pr: 0 }}>
<Box
sx={{
mr: 2,
}}
>
<svg height="25px" width="25px">
<rect width="100%" height="100%" fill={item} stroke={theme.palette.text.primary} strokeWidth="1px" />
</svg>
</Box>
{!isArrayItem && <Box mr={2}>{parentKey}</Box>}
<Box mr={2}>
<code>{item}</code>
</Box>
<Box color={theme.palette.text.disabled}>
<code>{path}</code>
</Box>
</Box>
}
/>
);
}
if (Array.isArray(item)) {
return (
<TreeItem nodeId={`${path}-array`} label={`${parentKey}[]`}>
{item.map((i, idx) => (
<MUIThemeExplorerItem
key={`${parentKey}-${idx}`}
parentKey={parentKey}
item={i}
theme={theme}
path={`${path}[${idx}]`}
isArrayItem
/>
))}
</TreeItem>
);
}
if (Object.keys(item).length) {
return (
<TreeItem nodeId={`${path}`} label={`${parentKey}`}>
{Object.keys(item).map((key) => (
<MUIThemeExplorerItem
key={`${parentKey}-${key}`}
parentKey={key}
item={item[key]}
theme={theme}
path={`${path}.${key}`}
/>
))}
</TreeItem>
);
}
return null;
};
@@ -0,0 +1,64 @@
import { Theme } from '@mui/material/styles';
import * as React from 'react';
import { Box, Grid, Typography } from '@mui/material';
import flatten from 'flat';
const SWATCH_SIZE = '40px';
export const PaletteSwatches: React.FC<{
theme: Theme;
}> = ({ theme }) => {
const swatches = React.useMemo<any>(() => flatten(theme.palette), [theme.palette]);
return (
<Grid container spacing={2}>
{Object.keys(swatches)
.filter((key) => typeof swatches[key] === 'string' && key !== 'mode')
.map((key) => (
<Grid item>
<PaletteSwatch theme={theme} path={key} value={swatches[key]} width="150px" />
</Grid>
))}
</Grid>
);
};
export const PaletteSwatchesList: React.FC<{
theme: Theme;
}> = ({ theme }) => {
const swatches = React.useMemo<any>(() => flatten(theme.palette), [theme.palette]);
return (
<>
{Object.keys(swatches)
.filter((key) => typeof swatches[key] === 'string' && key !== 'mode')
.map((key) => (
<Box display="flex" alignItems="center" p={1}>
<PaletteSwatch theme={theme} path={key} value={swatches[key]} />
</Box>
))}
</>
);
};
const PaletteSwatch: React.FC<{
theme: Theme;
path: string;
value: string;
width?: string;
}> = ({ theme, path, value, width }) => (
<>
<Box
sx={{
mr: 2,
height: SWATCH_SIZE,
width: SWATCH_SIZE,
background: value,
border: `1px solid ${theme.palette.text.primary}`,
}}
/>
<Box>
<Typography minWidth={width} maxWidth={width} fontFamily="monospace" overflow="scroll" fontSize="12px">
{path}
</Typography>
</Box>
</>
);
@@ -1,6 +1,5 @@
import * as React from 'react';
import { ComponentMeta } from '@storybook/react';
import { Box } from '@mui/material';
import { NymLogo, NymWordmark } from '../components';
export default {
@@ -13,9 +12,5 @@ export function Logo() {
}
export function Wordmark() {
return (
<div style={{ background: '#888', padding: '2rem' }}>
<NymWordmark height={250} />
</div>
);
return <NymWordmark height={250} />;
}
@@ -1,25 +1,24 @@
import * as React from 'react';
import { ComponentMeta } from '@storybook/react';
import { NymThemeProvider } from '@nymproject/mui-theme';
import { useTheme } from '@mui/material';
import { Playground } from '../playground';
import { PlaygroundPalette } from '../playground/theme';
import { MUIThemeExplorer } from '../playground/theme/MUIThemeExplorer';
export default {
title: 'Playground',
component: Playground,
} as ComponentMeta<typeof Playground>;
export function LightMode() {
return (
<NymThemeProvider mode="light">
<Playground />
</NymThemeProvider>
);
export function AllControls() {
return <Playground />;
}
export function DarkMode() {
return (
<NymThemeProvider mode="dark">
<Playground />
</NymThemeProvider>
);
export function Palette() {
return <PlaygroundPalette />;
}
export function ThemeExplorer() {
const theme = useTheme();
return <MUIThemeExplorer theme={theme} />;
}
+90 -1
View File
@@ -1144,6 +1144,39 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
"@date-io/core@^2.13.1":
version "2.13.1"
resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.13.1.tgz#f041765aff5c55fbc7e37fdd75fc1792733426d6"
integrity sha512-pVI9nfkf2qClb2Cxdq0Q4zJhdawMG4ybWZUVGifT78FDwzRMX2SwXBb55s5NRJk0HcIicDuxktmCtemZqMH1Zg==
"@date-io/date-fns@^2.13.1":
version "2.13.1"
resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.13.1.tgz#19d8a245dab61c03c95ba492d679d98d2b0b4af5"
integrity sha512-8fmfwjiLMpFLD+t4NBwDx0eblWnNcgt4NgfT/uiiQTGI81fnPu9tpBMYdAcuWxaV7LLpXgzLBx1SYWAMDVUDQQ==
dependencies:
"@date-io/core" "^2.13.1"
"@date-io/dayjs@^2.13.1":
version "2.13.1"
resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.13.1.tgz#98461d22ee98179b9f2dca3b36f1b618704ae593"
integrity sha512-5bL4WWWmlI4uGZVScANhHJV7Mjp93ec2gNeUHDqqLaMZhp51S0NgD25oqj/k0LqBn1cdU2MvzNpk/ObMmVv5cQ==
dependencies:
"@date-io/core" "^2.13.1"
"@date-io/luxon@^2.13.1":
version "2.13.1"
resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.13.1.tgz#3701b3cabfffda5102af302979aa6e58acfda91a"
integrity sha512-yG+uM7lXfwLyKKEwjvP8oZ7qblpmfl9gxQYae55ifbwiTs0CoCTkYkxEaQHGkYtTqGTzLqcb0O9Pzx6vgWg+yg==
dependencies:
"@date-io/core" "^2.13.1"
"@date-io/moment@^2.13.1":
version "2.13.1"
resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.13.1.tgz#122a51e4bdedf71ff3babb264427737dc022c1e6"
integrity sha512-XX1X/Tlvl3TdqQy2j0ZUtEJV6Rl8tOyc5WOS3ki52He28Uzme4Ro/JuPWTMBDH63weSWIZDlbR7zBgp3ZA2y1A==
dependencies:
"@date-io/core" "^2.13.1"
"@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3":
version "0.5.6"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f"
@@ -2643,6 +2676,19 @@
prop-types "^15.7.2"
react-is "^17.0.2"
"@mui/base@5.0.0-alpha.71":
version "5.0.0-alpha.71"
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.71.tgz#628f5ae10a8c015d61d3d1e6f04d66afc7500b90"
integrity sha512-LinacyjmZOS+roUqCyhrcbNIW7TlRf1U+15ETGwMn6biNXI9YEVgcc1Kak08CRtjM0yczxxzLWetiAjHMCVSjQ==
dependencies:
"@babel/runtime" "^7.17.2"
"@emotion/is-prop-valid" "^1.1.2"
"@mui/utils" "^5.4.4"
"@popperjs/core" "^2.11.2"
clsx "^1.1.1"
prop-types "^15.7.2"
react-is "^17.0.2"
"@mui/icons-material@^5.2.0":
version "5.4.4"
resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.4.4.tgz#0dc7b4e68cbbdfc675f09f0763be1100aad910af"
@@ -2650,6 +2696,25 @@
dependencies:
"@babel/runtime" "^7.17.2"
"@mui/lab@^5.0.0-alpha.72":
version "5.0.0-alpha.72"
resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.72.tgz#e784875bea3476be3437fc79dbee9c5b1e74535a"
integrity sha512-opml6yNpDvJzrCM9XzbckZMtfah+jFrYB8nB6kzORaQ3ixcMt+7RbFTPXG7NvQxW8VdxlGgfeBAMSWLDiFVMWA==
dependencies:
"@babel/runtime" "^7.17.2"
"@date-io/date-fns" "^2.13.1"
"@date-io/dayjs" "^2.13.1"
"@date-io/luxon" "^2.13.1"
"@date-io/moment" "^2.13.1"
"@mui/base" "5.0.0-alpha.71"
"@mui/system" "^5.5.0"
"@mui/utils" "^5.4.4"
clsx "^1.1.1"
prop-types "^15.7.2"
react-is "^17.0.2"
react-transition-group "^4.4.2"
rifm "^0.12.1"
"@mui/material@^5.0.1", "@mui/material@^5.2.2":
version "5.4.4"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.4.4.tgz#2652a07085bf107da590007286336640f605055e"
@@ -2723,6 +2788,20 @@
csstype "^3.0.10"
prop-types "^15.7.2"
"@mui/system@^5.5.0":
version "5.5.0"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.5.0.tgz#df7e540b12218db21a5edb16a6fa1d571d26455b"
integrity sha512-zFOfERv3Y4m5ehwTRR9cGaPuMvlD2qVXmFKC60P0Gte3aD6vYObyNriZv+mDVGlhDxZTZhxBrNPH3ns25xSFtQ==
dependencies:
"@babel/runtime" "^7.17.2"
"@mui/private-theming" "^5.4.4"
"@mui/styled-engine" "^5.4.4"
"@mui/types" "^7.1.2"
"@mui/utils" "^5.4.4"
clsx "^1.1.1"
csstype "^3.0.11"
prop-types "^15.7.2"
"@mui/types@^7.1.2":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.1.2.tgz#4f3678ae77a7a3efab73b6e040469cc6df2144ac"
@@ -2951,7 +3030,7 @@
schema-utils "^3.0.0"
source-map "^0.7.3"
"@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0":
"@popperjs/core@^2.11.2", "@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0":
version "2.11.2"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9"
integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==
@@ -7321,6 +7400,11 @@ csstype@^3.0.10, csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==
csstype@^3.0.11:
version "3.0.11"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
cyclist@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@@ -14814,6 +14898,11 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rifm@^0.12.1:
version "0.12.1"
resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.12.1.tgz#8fa77f45b7f1cda2a0068787ac821f0593967ac4"
integrity sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==
rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"