⬅ Back home

Cito Theme Controller

What

Idea

How to use

Javascript

/**
 * Cito Theme Controller
 * Version 1.0.0
 * Author: ilkka.kuivanen@me.com
 */
const LIGHT = 'light';
const DARK = 'dark';
const THEME = 'theme';
function getLocalStorage() {
    return localStorage.getItem(THEME);
}
function setLocalStorage(v) {
    localStorage.setItem(THEME, v);
}
function setTheme(v) {
    const html = document.querySelector('html');
    if (html !== null) {
        html.dataset['theme'] = v;
    }
    setLocalStorage(v);
}
function getCurrentThemeValue() {
    return (document.querySelector('html')?.dataset['theme'] ??
        'no theme set');
}
export function getCurrentTheme() {
    const theme = getCurrentThemeValue();
    return theme.charAt(0).toUpperCase() + theme.slice(1);
}
export function toggleTheme() {
    const currentTheme = getCurrentThemeValue();
    if (currentTheme === LIGHT) {
        setTheme(DARK);
    }
    else {
        setTheme(LIGHT);
    }
}
export function detectColorScheme() {
    let theme = LIGHT;
    // Get current media value, default to "light"
    let currentlySetSystemColorScheme = LIGHT;
    if (!window.matchMedia) {
        return;
    }
    else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
        currentlySetSystemColorScheme = DARK;
    }
    const currentLocalStorageTheme = getLocalStorage();
    // Prefer localStorage, otherwise go with system scheme
    if (currentLocalStorageTheme === LIGHT ||
        currentLocalStorageTheme === DARK) {
        theme = currentLocalStorageTheme;
    }
    else {
        theme = currentlySetSystemColorScheme;
    }
    document.querySelector('html')?.setAttribute('data-theme', theme);
    setLocalStorage(theme);
}

Typescript

/**
 * Cito Theme Controller
 * Version 1.0.0
 * Author: ilkka.kuivanen@me.com
 */

const LIGHT = 'light';
const DARK = 'dark';
const THEME = 'theme';

function getLocalStorage() {
    return localStorage.getItem(THEME);
}

function setLocalStorage(v: string) {
    localStorage.setItem(THEME, v);
}

function setTheme(v: string) {
    const html = document.querySelector('html');
    if (html !== null) {
        html.dataset['theme'] = v;
    }
    setLocalStorage(v);
}

function getCurrentThemeValue() {
    return (
        document.querySelector('html')?.dataset['theme'] ??
        'no theme set'
    );
}

export function getCurrentTheme() {
    const theme = getCurrentThemeValue();
    return theme.charAt(0).toUpperCase() + theme.slice(1);
}

export function toggleTheme() {
    const currentTheme = getCurrentThemeValue();
    if (currentTheme === LIGHT) {
        setTheme(DARK);
    } else {
        setTheme(LIGHT);
    }
}

export function detectColorScheme() {
    let theme = LIGHT;

    // Get current media value, default to "light"
    let currentlySetSystemColorScheme: typeof LIGHT | typeof DARK = LIGHT;
    if (!window.matchMedia) {
        return;
    } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
        currentlySetSystemColorScheme = DARK;
    }

    const currentLocalStorageTheme = getLocalStorage();

    // Prefer localStorage, otherwise go with system scheme
    if (
        currentLocalStorageTheme === LIGHT ||
        currentLocalStorageTheme === DARK
    ) {
        theme = currentLocalStorageTheme;
    } else {
        theme = currentlySetSystemColorScheme;
    }

    document.querySelector('html')?.setAttribute('data-theme', theme);
    setLocalStorage(theme);
}
From design to dev
Case: Improving task management and note taking for personal use
Contextual Use Scenarios: your favorite UX design driver
Some notes about dark themes
Cito Custom Properties
Cito Theme Controller
Perceived lightness
Atrophy
Strategic misrepresentation
Wrong problem