Skip to content

Instantly share code, notes, and snippets.

@perjo927
Last active September 2, 2024 08:54
Show Gist options
  • Save perjo927/421c718b410a17c8b6f3e383e4c0babc to your computer and use it in GitHub Desktop.
Save perjo927/421c718b410a17c8b6f3e383e4c0babc to your computer and use it in GitHub Desktop.
dark/light mode toggle
:root {
--black: rgb(13, 13, 13);
--darkest-gray: rgb(24, 25, 32);
--dark-gray: rgb(79, 79, 79);
--medium-gray: rgb(130, 130, 130);
--gray: rgb(189, 189, 189);
--light-gray: rgb(224, 224, 224);
--lightest-gray: rgb(242, 242, 242);
--white: rgb(250, 250, 250);
--purple: rgb(101, 82, 224);
--gold: rgb(204, 155, 46);
--green: rgb(46, 204, 69);
--blue: rgb(46, 120, 204);
--light-blue: rgb(46, 196, 204);
--light-red: rgb(235, 86, 86);
--light-yellow: rgb(246, 212, 126);
--primary-bg-color-darkmode: var(--darkest-gray);
--secondary-bg-color-darkmode: var(--black);
--primary-text-color-darkmode: var(--white);
--border-color-darkmode: var(--dark-gray);
--primary-bg-color-lightmode: var(--light-gray);
--secondary-bg-color-lightmode: var(--white);
--primary-text-color-lightmode: var(--darkest-gray);
--border-color-lightmode: var(--gray);
--primary-bg-color: var(--primary-bg-color-lightmode);
--secondary-bg-color: var(--secondary-bg-color-lightmode);
--primary-text-color: var(--primary-text-color-lightmode);
--secondary-text-color: var(--medium-gray);
--primary-color: var(--purple);
--secondary-color: var(--light-blue);
--error-color: var(--light-red);
--warning-color: var(--light-yellow);
--link-color: var(--primary-color);
--border-color: var(--border-color-lightmode);
--border-radius: 0.25rem;
--base-gap: 0.75rem;
--container-padding: 0.75rem;
--z-index-bottom: 1;
--z-index-popup: 10;
--z-index-menu: 1000;
--primary-box-shadow: 0 0.25rem 0.375rem var(--border-color);
font-size: 16px;
font-family: 'Manrope', Helvetica, Arial, sans-serif;
color-scheme: dark light;
/* TODO: this dark-mode switch is not supported yet */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark */
/*
color: light-dark(var(--primary-text-color), var(--primary-text-color-darkmode));
background-color: light-dark(
var(--primary-bg-color),
var(--primary-bg-color-darkmode)
);
*/
color: var(--primary-text-color);
background-color: var(--primary-bg-color);
}
/* media query that listens to system preferecens */
@media (prefers-color-scheme: dark) {
/* TODO: this can be replaced by light-dark in the future */
:root {
--primary-bg-color: var(--primary-bg-color-darkmode);
--secondary-bg-color: var(--secondary-bg-color-darkmode);
--primary-text-color: var(--primary-text-color-darkmode);
--border-color: var(--border-color-darkmode);
}
}
/* data attributes for color scheme that are set to user preferences */
[data-theme='light'] {
--primary-bg-color: var(--primary-bg-color-lightmode);
--secondary-bg-color: var(--secondary-bg-color-lightmode);
--primary-text-color: var(--primary-text-color-lightmode);
--border-color: var(--border-color-lightmode);
}
[data-theme='dark'] {
--primary-bg-color: var(--primary-bg-color-darkmode);
--secondary-bg-color: var(--secondary-bg-color-darkmode);
--primary-text-color: var(--primary-text-color-darkmode);
--border-color: var(--border-color-darkmode);
}
import {getColorScheme, initColorScheme} from './utils/color-scheme';
import {themeContext} from './data/contexts/theme-context';
@customElement('app-root')
export class AppRootElement extends LitElement {
private _themeContext = new ContextProvider(this, {
context: themeContext,
initialValue: {
colorScheme: getColorScheme(),
},
});
#handleColorSchemeChanged = (event: Event) => {
const detail = (event as CustomEvent).detail;
this._themeContext.setValue({
colorScheme: detail,
});
};
override connectedCallback(): void {
super.connectedCallback();
initColorScheme();
}
protected override firstUpdated(): void {
const mediaQueryListener = window.matchMedia('(min-width: 992px)');
this.#handleMenuToggled(null, mediaQueryListener.matches);
const header = this.renderRoot.querySelector('header-element');
header?.addEventListener(
HeaderElement.events.colorSchemeChanged,
this.#handleColorSchemeChanged
);
}
constructor() {
super();
}
override render() {
return html`
<header>
Some stuff here
</header>
<aside>
Some other stuff here
</aside>
<main>Some more stuff here</main>
`;
}
}
import {ColorScheme} from '../types';
export function getColorScheme(): ColorScheme {
const currentUserTheme = localStorage.getItem('color-scheme');
if (currentUserTheme) {
const userTheme = currentUserTheme as ColorScheme;
return userTheme;
}
const darkScheme = window.matchMedia('(prefers-color-scheme: dark)');
const lightScheme = window.matchMedia('(prefers-color-scheme: light)');
if (darkScheme.matches) {
return 'dark';
}
if (lightScheme.matches) {
return 'light';
}
return 'dark';
}
export function initColorScheme() {
const currentUserTheme = localStorage.getItem('color-scheme');
if (currentUserTheme) {
const htmlElement = document.querySelector('html');
htmlElement?.setAttribute('data-theme', currentUserTheme);
}
}
export function toggleColorScheme(
onToggledColorScheme: (colorScheme: ColorScheme) => void
) {
const currentTheme = getColorScheme();
const htmlElement = document.querySelector('html');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
localStorage.setItem('color-scheme', newTheme);
htmlElement?.setAttribute('data-theme', newTheme);
onToggledColorScheme(newTheme);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment