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

[system] Introduce mode to CssVarsProvider #29418

Merged
merged 40 commits into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4e5f739
add useTheme to createStyled
siriwatknp Oct 16, 2021
ef44ca1
add default theme to Joy
siriwatknp Oct 19, 2021
fc8a3e4
update tsconfig to include mui-system
siriwatknp Oct 19, 2021
fa484be
add ThemeProvider test
siriwatknp Oct 20, 2021
ae8d466
Revert "add useTheme to createStyled"
siriwatknp Oct 20, 2021
ddc35f9
Revert "Revert "add useTheme to createStyled""
siriwatknp Oct 20, 2021
5b54132
add Partial to style matchers
siriwatknp Oct 20, 2021
7c75d62
add tests
siriwatknp Oct 20, 2021
06f336a
add more tests
siriwatknp Oct 20, 2021
96c7a17
rename types
siriwatknp Oct 20, 2021
d1c45af
refactor to vars
siriwatknp Oct 20, 2021
a83d6c7
add tests for createStyled
siriwatknp Oct 20, 2021
1f1a4eb
remove unused colors
siriwatknp Oct 20, 2021
b7cf8dc
rename test
siriwatknp Oct 20, 2021
a5d654a
fix types augmentation
siriwatknp Oct 20, 2021
ef574b4
fix tests
siriwatknp Oct 20, 2021
3745b44
use initial tokens
siriwatknp Oct 22, 2021
105c6c8
revert createStyled
siriwatknp Oct 26, 2021
007121a
use ThemeContext from styled-engine
siriwatknp Oct 26, 2021
38559bc
Merge branch 'master' into joy/css-vars-provider
siriwatknp Oct 28, 2021
d9b3334
Merge branch 'master' of https://github.com/mui-org/material-ui into …
siriwatknp Oct 29, 2021
275e217
use system ThemeProvider and shared context
siriwatknp Oct 29, 2021
887125b
make getInitColorSchemeScript support mode
siriwatknp Oct 29, 2021
5816a77
add useCurrentColorScheme
siriwatknp Oct 29, 2021
36c7a45
move storage to useCurrentColorScheme
siriwatknp Oct 30, 2021
3c5d33a
add storage event tests
siriwatknp Oct 31, 2021
0210c5f
fix type
siriwatknp Oct 31, 2021
657bcee
update createCssVarsProvider to support system mode
siriwatknp Oct 31, 2021
1c8c659
Merge branch 'master' of https://github.com/mui-org/material-ui into …
siriwatknp Oct 31, 2021
9a8592d
does not include `vars`
siriwatknp Oct 31, 2021
2488a02
fix bug when setting mode to night
siriwatknp Oct 31, 2021
4b07232
fix resolve default color scheme
siriwatknp Oct 31, 2021
3b66301
fix script to use `system`
siriwatknp Oct 31, 2021
1f33efc
fix test
siriwatknp Oct 31, 2021
382604a
fix tests
siriwatknp Oct 31, 2021
d800cc8
simplify setColorScheme
siriwatknp Nov 1, 2021
8a77078
add demo page
siriwatknp Nov 1, 2021
186b33a
change day, night to light, dark
siriwatknp Nov 2, 2021
df62435
fix types declaration for CssVarsProvider
siriwatknp Nov 2, 2021
826cfc3
remove temp joy page
siriwatknp Nov 2, 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
207 changes: 207 additions & 0 deletions docs/pages/joy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import * as React from 'react';
Copy link
Member Author

@siriwatknp siriwatknp Nov 1, 2021

Choose a reason for hiding this comment

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

This file is for the preview demo. (will be deleted before merging).

import { CssVarsProvider, styled, useColorScheme } from '@mui/joy/styles';
import { GlobalStyles } from '@mui/styled-engine';

declare module '@mui/joy/styles' {
interface ColorSchemeOverrides {
dark: true;
lightGreen: true;
darkGreen: true;
// lightRed: true;
// darkRed: true;
}
interface Palette {
bgcolor: React.CSSProperties['backgroundColor'];
text: React.CSSProperties['color'];
}
}

const Button = styled('button', {
shouldForwardProp: (prop) => prop !== 'active',
})<{ active?: boolean; color?: string }>(({ theme, active }) => ({
border: 0,
fontSize: theme.vars.fontSize.md,
height: 40,
borderRadius: 40,
padding: '0.25rem 1rem',
...(active && {
color: '#fff',
backgroundColor: theme.vars.palette.brand[500],
}),
}));

const Button2 = styled('button', {
shouldForwardProp: (prop) => prop !== 'active',
})<{ active?: boolean; color?: string }>(({ theme, active }) => ({
fontSize: theme.vars.fontSize.md,
height: 40,
borderRadius: 40,
padding: '0.25rem 1rem',
border: '1px solid',
backgroundColor: 'transparent',
color: theme.vars.palette.text,
opacity: 0.4,
...(active && {
borderColor: theme.vars.palette.text,
opacity: 1,
}),
}));

const Toggle = () => {
const [mounted, setMounted] = React.useState(false);
const { mode, setMode, colorScheme, setColorScheme } = useColorScheme();

// When mounted on client, now we can show the UI
React.useEffect(() => setMounted(true), []);
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need this?

Copy link
Member Author

Choose a reason for hiding this comment

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

To prevent SSR className mismatch because on the server there is no mode | colorScheme. Here is the explanation https://github.com/pacocoursey/next-themes#usetheme

This page is for demo only, will be removed before merging.

if (!mounted) {
return null;
}
return (
<div style={{ display: 'flex', gap: 16 }}>
<div>
<p style={{ color: 'var(--joy-palette-text)' }}>MODE</p>
<div style={{ display: 'flex', gap: 16 }}>
<Button2
active={mode === 'system'}
onClick={() => {
setMode('system');
}}
>
System
</Button2>
<Button2
active={mode === 'light'}
onClick={() => {
setMode('light');
}}
>
Day
</Button2>
<Button2
active={mode === 'dark'}
onClick={() => {
setMode('dark');
}}
>
Night
</Button2>
</div>
</div>

<div style={{ width: 1, backgroundColor: 'var(--joy-palette-text)', margin: '0 0.5rem' }} />

<div>
<p style={{ color: 'var(--joy-palette-text)' }}>COLOR SCHEME</p>
<div style={{ display: 'flex', gap: 16 }}>
<Button
active={colorScheme === 'light' || colorScheme === 'dark'}
onClick={() => {
setColorScheme({
light: 'light',
dark: 'dark',
});
}}
>
Default
</Button>
<Button
active={colorScheme === 'lightGreen' || colorScheme === 'darkGreen'}
onClick={() => {
setColorScheme({
light: 'lightGreen',
dark: 'darkGreen',
});
}}
>
Green
</Button>
</div>
</div>
</div>
);
};

export default function Joy() {
return (
<CssVarsProvider
defaultMode="system"
defaultColorScheme={{
light: 'lightGreen',
dark: 'darkGreen',
}}
theme={{
colorSchemes: {
light: {
palette: {
bgcolor: 'var(--joy-palette-brand-100)',
text: 'var(--joy-palette-brand-900)',
},
},
dark: {
palette: {
brand: {
50: '#E2EDF8',
100: '#CEE0F3',
200: '#91B9E3',
300: '#5090D3',
400: '#265D97',
500: '#1E4976',
600: '#173A5E',
700: '#132F4C', // contrast 13.64:1
800: '#001E3C',
900: '#0A1929',
},
bgcolor: 'var(--joy-palette-brand-900)',
text: 'var(--joy-palette-brand-50)',
},
},
lightGreen: {
palette: {
brand: {
50: '#E9FBF0',
100: '#C6F6D9',
200: '#9AEFBC',
300: '#6AE79C',
400: '#3EE07F',
500: '#21CC66',
600: '#1DB45A',
700: '#1AA251',
800: '#178D46',
900: '#0F5C2E',
},
bgcolor: 'var(--joy-palette-brand-100)',
text: 'var(--joy-palette-brand-900)',
},
},
darkGreen: {
palette: {
brand: {
50: '#F3FCF5',
100: '#D2F6E1',
200: '#7BE9BB',
300: '#00DA9C',
400: '#00C094',
500: '#00A389',
600: '#00867B',
700: '#00706E',
800: '#00585E',
900: '#00464F',
},
bgcolor: 'var(--joy-palette-brand-900)',
text: 'var(--joy-palette-brand-100)',
},
},
},
}}
>
<GlobalStyles
styles={{
body: {
backgroundColor: 'var(--joy-palette-bgcolor)',
},
}}
/>
<Toggle />
</CssVarsProvider>
);
}
12 changes: 11 additions & 1 deletion packages/mui-joy/src/styles/CssVarsProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { styled, CssVarsProvider, useTheme } from '@mui/joy/styles';
import defaultTheme from './defaultTheme';

describe('[Joy] CssVarsProvider', () => {
let originalMatchmedia: typeof window.matchMedia;
const render = createClientRender();
const storage: Record<string, string> = {};
before(() => {
beforeEach(() => {
originalMatchmedia = window.matchMedia;
// Create mocks of localStorage getItem and setItem functions
Object.defineProperty(global, 'localStorage', {
value: {
Expand All @@ -18,6 +20,14 @@ describe('[Joy] CssVarsProvider', () => {
},
configurable: true,
});
window.matchMedia = () =>
({
addListener: () => {},
removeListener: () => {},
} as unknown as MediaQueryList);
});
afterEach(() => {
window.matchMedia = originalMatchmedia;
Copy link
Member Author

Choose a reason for hiding this comment

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

need to reset the matchMedia, otherwise, it will affect some tests in the project.

});
describe('All CSS vars', () => {
it('palette', () => {
Expand Down
49 changes: 42 additions & 7 deletions packages/mui-system/src/cssVars/createCssVarsProvider.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import { Result, Mode } from './useCurrentColorScheme';

type RequiredDeep<T> = {
[K in keyof T]-?: RequiredDeep<T[K]>;
Expand Down Expand Up @@ -35,10 +36,9 @@ type DecideTheme<
};
};

export interface ColorSchemeContextValue<DesignSystemColorScheme extends string> {
allColorSchemes: DesignSystemColorScheme[];
colorScheme: DesignSystemColorScheme | undefined;
setColorScheme: React.Dispatch<React.SetStateAction<DesignSystemColorScheme | undefined>>;
export interface ColorSchemeContextValue<SupportedColorScheme extends string>
extends Result<SupportedColorScheme> {
allColorSchemes: SupportedColorScheme[];
}

export default function createCssVarsProvider<
Expand All @@ -63,15 +63,50 @@ export default function createCssVarsProvider<
>
>;
};
defaultColorScheme: DesignSystemColorScheme;
defaultColorScheme:
| DesignSystemColorScheme
| { light: DesignSystemColorScheme; dark: DesignSystemColorScheme };
/**
* Design system default mode
* @default 'light'
*/
defaultMode?: Mode;
/**
* CSS variable prefix
* @default ''
*/
prefix?: string;
}): {
CssVarsProvider: (
props: React.PropsWithChildren<
{
defaultColorScheme?: DesignSystemColorScheme | ApplicationColorScheme;
storageKey?: string;
/**
* Application default mode (overrides design system `defaultMode` if specified)
*/
defaultMode?: Mode;
/**
* Application default colorScheme (overrides design system `defaultColorScheme` if specified)
*/
defaultColorScheme?:
| DesignSystemColorScheme
| ApplicationColorScheme
| {
light: DesignSystemColorScheme | ApplicationColorScheme;
dark: DesignSystemColorScheme | ApplicationColorScheme;
};
/**
* localStorage key used to store application `mode`
* @default 'mui-mode'
*/
modeStorageKey?: string;
/**
* DOM attribute for applying color scheme
* @default 'data-mui-color-scheme'
*/
attribute?: string;
/**
* CSS variable prefix (overrides design system `prefix` if specified)
*/
prefix?: string;
} & DecideTheme<ApplicationThemeInput, DesignSystemColorScheme, ApplicationColorScheme>
>,
Expand Down
Loading