Skip to content

Commit

Permalink
fix(color-mode): fix color mode issues
Browse files Browse the repository at this point in the history
  • Loading branch information
gregberge committed Sep 22, 2019
1 parent 71e1587 commit 237c888
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 42 deletions.
75 changes: 39 additions & 36 deletions packages/core/src/colorModes.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,29 @@ function hasColorModes(theme) {
return theme && theme.colors && theme.colors.modes
}

function hasCustomPropertiesEnabled(theme) {
return (
theme &&
(theme.useCustomProperties === undefined || theme.useCustomProperties)
)
}

function hasMediaQueryEnabled(theme) {
return (
theme &&
(theme.useColorSchemeMediaQuery === undefined ||
theme.useColorSchemeMediaQuery)
)
}

function getInitialColorModeName(theme) {
return theme.initialColorModeName || 'default'
}

function getDefaultColorModeName(theme) {
return theme.defaultColorModeName || getInitialColorModeName(theme)
}

export function createColorStyles(theme, { targetSelector = 'body' } = {}) {
if (!hasColorModes(theme)) return null
const { modes, ...colors } = theme.colors
Expand Down Expand Up @@ -69,42 +92,19 @@ export function createColorStyles(theme, { targetSelector = 'body' } = {}) {
})
}

Object.keys(modes).forEach(mode => {
const initialModeName = getInitialColorModeName(theme)
;[initialModeName, ...Object.keys(modes)].forEach(mode => {
const key = `&.${getColorModeClassName(mode)}`
styles += `${key}{${getModePropertiesDeclarations(mode)}}`
})

return `${targetSelector}{${styles}}`
}

function hasCustomPropertiesEnabled(theme) {
return (
theme &&
(theme.useCustomProperties === undefined || theme.useCustomProperties)
)
}

function hasMediaQueryEnabled(theme) {
return (
theme &&
(theme.useColorSchemeMediaQuery === undefined ||
theme.useColorSchemeMediaQuery)
)
}

function getInitialColorModeName(theme) {
return theme.initialColorModeName || 'default'
}

function getDefaultColorModeName(theme) {
return theme.defaultColorModeName || getInitialColorModeName(theme)
}

function getInitialMode(theme) {
if (!hasColorModes(theme)) return null
const stored = storage.get()
if (stored) {
return stored
}
if (stored) return stored
if (hasMediaQueryEnabled(theme) && theme.colors && theme.colors.modes) {
const systemMode = SYSTEM_MODES.find(mode => {
if (!theme.colors.modes[mode]) return null
Expand All @@ -120,26 +120,24 @@ export function useColorModeState(theme, { target = document.body } = {}) {

// Add mode className
const customPropertiesEnabled = hasCustomPropertiesEnabled(theme)
const initialColorMode = getInitialColorModeName(theme)
React.useLayoutEffect(() => {
if (!customPropertiesEnabled) return undefined
if (mode === initialColorMode) return undefined
const className = getColorModeClassName(mode)
target.classList.add(className)
return () => {
target.classList.remove(className)
}
}, [customPropertiesEnabled, target, mode, initialColorMode])
}, [customPropertiesEnabled, target, mode])

// Store mode preference
const defaultColorMode = getDefaultColorModeName(theme)
const changedRef = React.useRef(false)
React.useEffect(() => {
if (mode === defaultColorMode) {
storage.clear()
return
if (changedRef.current) {
storage.set(mode)
} else {
changedRef.current = true
}
storage.set(mode)
}, [defaultColorMode, mode])
}, [mode])

return [mode, setMode]
}
Expand Down Expand Up @@ -200,6 +198,11 @@ export function createColorModeProvider({
}) {
function ColorModeProvider({ children, target, targetSelector }) {
const theme = React.useContext(ThemeContext)
if (!theme) {
throw new Error(
'[ColorModeProvider] requires ThemeProvider upper in the tree',
)
}
const colorState = useColorModeState(theme, { target })
const colorModeTheme = useColorModeTheme(theme, colorState[0])
return (
Expand Down
14 changes: 8 additions & 6 deletions packages/core/src/colorModes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe('#createColorStyles', () => {
},
}
expect(createColorStyles(theme)).toBe(
`body{--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff0000;--xstyled-colors-danger: #ff0000;--xstyled-colors-text: #000;@media (prefers-color-scheme: dark){--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff4400;--xstyled-colors-danger: #ff4400;--xstyled-colors-text: #fff;}&.xstyled-color-mode-dark{--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff4400;--xstyled-colors-danger: #ff4400;--xstyled-colors-text: #fff;}}`,
`body{--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff0000;--xstyled-colors-danger: #ff0000;--xstyled-colors-text: #000;@media (prefers-color-scheme: dark){--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff4400;--xstyled-colors-danger: #ff4400;--xstyled-colors-text: #fff;}&.xstyled-color-mode-default{--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff0000;--xstyled-colors-danger: #ff0000;--xstyled-colors-text: #000;}&.xstyled-color-mode-dark{--xstyled-colors-black: #000;--xstyled-colors-white: #fff;--xstyled-colors-red: #ff4400;--xstyled-colors-danger: #ff4400;--xstyled-colors-text: #fff;}}`,
)
})
})
Expand Down Expand Up @@ -203,12 +203,13 @@ describe('#useColorModeState', () => {
const setDarkModeBtn = getByTestId('setDarkMode')
const setDefaultModeBtn = getByTestId('setDefaultMode')
expect(getByTestId('mode')).toHaveTextContent('default')
expect(document.body).not.toHaveClass('xstyled-color-mode-default')
expect(document.body).toHaveClass('xstyled-color-mode-default')
expect(document.body).not.toHaveClass('xstyled-color-mode-dark')
fireEvent.click(setDarkModeBtn)
expect(document.body).not.toHaveClass('xstyled-color-mode-default')
expect(document.body).toHaveClass('xstyled-color-mode-dark')
fireEvent.click(setDefaultModeBtn)
expect(document.body).not.toHaveClass('xstyled-color-mode-default')
expect(document.body).toHaveClass('xstyled-color-mode-default')
expect(document.body).not.toHaveClass('xstyled-color-mode-dark')
})

Expand All @@ -221,12 +222,13 @@ describe('#useColorModeState', () => {
const setDarkModeBtn = getByTestId('setDarkMode')
const setDefaultModeBtn = getByTestId('setDefaultMode')
expect(getByTestId('mode')).toHaveTextContent('default')
expect(main).not.toHaveClass('xstyled-color-mode-default')
expect(main).toHaveClass('xstyled-color-mode-default')
expect(main).not.toHaveClass('xstyled-color-mode-dark')
fireEvent.click(setDarkModeBtn)
expect(main).not.toHaveClass('xstyled-color-mode-default')
expect(main).toHaveClass('xstyled-color-mode-dark')
fireEvent.click(setDefaultModeBtn)
expect(main).not.toHaveClass('xstyled-color-mode-default')
expect(main).toHaveClass('xstyled-color-mode-default')
expect(main).not.toHaveClass('xstyled-color-mode-dark')
})
})
Expand All @@ -253,7 +255,7 @@ describe('#useColorModeState', () => {
fireEvent.click(setDarkModeBtn)
expect(window.localStorage.getItem('xstyled-color-mode')).toBe('dark')
fireEvent.click(setDefaultModeBtn)
expect(window.localStorage.getItem('xstyled-color-mode')).toBe(null)
expect(window.localStorage.getItem('xstyled-color-mode')).toBe('default')
})
})

Expand Down

0 comments on commit 237c888

Please sign in to comment.