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

feat: parse theme from query param #469

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 8 additions & 2 deletions packages/theme/cookie-theme-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import {
import { themeMap } from './themes.js'
import { getThemeNameFromCookies } from './utils/cookies.js'
import { initColors } from './document-head-contents/index.js'
import { updateGlobalTheme } from './document-head-contents/element-theme-script.js'
import {
getThemeNameFromUrl,
updateGlobalTheme,
} from './document-head-contents/element-theme-script.js'
import { ThemeContext } from './types.js'

const defaultThemeContext = {} as ThemeContext
Expand Down Expand Up @@ -56,7 +59,7 @@ export const CookieThemeProvider: FC<
// we always start with default theme, or, if server wants to provide
// specific default theme, with server-provided theme to avoid hydration errors
const [internalThemeName, setThemeName] = useState<ThemeName>(
initialThemeName || DEFAULT_THEME_NAME,
getThemeNameFromUrl() || initialThemeName || DEFAULT_THEME_NAME,
)
// since we're using this component to provide cookie-theme,
// we eventually want to respect theme provided in cookie, not general theme,
Expand All @@ -78,10 +81,13 @@ export const CookieThemeProvider: FC<
const systemThemeName = prefersDarkThemeMediaQuery?.matches
? ThemeName.dark
: ThemeName.light
const themeNameUrl = getThemeNameFromUrl()
const themeNameCookie = getThemeNameFromCookies()
const newThemeName =
// first, if we have some override (e.g. in Storybook), we respect it
overrideThemeName ||
// url query has higher priority than cookie
themeNameUrl ||
// then, if we have cookie theme, we use theme from cookie
themeNameCookie ||
// else, we follow theme we were provided in initialization from server,
Expand Down
16 changes: 16 additions & 0 deletions packages/theme/document-head-contents/element-theme-script.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { VOID_FN } from '../../utils/index.js'
import { themeCookieKey, ThemeName } from '../constants.js'
import { setThemeCookie } from '../utils/set-theme-cookie.js'

export const getThemeNameFromUrl = (): ThemeName | undefined => {
if (typeof window === 'undefined') return undefined
const url = new URL(window.location.href)
const queryTheme = url.searchParams.get('theme')?.toLowerCase()
if (queryTheme === 'light') return ThemeName.light
if (queryTheme === 'dark') return ThemeName.dark
return undefined
}

/**
* What is happening here:
* We want to have React dehydrated HTML to be loaded after theme is initialized.
Expand All @@ -18,6 +27,13 @@ import { setThemeCookie } from '../utils/set-theme-cookie.js'
* */
/*#__PURE__*/
const themeScriptValueString = function (key: string) {
const url = new URL(window.location.href)
const queryTheme = url.searchParams.get('theme')?.toLowerCase()
if (queryTheme === 'light' || queryTheme === 'dark') {
document.documentElement.dataset.lidoTheme = queryTheme
// eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {}
}
if (!window.matchMedia) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {}
Expand Down
Loading