/themeit

Modern Web implementation of a theme switcher

Primary LanguageTypeScriptMIT LicenseMIT

ThemeIT! (Theme Switcher)

Monarch butterfly hatched from a cocoon

Image: Monarch Butterfly hatched from a cocoon.

A lightweight browser native way to switch color themes. ThemeIT! follows the Modern Web implementation for css theming and leverages the awesome power of CSS variables and HTML link element + with Javascript to allow theme customization inside of your web app, react app or website.

Package information

@themeit/native

Detail Value
Version 1.1.1
Size 5.0 kB
Size (gzip) 2.0 kB
SHASUM 7aa83b7f67a48d3612dd535c1ec073a3c940223f
Dependency (count) 0

@themeit/react

Detail Value
Version 1.1.1
Size 3.7 kB
Size (gzip) 1.7 kB
SHASUM acc3e0e127a8437e13878960917a939482b67e46
Dependency (count) 2

Install

npm

npm install @themeit/native
npm install @themeit/react # If you support React

yarn

yarn add @themeit/native
yarn add @themeit/react # If you support React

Setup instructions

Step 1 (Prep work)

  1. Prepare your CSS by separating each theme into it's own CSS file.
  2. Use the :root pseudo-class for setting all variables.
  3. Make sure that all variables match.

You can look at the examples/ directory to get a visual representations of what needs to be done

Step 2 (Loading CSS)

  1. Add all CSS theme files inside of your HTML file.
  2. Set the media(prefers-color-scheme: <name>) attribute for each theme
  3. For the main theme please set the following (prefers-color-scheme: light) as the media attribute.

Important when setting the (prefers-color-scheme: <name>) the <name> will be used by ThemeIT! internally and externally. This key/name will be used by you when you want to change the theme using ThemeIT!. Please name them accordingly.

How to use (Javascript/Typescript)

Initialize

Import ThemeIT! and call init method in root file before using any other methods. (Do this after Setup instructions).

  1. Argument #1 defaultTheme what theme should be set as the initial theme. (Default: auto)
  2. Argument #2 autoLoad whatever you should load the defaultTheme during initialization.
import { init } from "@themeit/native";

init("my-theme", true)
import type { DefaultTheme } from "@themeit/native";
import { init } from "@themeit/native";

// DefaultTheme = "auto" | "light" | "dark";
type MyThemes = DefaultTheme | "my-theme";

init<MyThemes>("my-theme", true)

System theme

The default option of ThemeIT! is to use the system theme. This is the out-of-the-box behavior so no setup is needed. To toggle this feature programmatically you can use useTheme("auto").

Change theme

To change themes please use the useTheme method. Make that the name here matches the one you used when setting media(prefers-color-scheme: <name>) of CSS file.

// Javascript
import { useTheme } from "@themeit/native";

const myNewTheme = "my-theme";
useTheme(newTheme);
// Typescript
import { useTheme } from "@themeit/native";

type MyThemes = "auto" | "my-theme";

const myNewTheme = "my-theme";

useTheme<MyThemes>(newTheme); // Nice autocomplete :D

Get theme

To get the current theme use the getTheme method.

// Javascript
import { getTheme } from "@themeit/native";

const theme = getTheme();
// Typescript
import { getTheme } from "@themeit/native";

type MyTheme = "auto" | "dark" | "my-theme";

const theme = getTheme<MyTheme>();

Get all themes

To get all the themes available use the getThemeList method.

// Javascript
import { getThemeList } from "@themeit/native";

const themeList = getThemeList();
// Typescript
import { getThemeList } from "@themeit/native";

const themeList: Array<string> = getThemeList();

How to use (React)

Initialize

Import @themeit/react and setup the ThemeProvider in root file before using any other methods. Note that ThemeProvider should be above React.StrictMode as it won't work the other way around. (Do this after Setup instructions).

ThemeProvider Props:

  1. defaultTheme – what theme should be set as the initial theme. (Default: auto)
  2. autoLoad – whatever you should load the defaultTheme during initialization.
// Javascript
import { ThemeProvider } from "@themeit/react";

ReactDOM.createRoot(document.getElementById("root")).render(
 <ThemeProvider defaultTheme="my-theme" autoLoad>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ThemeProvider>
);
// Typescript
import { ThemeProvider } from "@themeit/react";

type CustomThemes =  "light" | "dark" | "my-theme";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
 <ThemeProvider<CustomThemes> defaultTheme="my-theme" autoLoad>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ThemeProvider>
);

Actions

To change the theme use the useTheme hook from @themeit/react. The hook returns a tuple with [state, action] we are interested in the action here.

Action Props:

  1. changeTheme – Call to change the current theme of the browser.
import { useTheme } from "@themeit/react";

const MyApp = () => {
   const [_, { changeTheme }] = useTheme();

   return (
      <button onClick={() => { changeTheme("dark") }}>
      Turn of the lights!
      </button>
   )
}
import { useTheme } from "@themeit/react";

type MyThemes = "light" | "dark" | "my-theme";

const MyApp = () => {
   const [_, { changeTheme }] = useTheme<MyThemes>();

   return (
      <button onClick={() => { changeTheme("dark") }}>
      Turn of the lights!
      </button>
   )
}

State

To get the current theme use the useTheme hook from @themeit/react. The hook returns a tuple with [state, action] we are interested in the state here.

State Props:

  1. theme – Current theme of ThemeIT!
  2. themeList – All themes available for ThemeIT!
// Javascript
import { useTheme } from "@themeit/react";

const MyApp = () => {
   const [{ theme }] = useTheme();

   return (
      div>
         <h1>
            The curren theme is: {theme}
         </h1>
         <code>
         {JSON.stringify(themeList, null, 2)}
         </code>
      </div>
   )
}
// Typescript
import { useTheme } from "@themeit/react";

type MyThemes = "light" | "dark" | "my-theme";

const MyApp = () => {
   const [{ theme, themeList }] = useTheme<MyThemes>();

   return (
      <div>
         <h1>
            The curren theme is: {theme}
         </h1>
         <code>
         {JSON.stringify(themeList, null, 2)}
         </code>
      </div>
   )
}

Contribution

The project could use support for: Vue, Angular, NextJS, Svelte and Remix.run. If you are willing to contribute please follow CONTRIBUTE.md for more information.