Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
4f20314
Add lite version SCSS for deprecations and expose font face and link …
codecaaron Mar 15, 2021
646ed5d
helmet workaround
codecaaron Mar 15, 2021
eb8e0f2
Split into prefetch and preload
codecaaron Mar 15, 2021
a833f80
Merge branch 'main' into ar-static-cms-fonts
codecaaron Mar 15, 2021
a50f688
Reorganize to single provider
codecaaron Mar 16, 2021
1213286
Merge branch 'ar-static-cms-fonts' of github.com:Codecademy/client-mo…
codecaaron Mar 16, 2021
8216de4
use lite entry point
codecaaron Mar 16, 2021
202e3c8
turn off preload for tests
codecaaron Mar 16, 2021
5b598fc
Make globals opt out
codecaaron Mar 16, 2021
6e71623
export props
codecaaron Mar 16, 2021
761c872
Export theme
codecaaron Mar 16, 2021
620c745
Fix stuff
codecaaron Mar 16, 2021
782b4c9
Decorator
codecaaron Mar 16, 2021
098938a
Fix tests
codecaaron Mar 16, 2021
ac25cfa
Styles yo
codecaaron Mar 16, 2021
e0b25cb
Sweet
codecaaron Mar 16, 2021
166bb28
Peer dep and reboot
codecaaron Mar 16, 2021
99e6f64
Add reboot for real
codecaaron Mar 16, 2021
2e664e8
Resets
codecaaron Mar 16, 2021
ebf33e2
No helmet and remove lite as a concept
codecaaron Mar 17, 2021
738794e
lazy load helmet if configured
codecaaron Mar 17, 2021
c085cec
Correct import
codecaaron Mar 17, 2021
1bcca36
imports again...
codecaaron Mar 17, 2021
529d760
Reorganize again
codecaaron Mar 17, 2021
ad1ee25
Keep AssetProvider separate :(
codecaaron Mar 17, 2021
9515134
Change?
codecaaron Mar 17, 2021
fd2f70b
add helmet to Page
codecaaron Mar 17, 2021
083b58a
Merge branch 'main' into ar-static-cms-fonts
codecaaron Mar 17, 2021
6112faa
No cache no globals
codecaaron Mar 17, 2021
36df7d0
Merge branch 'ar-static-cms-fonts' of github.com:Codecademy/client-mo…
codecaaron Mar 17, 2021
aba11e0
Everything preload
codecaaron Mar 17, 2021
896feaa
Format comments
codecaaron Mar 17, 2021
50a132d
Upadte readmes
codecaaron Mar 17, 2021
f0c148b
Keep it in reboot
codecaaron Mar 17, 2021
1dbfa28
Fix format
codecaaron Mar 17, 2021
08d8eb8
consistent font-faces
codecaaron Mar 17, 2021
d4d3ef7
Merge branch 'main' into ar-static-cms-fonts
codecaaron Mar 20, 2021
8641a08
Only provision things if needed
codecaaron Mar 20, 2021
5635d3a
Create color mode utility
codecaaron Mar 20, 2021
674dbfe
Same set
codecaaron Mar 20, 2021
a8ab04e
Wreck it
codecaaron Mar 20, 2021
aaaaf71
Remove mode from Anchors
codecaaron Mar 20, 2021
864d0fd
Bump Versions
codecaaron Mar 20, 2021
2b00590
Storybook why?
codecaaron Mar 20, 2021
a66349d
Src
codecaaron Mar 20, 2021
89c445d
ignore rule
codecaaron Mar 20, 2021
3b1c0de
Add a bit of space
codecaaron Mar 20, 2021
857a6cb
Add Background
codecaaron Mar 21, 2021
7f4b385
Better naming
codecaaron Mar 21, 2021
891d7cd
Remove unused
codecaaron Mar 21, 2021
1a2ceaa
Boom
codecaaron Mar 21, 2021
1d5a469
Examples
codecaaron Mar 21, 2021
2d7f47d
P
codecaaron Mar 21, 2021
e553680
Reorganize and add docs
codecaaron Mar 22, 2021
71e45a4
Rename
codecaaron Mar 22, 2021
48fd6fc
Snapshot
codecaaron Mar 22, 2021
1bdda5f
Update for single provisioning
codecaaron Mar 22, 2021
c19d1b3
Merge branch 'ar-static-cms-fonts' of github.com:Codecademy/client-mo…
codecaaron Mar 22, 2021
69dcc59
Use only real colors
codecaaron Mar 22, 2021
3cf6537
Fix
codecaaron Mar 22, 2021
63dbea6
Just use key as prefix
codecaaron Mar 23, 2021
bf26533
Fix the method
codecaaron Mar 23, 2021
42475a0
Use the real name
codecaaron Mar 23, 2021
4f81134
Add background tests
codecaaron Mar 25, 2021
ee6e8ef
Update descriptions and calculation
codecaaron Mar 25, 2021
14b148f
Add message
codecaaron Mar 25, 2021
a8d76f2
Merge branch 'main' into ar-color-mode-v1
codecaaron Mar 25, 2021
9e0bddf
Switch to variable provision reset
codecaaron Mar 25, 2021
99bf4c9
Add color back to reboot
codecaaron Mar 25, 2021
3325e88
Merge branch 'ar-color-mode-v1' of github.com:Codecademy/client-modul…
codecaaron Mar 25, 2021
fe244c2
Link for colormodes
codecaaron Mar 25, 2021
49d2e92
Removes gamut version
codecaaron Mar 25, 2021
3e4b61b
Merge branch 'main' into ar-color-mode-v1
codecaaron Mar 25, 2021
b8d74b7
remove root usage for now
codecaaron Mar 26, 2021
2ac57e4
Merge branch 'ar-color-mode-v1' of github.com:Codecademy/client-modul…
codecaaron Mar 26, 2021
bb16a21
Remove colors.primary usage
codecaaron Mar 26, 2021
1cb504a
Allow setting of default mode
codecaaron Mar 26, 2021
a6cda2a
Merge branch 'main' into ar-color-mode-v1
codecaaron Mar 27, 2021
b3cd831
Fix Gamut Provider
codecaaron Mar 27, 2021
082f38c
Make color modes extendable
codecaaron Mar 28, 2021
0cd999e
Merge conflicts
codecaaron Mar 30, 2021
64b43ee
Merge branch 'main' into ar-color-mode-v1
codecaaron Mar 31, 2021
35699c3
Update tests
codecaaron Mar 31, 2021
4f01ab6
Merge branch 'ar-color-mode-v1' of github.com:Codecademy/client-modul…
codecaaron Mar 31, 2021
ae03696
Merge branch 'main' of github.com:Codecademy/client-modules into ar-c…
codecaaron Apr 1, 2021
45619e2
Fix test
codecaaron Apr 1, 2021
c7ba72b
Add Mode Switcher
codecaaron Apr 2, 2021
1ab1299
Add Params
codecaaron Apr 2, 2021
cfe3bf7
Remove breaking changes
codecaaron Apr 5, 2021
b8a279a
Update docs
codecaaron Apr 5, 2021
d91fd98
Update Color Modes
codecaaron Apr 5, 2021
b2b58ff
Fix links
codecaaron Apr 5, 2021
cf5838e
remove badge component
codecaaron Apr 5, 2021
9454360
correct ordering
codecaaron Apr 5, 2021
c0f540e
Pull in changes
codecaaron Apr 6, 2021
2944928
add shadow colors to modes
codecaaron Apr 6, 2021
88a8a15
Merge branch 'main' into ar-color-mode-v1
codecaaron Apr 8, 2021
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: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
"@babel/core": "7.13.10",
"@babel/preset-typescript": "^7.13.0",
"@emotion/babel-plugin": "^11.1.2",
"@emotion/react": "^11.1.4",
"@emotion/styled": "^11.0.0",
"@emotion/react": "^11.1.5",
"@emotion/styled": "^11.1.5",
"@testing-library/jest-dom": "^5.7.0",
"@testing-library/react": "^11.0.4",
"@testing-library/react-hooks": "^5.1.0",
Expand Down
12 changes: 7 additions & 5 deletions packages/gamut-styles/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@
"@codecademy/variance": "^0.6.0"
},
"peerDependencies": {
"@emotion/react": "^11.1.4",
"@emotion/styled": "^11.0.0",
"@emotion/react": "^11.15",
"@emotion/styled": "^11.1.5",
"react-helmet": "^6.1.0"
},
"devDependencies": {
"@emotion/react": "^11.1.4",
"@emotion/styled": "^11.0.0",
"@types/react-helmet": "^6.1.0"
"@emotion/react": "^11.1.5",
"@emotion/styled": "^11.1.5",
"@emotion/jest": "11.2.1",
"@types/react-helmet": "^6.1.0",
"component-test-setup": "^0.1.1"
},
"license": "MIT",
"publishConfig": {
Expand Down
29 changes: 12 additions & 17 deletions packages/gamut-styles/src/AssetProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,19 @@ import { Helmet } from 'react-helmet';

import { webFonts } from './remoteAssets/fonts';

export const createFontLinks = () => {
const links: React.ReactNode[] = [];
webFonts.forEach(({ filePath, extensions }) =>
extensions.forEach((ext) =>
links.push(
<link
key={`${filePath}-${ext}`}
rel="preload"
href={`${filePath}.${ext}`}
crossOrigin="anonymous"
as="font"
type={`font/${ext}`}
/>
)
)
export const createFontLinks = () =>
webFonts.flatMap(({ filePath, extensions }) =>
extensions.map((ext) => (
<link
key={`${filePath}-${ext}`}
rel="preload"
href={`${filePath}.${ext}`}
crossOrigin="anonymous"
as="font"
type={`font/${ext}`}
/>
))
);
return links;
};

export const AssetProvider = () => {
return <Helmet>{createFontLinks()}</Helmet>;
Expand Down
67 changes: 67 additions & 0 deletions packages/gamut-styles/src/Background.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { getContrast, meetsContrastGuidelines } from 'polished';
import React, { useMemo } from 'react';

import { ColorMode } from './ColorMode';
import { properties } from './props';
import { colors } from './variables';

const Reset = styled.div(properties.backgroundColor);

export type BackgroundProps = {
initialBackground: keyof typeof colors;
className?: string;
};

export const Background: React.FC<BackgroundProps> = ({
children,
className,
initialBackground,
}) => {
const {
colorModes: { active, modes },
} = useTheme();
const accessibleMode = useMemo(() => {
const { light, dark } = modes;

const lightModeContrast = getContrast(
light.text,
colors[initialBackground]
);
const darkModeContrast = getContrast(dark.text, colors[initialBackground]);

// Minimum Contrast Requirement is 4.5 for AA (this will not be a perfect metric since there are multiple standards but should meet most of our needs)
const highestContrastMode =
lightModeContrast > darkModeContrast ? 'light' : 'dark';
const { AA } = meetsContrastGuidelines(
modes[highestContrastMode].text,
colors[initialBackground]
);
if (!AA) {
// eslint-disable-next-line no-console
console.warn(
`You are using an inaccessible background color ${initialBackground} (${colors[initialBackground]}) for color contrast`
);
}
return highestContrastMode;
}, [initialBackground, modes]);

if (accessibleMode === active) {
return (
<Reset className={className} backgroundColor={initialBackground}>
{children}
</Reset>
);
}

return (
<ColorMode
className={className}
mode={accessibleMode}
initialBackground={initialBackground}
>
{children}
</ColorMode>
);
};
47 changes: 47 additions & 0 deletions packages/gamut-styles/src/ColorMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { compose, HandlerProps } from '@codecademy/gamut-system';
import { Theme, ThemeProvider, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import React from 'react';

import { properties } from './props';
import { createVariables } from './utilities';
import { colors } from './variables';

export type ColorModeProps = {
mode: keyof Theme['colorModes']['modes'];
initialBackground?: keyof typeof colors;
className?: string;
};

const colorProps = compose(properties.backgroundColor, properties.textColor);

export interface VariableProviderProps extends HandlerProps<typeof colorProps> {
variables: Parameters<typeof createVariables>[0];
}

export const VariableProvider = styled.div<VariableProviderProps>(
compose(properties.backgroundColor, properties.textColor),
({ variables }) => createVariables(variables, 'colors')
);

export const ColorMode: React.FC<ColorModeProps> = ({
mode,
initialBackground,
children,
className,
}) => {
const { colorModes } = useTheme();

return (
<ThemeProvider theme={{ colorModes: { ...colorModes, active: mode } }}>
<VariableProvider
variables={colorModes.modes[mode]}
backgroundColor={initialBackground}
textColor="text"
className={className}
>
{children}
</VariableProvider>
</ThemeProvider>
);
};
25 changes: 21 additions & 4 deletions packages/gamut-styles/src/GamutProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import {
CacheProvider,
css,
CSSObject,
EmotionCache,
Global,
Theme,
ThemeProvider,
} from '@emotion/react';
import React, { useContext, useRef } from 'react';
import React, { useContext, useMemo, useRef } from 'react';

import { createEmotionCache } from './cache';
import { Reboot, Typography } from './globals';
import { theme, themeCssVariables } from './theme';
import { createVariables } from './utilities';

export interface GamutProviderProps {
useGlobals?: boolean;
useCache?: boolean;
mode?: keyof Theme['colorModes']['modes'];
cache?: EmotionCache;
}

Expand All @@ -27,12 +31,25 @@ GamutContext.displayName = 'GamutContext';
export const GamutProvider: React.FC<GamutProviderProps> = ({
children,
cache,
mode = 'light',
useGlobals = true,
useCache = true,
}) => {
const { hasGlobals, hasCache } = useContext(GamutContext);
const shouldCreateCache = useCache && !hasCache;
const shouldInsertGlobals = useGlobals && !hasGlobals;
const rootVariables = useMemo(() => {
const vars: CSSObject = {
...themeCssVariables,
...createVariables(theme.colorModes.modes[mode], 'colors'),
};
return vars;
}, [mode]);

const rootTheme = useMemo(
() => ({ ...theme, colorModes: { ...theme.colorModes, active: mode } }),
[mode]
);

// Do not initialize a new cache if one has been provided as props
const activeCache = useRef<EmotionCache | false>(
Expand All @@ -43,7 +60,7 @@ export const GamutProvider: React.FC<GamutProviderProps> = ({
<>
<Typography />
<Reboot />
<Global styles={css({ ':root': themeCssVariables })} />
<Global styles={css({ ':root': rootVariables })} />
</>
);

Expand All @@ -57,7 +74,7 @@ export const GamutProvider: React.FC<GamutProviderProps> = ({
>
<CacheProvider value={activeCache.current}>
{globals}
<ThemeProvider theme={theme}>{children}</ThemeProvider>
<ThemeProvider theme={rootTheme}>{children}</ThemeProvider>
</CacheProvider>
</GamutContext.Provider>
);
Expand All @@ -71,7 +88,7 @@ export const GamutProvider: React.FC<GamutProviderProps> = ({
}}
>
{globals}
<ThemeProvider theme={theme}>{children}</ThemeProvider>
<ThemeProvider theme={rootTheme}>{children}</ThemeProvider>
</GamutContext.Provider>
);
};
105 changes: 105 additions & 0 deletions packages/gamut-styles/src/__tests__/Background-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { matchers } from '@emotion/jest';
import { ThemeProvider, useTheme } from '@emotion/react';
import { setupRtl as setupRtlBase } from 'component-test-setup';
import { overArgs } from 'lodash';
import React from 'react';

import { Background } from '../Background';
import { theme } from '../theme';

expect.extend(matchers);

function withThemeProvider<Props>(
WrappedComponent: React.ComponentType<Props>
) {
const WithBoundaryComponent: React.FC<Props> = (props) => (
<ThemeProvider theme={theme}>
<WrappedComponent {...props} />
</ThemeProvider>
);

return WithBoundaryComponent;
}

const setupRtl = overArgs(
setupRtlBase,
withThemeProvider
) as typeof setupRtlBase;

const renderView = setupRtl(Background, {
children: <div data-testid="content" />,
});

const ActiveMode = () => {
const {
colorModes: { active },
} = useTheme();
return <div>{active}</div>;
};

describe('Background', () => {
it('switches the default colormode when contrast standards are not met', () => {
const { view } = renderView({ initialBackground: 'navy' });
expect(view.getByTestId('content').parentElement).toHaveStyleRule(
'background-color',
theme.colors.navy
);
});

it('allows for changing the color mode while nested', () => {
const { view } = renderView({
initialBackground: 'navy',
children: (
<div data-testid="content">
<Background initialBackground="beige">
<div data-testid="nested-content" />
</Background>
</div>
),
});
expect(view.getByTestId('content').parentElement).toHaveStyleRule(
'background-color',
theme.colors.navy
);

expect(view.getByTestId('nested-content').parentElement).toHaveStyleRule(
'background-color',
theme.colors.beige
);

/** text color reset should be on the variable provisioner if needed */
expect(view.getByTestId('nested-content').parentElement).toHaveStyleRule(
'color',
theme.colors.text
);
});

it('does not change the color mode when contrasts do not conflict', () => {
const { view } = renderView({
initialBackground: 'white',
});

// Grand parent
expect(
view.getByTestId('content').parentElement?.parentElement
).not.toHaveStyleRule('color', theme.colors.text);
});

it('updates the theme context to the current mode', () => {
const { view } = renderView({
initialBackground: 'navy',
children: <ActiveMode />,
});

view.getByText('dark');
});

it('does not update the theme context when the color mode has not changed', () => {
const { view } = renderView({
initialBackground: 'white',
children: <ActiveMode />,
});

view.getByText('light');
});
});
2 changes: 2 additions & 0 deletions packages/gamut-styles/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import '@emotion/react';
import { theme } from './theme';

export * from './GamutProvider';
export * from './ColorMode';
export * from './Background';

export * from './cache';
export * from './variables';
Expand Down
Loading