-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
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
Changes from 38 commits
4e5f739
ef44ca1
fc8a3e4
fa484be
ae8d466
ddc35f9
5b54132
7c75d62
06f336a
96c7a17
d1c45af
a83d6c7
1f1a4eb
b7cf8dc
a5d654a
ef574b4
3745b44
105c6c8
007121a
38559bc
d9b3334
275e217
887125b
5816a77
36c7a45
3c5d33a
0210c5f
657bcee
1c8c659
9a8592d
2488a02
4b07232
3b66301
1f33efc
382604a
d800cc8
8a77078
186b33a
df62435
826cfc3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
import * as React from 'react'; | ||
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), []); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To prevent SSR className mismatch because on the server there is no
|
||
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> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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: { | ||
|
@@ -18,6 +20,14 @@ describe('[Joy] CssVarsProvider', () => { | |
}, | ||
configurable: true, | ||
}); | ||
window.matchMedia = () => | ||
({ | ||
addListener: () => {}, | ||
removeListener: () => {}, | ||
} as unknown as MediaQueryList); | ||
}); | ||
afterEach(() => { | ||
window.matchMedia = originalMatchmedia; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need to reset the |
||
}); | ||
describe('All CSS vars', () => { | ||
it('palette', () => { | ||
|
There was a problem hiding this comment.
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).