>

Theme Toggle

Theme Toggle

Theme Toggle

Light / Dark mode toggle for Framer websites.

Theme toggle for Framer websites
Theme toggle for Framer websites
Theme toggle for Framer websites

Let your visitors choose between light and dark mode using this theme toggle override for Framer.

The toggle works with the Framer built-in light/dark color system, making it easily integrable with new or existing projects.

All you have to do is:

  1. Copy the code below (or remix the project).

  2. Paste the code in a new code override in your project.

  3. Apply it to any frame on your website.

And voilà! You know have a perfectly functioning toggle on your website.


import type { ComponentType } from "react"
import { addPropertyControls, ControlType } from "framer"
import React, { useEffect, useState } from "react"

function getOSTheme() {
    if (typeof window !== "undefined" && typeof document !== "undefined") {
        return window.matchMedia &&
            window.matchMedia("(prefers-color-scheme: dark)").matches
            ? "dark"
            : "light"
    }
    return "light"
}

function setInitialState() {
    const osTheme = getOSTheme()
    const currentToggleState =
        localStorage.getItem("currentToggleState") ||
        (osTheme === "dark" ? "dark" : "light")
    localStorage.setItem("currentToggleState", currentToggleState)

    if (typeof document !== "undefined") {
        const styleTag = document.getElementsByTagName("style")[0]
        const newCSS = styleTag.innerHTML.replace(
            /prefers-color-scheme: \w+/,
            `prefers-color-scheme: ${
                (currentToggleState === "dark" && osTheme === "dark") ||
                (currentToggleState === "light" && osTheme === "light")
                    ? "dark"
                    : "light"
            }`
        )
        styleTag.innerHTML = newCSS
    }

    return currentToggleState === "dark"
}

export function themeSwictherBasedOnSystem(Component): ComponentType {
    return (props) => {
        const [isOn, setIsOn] = useState(setInitialState())

        const toggle = () => {
            const newToggleState = !isOn ? "dark" : "light"
            setIsOn(!isOn)
            localStorage.setItem("currentToggleState", newToggleState)
            if (typeof window !== "undefined") {
                window.dispatchEvent(new CustomEvent("themeChange"))
            }
        }

        useEffect(() => {
            if (typeof window !== "undefined") {
                const mediaQuery = window.matchMedia(
                    "(prefers-color-scheme: dark)"
                )
                mediaQuery.addListener((e) => {
                    const newTheme = e.matches ? "dark" : "light"
                    localStorage.setItem("currentOsTheme", newTheme)
                    localStorage.setItem("currentToggleState", newTheme)
                    setIsOn(newTheme === "dark")

                    if (typeof document !== "undefined") {
                        const styleTag =
                            document.getElementsByTagName("style")[0]
                        const newCSS = styleTag.innerHTML.replace(
                            /prefers-color-scheme: \w+/,
                            `prefers-color-scheme: ${
                                (newTheme === "dark" && newTheme === "dark") ||
                                (newTheme === "light" && newTheme === "light")
                                    ? "dark"
                                    : "light"
                            }`
                        )
                        styleTag.innerHTML = newCSS
                    }

                    window.dispatchEvent(new CustomEvent("themeChange"))
                })
            }
        }, [])

        useEffect(() => {
            if (
                typeof window !== "undefined" &&
                typeof document !== "undefined"
            ) {
                const currentToggleState = isOn ? "dark" : "light"
                const currentOsTheme =
                    localStorage.getItem("currentOsTheme") || getOSTheme()

                const styleTag = document.getElementsByTagName("style")[0]
                const newCSS = styleTag.innerHTML.replace(
                    /prefers-color-scheme: \w+/,
                    `prefers-color-scheme: ${
                        (currentToggleState === "dark" &&
                            currentOsTheme === "dark") ||
                        (currentToggleState === "light" &&
                            currentOsTheme === "light")
                            ? "dark"
                            : "light"
                    }`
                )
                styleTag.innerHTML = newCSS

                localStorage.setItem("currentToggleState", currentToggleState)
            }
        }, [isOn])

        const [isClient, setIsClient] = useState(false)

        useEffect(() => {
            setIsClient(true)
        }, [])

        return <Component {...props} onClick={toggle} />
    }
}

Overview:

Light / Dark mode toggle for Framer websites.

Details:

Category

Override

Last Updated

Aug 7, 2024

Join Our Community

Receive updates on release dates, products, tips, and tutorials. No spam. Unsubscribe anytime.

Join Our Community

Receive updates on release dates, products, tips, and tutorials. No spam. Unsubscribe anytime.

Join Our Community

Receive updates on release dates, products, tips, and tutorials. No spam. Unsubscribe anytime.