Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] Emotion Theming #382

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-shadow": "error",
"@typescript-eslint/no-use-before-define": "error",
"arrow-parens": "off",
"no-shadow": "off",
"no-use-before-define": "off",
"react/jsx-filename-extension": ["warn", { "extensions": [".js", ".tsx"] }],
Expand All @@ -56,7 +57,8 @@
"emotion/jsx-import": "error",
"emotion/no-vanilla": "error",
"emotion/import-from-emotion": "error",
"emotion/styled-import": "error"
"emotion/styled-import": "error",
"react/jsx-props-no-spreading": "off"
}
},
{
Expand Down
135 changes: 75 additions & 60 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,89 @@
import { useState } from 'react';
import { addDecorator, addParameters, configure } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';
import { addReadme, configureReadme } from 'storybook-readme';
import centered from '@storybook/addon-centered/react';
import { Global, css } from '@emotion/core';
import { ThemeProvider } from 'emotion-theming';
import Theme from './theme';
import {
resetStyles,
brandStyles,
} from '../src/utils/injectGlobalStyles/style';
import { primaryTheme, secondaryTheme } from '../src/constants/themes';

const InjectGlobalStyles = (storyFn) => (
<div
css={css`
padding: 1rem;
`}
>
<Global styles={resetStyles} />
<Global styles={brandStyles} />
<Global
styles={css`
@font-face {
font-family: 'nocturno';
src: url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.eot');
src: url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.eot?#iefix')
format('embedded-opentype'),
url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.woff2')
format('woff2'),
url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.woff')
format('woff'),
url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.svg#Typotheque_webfonts_service')
format('svg');
}
`}
/>
<Global
styles={css`
@font-face {
font-family: 'larssiet';
src: url('https://assets.curology.com/fonts/larssiet/34535B_1_0.eot');
src: url('https://assets.curology.com/fonts/larssiet/34535B_1_0.eot?#iefix')
format('embedded-opentype'),
url('https://assets.curology.com/fonts/larssiet/34535B_1_0.woff2')
format('woff2'),
url('https://assets.curology.com/fonts/larssiet/34535B_1_0.woff')
format('woff'),
url('https://assets.curology.com/fonts/larssiet/34535B_1_0.ttf')
format('truetype');
}
`}
/>
<Global
styles={css`
@font-face {
font-family: 'larssiet';
font-weight: bold;
src: url('https://assets.curology.com/fonts/larssiet/34535B_0_0.eot');
src: url('https://assets.curology.com/fonts/larssiet/34535B_0_0.eot?#iefix')
format('embedded-opentype'),
url('https://assets.curology.com/fonts/larssiet/34535B_0_0.woff2')
format('woff2'),
url('https://assets.curology.com/fonts/larssiet/34535B_0_0.woff')
format('woff'),
url('https://assets.curology.com/fonts/larssiet/34535B_0_0.ttf')
format('truetype');
}
const InjectGlobalStyles = (storyFn) => {
const [theme, setTheme] = useState(primaryTheme);

const toggleTheme = () =>
theme.__type === 'primary'
? setTheme(secondaryTheme)
: setTheme(primaryTheme);

return (
<div
css={css`
padding: 1rem;
`}
/>
{storyFn()}
</div>
);
>
<Global styles={resetStyles} />
<Global styles={brandStyles} />
<Global
styles={css`
@font-face {
font-family: 'nocturno';
src: url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.eot');
src: url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.eot?#iefix')
format('embedded-opentype'),
url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.woff2')
format('woff2'),
url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.woff')
format('woff'),
url('https://s3-us-west-1.amazonaws.com/fonts-california.typotheque.com/WF-029669-009918-001560-fa6dd062b0c32d6d9a297bd175bb0381.svg#Typotheque_webfonts_service')
format('svg');
}
`}
/>
<Global
styles={css`
@font-face {
font-family: 'larssiet';
src: url('https://assets.curology.com/fonts/larssiet/34535B_1_0.eot');
src: url('https://assets.curology.com/fonts/larssiet/34535B_1_0.eot?#iefix')
format('embedded-opentype'),
url('https://assets.curology.com/fonts/larssiet/34535B_1_0.woff2')
format('woff2'),
url('https://assets.curology.com/fonts/larssiet/34535B_1_0.woff')
format('woff'),
url('https://assets.curology.com/fonts/larssiet/34535B_1_0.ttf')
format('truetype');
}
`}
/>
<Global
styles={css`
@font-face {
font-family: 'larssiet';
font-weight: bold;
src: url('https://assets.curology.com/fonts/larssiet/34535B_0_0.eot');
src: url('https://assets.curology.com/fonts/larssiet/34535B_0_0.eot?#iefix')
format('embedded-opentype'),
url('https://assets.curology.com/fonts/larssiet/34535B_0_0.woff2')
format('woff2'),
url('https://assets.curology.com/fonts/larssiet/34535B_0_0.woff')
format('woff'),
url('https://assets.curology.com/fonts/larssiet/34535B_0_0.ttf')
format('truetype');
}
`}
/>
<ThemeProvider theme={theme}>
<button onClick={toggleTheme}>Swap Theme</button>
{storyFn()}
</ThemeProvider>
</div>
);
};

addDecorator(InjectGlobalStyles);
addDecorator(centered);
Expand Down Expand Up @@ -105,7 +120,7 @@ addParameters({
},
});

const req = require.context('../stories', true, /.(ts|tsx|js)$/);
const req = require.context('../stories/toggle', true, /.(ts|tsx|js)$/);
function loadStories() {
req.keys().forEach(req);
}
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@
"yarn-run-all": "^3.1.1"
},
"dependencies": {
"@emotion/core": "^10.0.35",
"@emotion/styled": "^10.0.27",
"@emotion/core": "10.0.35",
"@emotion/styled": "10.0.27",
"@react-aria/focus": "^3.0.2",
"emotion-theming": "10.0.27",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to update our Usage documentation to note that all applications using radiance-ui need to set up a ThemeProvider at the top level of their App--or at least at the highest-level that makes use of radiance-ui components: https://emotion.sh/docs/theming

"lodash.round": "^4.0.4",
"lodash.throttle": "^4.1.1",
"lodash.uniqueid": "^4.0.1",
Expand All @@ -146,6 +147,7 @@
"peerDependencies": {
"@emotion/core": "10.0.35",
"@emotion/styled": "10.0.27",
"emotion-theming": "10.0.27",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've run into compatibility issues in the past in applications that use our library if there's an @emotion version mismatch, see #323. Basically, styles don't always apply as expected, which resulted in (mostly) padding/alignment issues.

It's higher maintenance to handle it this way but I think it is worth the small cost.

"react": "^16.13.1",
"react-dom": "^16.13.1"
},
Expand Down
60 changes: 60 additions & 0 deletions src/constants/colors/primary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import PropTypes from 'prop-types';

import COLORS from '.';

const PRIMARY_COLORS = {
// brand colors
primary: COLORS.purple100,
primaryTint1: COLORS.purple85,
primaryTint2: COLORS.purple70,
primaryTint3: COLORS.purple30,
secondary: COLORS.lavender100,
tertiary: COLORS.purple4,

// general colors
success: COLORS.statusGreen,
successBackground: COLORS.statusGreenBackground,
successBorder: COLORS.statusGreenBorder,
info: COLORS.statusPurple,
infoBackground: COLORS.statusPurpleBackground,
infoBorder: COLORS.statusPurpleBorder,
error: COLORS.statusRed,
errorBackground: COLORS.statusRedBackground,
errorBorder: COLORS.statusRedBorder,
default: COLORS.purple70,
defaultBackground: COLORS.purple10,
defaultBorder: COLORS.purple15,
accent: COLORS.red,
disabled: COLORS.purple10,
failure: COLORS.red,
hover: COLORS.purple4,
warning: COLORS.yellowLight,

// ui colors
background: COLORS.purple4,
backgroundDark: COLORS.purple4,
border: COLORS.purple10,
divider: COLORS.purple10,

// form colors
radioBorder: COLORS.purple30,
radioBorderSelected: COLORS.lavender100,

// typography
textMuted: COLORS.purple70,
textGhost: COLORS.purple30,
textDisabled: COLORS.purple30,

// overlay
overlay: 'rgba(45, 45, 48, 0.7)',
overlaySolid: 'rgba(45, 45, 48, 1)',

black: COLORS.black,
white: COLORS.white,
};

export const PRIMARY_COLORS_PROP_TYPES = PropTypes.oneOf(
Object.values(PRIMARY_COLORS),
);

export default PRIMARY_COLORS;
60 changes: 60 additions & 0 deletions src/constants/colors/secondary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import PropTypes from 'prop-types';

import { COLORS } from '..';

const SECONDARY_COLORS = {
// brand colors
primary: null,
primaryTint1: '#000000',
primaryTint2: null,
primaryTint3: '#cccccc',
secondary: '#414a4c',
tertiary: null,

// general colors
success: null,
successBackground: null,
successBorder: null,
info: null,
infoBackground: null,
infoBorder: null,
error: null,
errorBackground: null,
errorBorder: null,
default: null,
defaultBackground: null,
defaultBorder: null,
accent: null,
disabled: null,
failure: null,
hover: null,
warning: null,

// ui colors
background: null,
backgroundDark: null,
border: null,
divider: null,

// form colors
radioBorder: null,
radioBorderSelected: null,

// typography
textMuted: null,
textGhost: null,
textDisabled: null,

// overlay
overlay: null,
overlaySolid: null,

black: COLORS.black,
white: COLORS.white,
};

export const SECONDARY_COLORS_PROP_TYPES = PropTypes.oneOf(
Object.values(SECONDARY_COLORS),
);

export default SECONDARY_COLORS;
10 changes: 10 additions & 0 deletions src/constants/colors/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import PRIMARY_COLORS from './primary';
import SECONDARY_COLORS from './secondary';

describe('theme colors', () => {
it('primary and secondary colors have the same number of properties', () => {
expect(Object.keys(PRIMARY_COLORS).length).toEqual(
Object.keys(SECONDARY_COLORS).length,
);
});
});
2 changes: 2 additions & 0 deletions src/constants/themes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as primaryTheme } from './primary';
export { default as secondaryTheme } from './secondary';
7 changes: 7 additions & 0 deletions src/constants/themes/primary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import PRIMARY_COLORS from '../colors/primary';

export default {
__type: 'primary',
BOX_SHADOW: {},
COLORS: PRIMARY_COLORS,
} as const;
7 changes: 7 additions & 0 deletions src/constants/themes/secondary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import SECONDARY_COLORS from '../colors/secondary';

export default {
__type: 'secondary',
BOX_SHADOW: {},
COLORS: SECONDARY_COLORS,
} as const;
14 changes: 14 additions & 0 deletions src/constants/themes/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import primaryTheme from './primary';
import secondaryTheme from './secondary';

type BoxShadow =
| typeof primaryTheme['BOX_SHADOW']
| typeof secondaryTheme['BOX_SHADOW'];

type Colors = typeof primaryTheme['COLORS'] | typeof secondaryTheme['COLORS'];

export type ThemeType = {
__type: 'primary' | 'secondary';
BOX_SHADOW: BoxShadow;
COLORS: Colors;
};
Loading