fix: use light theme when js is disabled

Fix a bug where the LSD css vars and themed images were not applied correctly when JS was disabled. This was caused by Docusaurus not setting a data-theme attribute to the HTML element. The commit adds a fallback to the light theme and the LSD theme variables in the CSS.
This commit is contained in:
Hossein Mehrabi
2024-01-17 20:50:36 +03:30
parent d910e4f581
commit bfa6888eb3
4 changed files with 74 additions and 8 deletions
@@ -10,8 +10,7 @@ export const ThemeProvider: React.FC<React.PropsWithChildren<{}>> = ({
return (
<LSDThemeProvider theme={theme.current} injectCssVars={false}>
<Global styles={theme.darkCssVars} />
<Global styles={theme.lightCssVars} />
<Global styles={theme.cssVars} />
{children}
</LSDThemeProvider>
)
@@ -4,14 +4,22 @@ import { css } from '@emotion/react'
import { useMemo } from 'react'
import { useThemeOptions } from './useThemeOptions'
const useThemeCssVars = (theme: Theme, colorMode: string) =>
const useThemeCssVars = (light: Theme, dark: Theme, fallback: Theme) =>
useMemo(
() => css`
[data-theme=${colorMode}] {
${theme.cssVars}
html:not([data-theme]) {
${fallback.cssVars}
}
html[data-theme='light'] {
${light.cssVars}
}
html[data-theme='dark'] {
${dark.cssVars}
}
`,
[theme],
[dark, light],
)
export const useTheme = () => {
@@ -43,7 +51,6 @@ export const useTheme = () => {
light: themes.light,
current: themes[colorMode.colorMode],
colorMode: colorMode.colorMode,
lightCssVars: useThemeCssVars(themes.light, 'light'),
darkCssVars: useThemeCssVars(themes.dark, 'dark'),
cssVars: useThemeCssVars(themes.light, themes.dark, themes.light),
}
}
@@ -0,0 +1,41 @@
import React from 'react'
import clsx from 'clsx'
import useIsBrowser from '@docusaurus/useIsBrowser'
import { useColorMode } from '@docusaurus/theme-common'
import type { Props } from '@theme/ThemedImage'
import styles from './styles.module.css'
export default function ThemedImage(props: Props): JSX.Element {
const isBrowser = useIsBrowser()
const { colorMode } = useColorMode()
const { sources, className, alt, ...propsRest } = props
type SourceName = keyof Props['sources']
const clientThemes: SourceName[] = colorMode === 'dark' ? ['dark'] : ['light']
const renderedSourceNames: SourceName[] = isBrowser
? clientThemes
: // We need to render both images on the server to avoid flash
// See https://github.com/facebook/docusaurus/pull/3730
['light', 'dark']
return (
<>
{renderedSourceNames.map((sourceName) => (
<img
key={sourceName}
src={sources[sourceName]}
alt={alt}
className={clsx(
styles.themedImage,
styles[`themedImage--${sourceName}`],
className,
)}
{...propsRest}
/>
))}
</>
)
}
@@ -0,0 +1,19 @@
.themedImage {
display: none;
}
[data-theme='light'] .themedImage--light {
display: initial;
}
[data-theme='dark'] .themedImage--dark {
display: initial;
}
/*
JS disabled??? Show light version by default => better than showing nothing
TODO bad, but we currently always show light mode when there's no data-theme
*/
html:not([data-theme]) .themedImage--light {
display: initial;
}