-
Notifications
You must be signed in to change notification settings - Fork 1.4k
docs: light mode dark mode #8050
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
base: main
Are you sure you want to change the base?
Changes from 6 commits
f7675d9
ec44bf9
df13812
9f6eb31
a871af8
94d105b
5088ec8
f70566b
68c7d21
c4a2fd4
12441e5
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,19 @@ | ||
import { component$ } from '@builder.io/qwik'; | ||
|
||
interface BrillianceIconProps { | ||
class?: string; | ||
} | ||
|
||
export const BrillianceIcon = component$<BrillianceIconProps>(({ class: className, ...props }) => { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
fill="currentColor" | ||
class={className} | ||
viewBox="0 0 16 16" | ||
{...props} | ||
> | ||
<path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16M1 8a7 7 0 0 0 7 7 3.5 3.5 0 1 0 0-7 3.5 3.5 0 1 1 0-7 7 7 0 0 0-7 7" /> | ||
</svg> | ||
); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { component$ } from '@builder.io/qwik'; | ||
|
||
interface MoonIconProps { | ||
class?: string; | ||
} | ||
|
||
export const MoonIcon = component$<MoonIconProps>(({ class: className, ...props }) => { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
fill="none" | ||
viewBox="0 0 24 24" | ||
stroke-width="1.5" | ||
stroke="currentColor" | ||
class={className} | ||
{...props} | ||
> | ||
<path | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" | ||
/> | ||
</svg> | ||
); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { component$ } from '@builder.io/qwik'; | ||
|
||
interface SunIconProps { | ||
class?: string; | ||
} | ||
|
||
export const SunIcon = component$<SunIconProps>(({ class: className, ...props }) => { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
fill="none" | ||
viewBox="0 0 24 24" | ||
stroke-width="1.5" | ||
stroke="currentColor" | ||
class={className} | ||
{...props} | ||
> | ||
<path | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" | ||
/> | ||
</svg> | ||
); | ||
}); |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,17 @@ | ||
.theme-toggle { | ||
--size: 22px; | ||
--icon-fill: hsl(210 10% 15%); | ||
--icon-fill-hover: hsl(210 10% 30%); | ||
|
||
display: block; | ||
|
||
background: none; | ||
border: none; | ||
padding: 0; | ||
|
||
inline-size: var(--size); | ||
block-size: var(--size); | ||
aspect-ratio: 1; | ||
border-radius: 50%; | ||
|
||
cursor: pointer; | ||
touch-action: manipulation; | ||
-webkit-tap-highlight-color: transparent; | ||
|
||
outline-offset: 5px; | ||
.themeIcon { | ||
opacity: 0; | ||
transition: opacity 400ms ease-in-out; | ||
width: 25px; | ||
height: 25px; | ||
} | ||
|
||
[data-theme='dark'] .theme-toggle { | ||
--icon-fill: hsl(210 10% 100%); | ||
--icon-fill-hover: hsl(210 15% 70%); | ||
.themeIcon.auto { | ||
width: 21px; | ||
height: 21px; | ||
} | ||
|
||
.theme-toggle > svg { | ||
inline-size: 100%; | ||
block-size: 100%; | ||
stroke-linecap: round; | ||
html[data-theme='light'] .themeIcon.light, | ||
html[data-theme='dark'] .themeIcon.dark, | ||
html:not([data-theme]) .themeIcon.auto { | ||
|
||
opacity: 1; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,32 @@ | ||
import { component$, event$, useContext, useStyles$ } from '@builder.io/qwik'; | ||
import { SunAndMoon } from './sun-and-moon'; | ||
import { component$, event$, isServer, useStyles$ } from '@builder.io/qwik'; | ||
import { themeStorageKey } from '../router-head/theme-script'; | ||
import themeToggle from './theme-toggle.css?inline'; | ||
import { GlobalStore } from '../../context'; | ||
import { SunIcon } from './Sun'; | ||
import { MoonIcon } from './Moon'; | ||
import { BrillianceIcon } from './Brilliance'; | ||
export type ThemePreference = 'dark' | 'light' | 'auto'; | ||
export const setPreference = (theme: ThemePreference) => { | ||
if (theme === 'auto') { | ||
document.firstElementChild?.removeAttribute('data-theme'); | ||
|
||
} else { | ||
document.firstElementChild?.setAttribute('data-theme', theme!); | ||
} | ||
|
||
localStorage.setItem(themeStorageKey, theme); | ||
}; | ||
|
||
export type ThemePreference = 'dark' | 'light'; | ||
export const getColorPreference = (): ThemePreference => { | ||
if (isServer) { | ||
return 'auto'; | ||
} | ||
let theme; | ||
try { | ||
theme = localStorage.getItem(themeStorageKey); | ||
} catch { | ||
// | ||
} | ||
return (theme as ThemePreference) || 'auto'; | ||
}; | ||
|
||
export const colorSchemeChangeListener = (onColorSchemeChange: (isDark: boolean) => void) => { | ||
JerryWu1234 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const listener = ({ matches: isDark }: MediaQueryListEvent) => { | ||
|
@@ -18,56 +40,32 @@ export const colorSchemeChangeListener = (onColorSchemeChange: (isDark: boolean) | |
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', listener); | ||
}; | ||
|
||
export const setPreference = (theme: ThemePreference) => { | ||
localStorage.setItem(themeStorageKey, theme); | ||
reflectPreference(theme); | ||
}; | ||
|
||
export const reflectPreference = (theme: ThemePreference) => { | ||
document.firstElementChild?.setAttribute('data-theme', theme); | ||
}; | ||
|
||
export const getColorPreference = (): ThemePreference => { | ||
let theme; | ||
try { | ||
theme = localStorage.getItem(themeStorageKey); | ||
} catch (err) { | ||
// | ||
} | ||
if (theme) { | ||
return theme as ThemePreference; | ||
} else { | ||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; | ||
} | ||
}; | ||
|
||
export const ThemeToggle = component$(() => { | ||
useStyles$(themeToggle); | ||
const state = useContext(GlobalStore); | ||
|
||
const onClick$ = event$(() => { | ||
state.theme = state.theme === 'light' ? 'dark' : 'light'; | ||
setPreference(state.theme); | ||
let currentTheme = getColorPreference(); | ||
if (currentTheme === 'dark') { | ||
currentTheme = 'light'; | ||
} else if (currentTheme === 'light') { | ||
currentTheme = 'auto'; | ||
} else { | ||
currentTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'light' : 'dark'; | ||
} | ||
setPreference(currentTheme); | ||
}); | ||
|
||
return ( | ||
<> | ||
<span class="lg:hidden"> | ||
<button onClick$={onClick$}>{state.theme === 'light' ? 'Dark' : 'Light'} theme</button> | ||
</span> | ||
<span class="hidden lg:block"> | ||
<button | ||
type="button" | ||
class="theme-toggle" | ||
id="theme-toggle" | ||
title="Toggles light & dark" | ||
aria-label={state.theme} | ||
aria-live="polite" | ||
onClick$={onClick$} | ||
> | ||
<SunAndMoon /> | ||
</button> | ||
</span> | ||
<button | ||
onClick$={onClick$} | ||
class="group relative flex h-8 w-8 items-center justify-center rounded-md bg-background text-foreground hover:opacity-60" | ||
> | ||
<div class="absolute inset-0 grid place-items-center transition-transform duration-200 ease-out group-hover:scale-110 group-active:scale-75"> | ||
<SunIcon class="themeIcon light col-start-1 row-start-1" /> | ||
<MoonIcon class="themeIcon dark col-start-1 row-start-1" /> | ||
<BrillianceIcon class="themeIcon auto col-start-1 row-start-1" /> | ||
</div> | ||
</button> | ||
</> | ||
); | ||
}); |
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.
I think all these dark mode changes should only look at data-theme.