react-perfect-dark-mode
gatsby-plugin-perfect-dark-mode
next-plugin-perfect-dark-mode
vue-perfect-dark-mode
window.__pdm__.mode
is a Writable
.light
and dark
.There are a few options for installing perfect-dark-mode
.
Note, if you use Gatsby or Next.js you do not need to do this.
yarn add perfect-dark-mode
Then you must add node_modules/perfect-dark-mode/dist/index.js
as a script in the <head>
of your page.
How you do this will depend on the framework you are using.
Add this code to the <head>
of your page:
<script src="https://unpkg.com/[email protected]/dist/index.js"></script>
Add this code to the <head>
of your page:
<script>(()=>{var W=({prefix:r="pdm",modes:w=["light","dark"]}={})=>{var n=r,l=window.localStorage,t=w,c=new Set,h=e=>{t=e,c.forEach(o=>o(e))},O={subscribe(e){return e(t),c.add(e),()=>c.delete(e)},set:h,update(e){h(e(t))}},u=new Set,a=matchMedia("(prefers-color-scheme: dark)"),m,f=({matches:e})=>{m=e?"dark":"light",u.forEach(o=>o(m))};a.addEventListener?a.addEventListener("change",f):a.addListener(f),f(a);var v={subscribe(e){return e(m),u.add(e),()=>u.delete(e)}},P=e=>{if(!(!e||!t.includes(e)))return e},p=new Set,s=P(l.getItem(n)),M=(e,o=!0)=>{e!==s&&(o&&(e!==void 0?l.setItem(n,e):l.removeItem(n)),p.forEach(T=>T(e)),s=e)};window.addEventListener("storage",e=>e.key===n&&M(e.newValue||void 0,!1));var i={subscribe(e){return e(s),p.add(e),()=>p.delete(e)},set:M,update(e){M(e(s))}},g,k,d,b=new Set,x=()=>{var e=g||k;e!==d&&(d=e,b.forEach(o=>o(d)))};i.subscribe(e=>{g=e,x()}),v.subscribe(e=>{k=e,x()});var E={subscribe(e){return e(d),b.add(e),()=>b.delete(e)},set:i.set,update(e){var o=t.indexOf(d);o=o===-1?0:o,i.set(e(d,t,o))}},C=document.documentElement.classList,S;return E.subscribe(e=>{S&&C.remove(`${r}-${S}`),C.add(`${r}-${e}`),S=e}),C.add(r),{mode:E,modes:O,modeOS:v,modeSaved:i}};window.__pdm__=W({modes:document.documentElement.dataset.pdm?.split(" ")});})();</script>
A class indicating the color mode will be added to <html>
(e.g. pdm-light
or pdm-dark
).
This is done before the rest of your page is rendered (that's why it needs to be in head).
Here is a simple implementation of dark and light modes using CSS variables and the classes added by PDM:
/* This supports users with JS disabled. */
@media (prefers-color-scheme: dark) {
:root {
--color: white;
--background: black;
}
}
/* This supports users with JS disabled. */
@media (prefers-color-scheme: light) {
:root {
--color: black;
--background: white;
}
}
/* Styles for when light mode is enabled. */
.pdm-light {
--color: black;
--background: white;
}
/* Styles for when dark mode is enabled. */
.pdm-dark {
--color: white;
--background: black;
}
/* Default color and background. */
/* If you add a color or background on other components (e.g. body or some custom Button) */
/* that will override these. You will need to change those styles to use these CSS variables. */
:root {
color: var(--color);
background: var(--background);
}
In the rest of your app use --color
and --background
as needed.
subscribe
to the mode, this can be used for rendering a toggle component.const { mode } = window.__pdm__
const unsubscribe = mode.subscribe((v) => console.log(v))
set
the mode.update
the mode based on the current mode.const { mode } = window.__pdm__
mode.set('light')
mode.update((mode) => (mode === 'light' ? 'dark' : 'light'))
window.__pdm__
mode: Writable<ColorMode>
modeSaved || modeOS
.subscribe(listener: (mode: ColorMode) => void): () => void
set(mode: ColorMode): void
update(updater: (mode: ColorMode, modes: ColorMode[], index: number | undefined) => ColorMode): void
modes[(modeIndex + 1) % modes.length]
.modes: Writable<ColorMode[]>
subscribe(listener: (modes: ColorMode[]) => void): () => void
set(modes: ColorMode[]): void
update(updater: (modes: ColorMode[]) => ColorMode[]): void
modeSaved: Writable<ColorMode>
mode
.subscribe(listener: (mode: ColorMode) => void): () => void
modeOS: Readable<ColorMode>
mode
.subscribe(listener: (mode: ColorMode) => void): () => void
If for some reason you don't want PDM to automatically initialize itself and add itself on window.__pdm__
you can use the pure version:
import { createPerfectDarkMode } from 'perfect-dark-mode'
const pdm = createPerfectDarkMode()