varial
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

Varial

Varial provides UI theme support for React apps using CSS variables.

varial.init({
  variants: ['light', 'dark'],
  styles: { background: { light: 'white', dark: 'black' } },
});

function App() {
  const { variant, setVariant } = useVariant();
  const onClick = () => setVariant(variant === 'light' ? 'dark' : 'light');
  return (
    <button style={{ backgroundColor: 'var(--background)' }} onClick={onClick}>
      Toggle theme
    </button>
  );
}

ReactDOM.render(
  <VariantProvider>
    <App />
  </VariantProvider>,
  document.getElementById('root'),
);

Features

  • Multi-theme support using CSS variables – integrates with your preferred UI toolkit
  • Automatic user dark preference detection
  • Theme switch with React Context
  • Smooth initial theme load with pre-rendered React pages – avoid the "white flash"

Install

npm install varial

Initialization

The library must be initialized by providing a styles object that contains a mapping of global CSS variables as well as a variants array containing the names of all variants used in styles. Both regular key-value pairs as well as different values for each theme variant can be provided.

import varial from "varial";

const variants = ['light', 'dark'];

const styles = {
  greyDark: "hsl(215, 22%, 15%)",
  greyLight: "hsl(210, 17%, 98%)",
  background: {
    light: "var(--greyLight)",
    dark: "var(--greyDark)",
  },
  text: {
    light: "black",
    dark: "white",
  },
};

varial.init({ variants, styles, defaultVariant: "dark" });

This will create the following global CSS variables:

{
    --greyDark: hsl(215, 22%, 15%);
    --greyLight: hsl(210, 17%, 98%);
    --background: var(--greyDark);
    --text: white;
}

Calling varial.init is the bare minimum of using this library. Rest of the functionalities are optional.

Theme Control

The library exposes the current theme using React Context. Wrap your App with a VariantProvider:

import varial, { VariantProvider } from "react-varial";

varial.init({ styles });

ReactDOM.render(
  <VariantProvider>
    <App />
  </VariantProvider>
  document.getElementById("root")
);

Access and change theme in function components with the useVariant hook:

import { useVariant } from "react-varial";

function App() {
  const { variant, setVariant } = useVariant();
  return (
    <button onClick={setVariant(variant === 'light' ? 'dark' : 'light')}>
      Toggle theme
    </button>
  );
}

setVariant updates all the CSS variables created using your styles object with the values of the given variant.

Automatic Darkmode

Automatic darkmode is supported if your styles object contains variants named light and dark. Color preference detection can be enabled with the detectColorScheme option:

varial.init({ styles, detectColorScheme: true });

The color scheme will update real-time if the user changes their color preference in OS settings.

Avoid the "White Flash" With SSR

Regular SPAs that are not server rendered suffer from a brief flash of white on the initial load of the page. This can be somewhat jarring especially if the page has a dark theme. The flash happens because the HTML page is empty when it arrives to the browser, and it gets populated with markup only after some code has been executed.

Pre-rendered apps have existing HTML already when they arrive to the browser, so we can leverage some well timed scripting to update the page theme to match the user's preference before rendering anything.

The library provides a mechanism for injecting a script to the beginning of your page that will update the CSS variables to the selected variant before any other code is executed. That way your pre-rendered and contentful page will have the user's preferred color scheme on the very first render.

For example with Next.js, place ThemeScript as the first element of body in your custom Document:

import Document, { Head, Html, Main, NextScript } from "next/document";
import { ThemeScript } from "react-varial";

class MyDocument extends Document {
  /* ... */
  render() {
    return (
      <Html>
        <Head />
        <body>
          <ThemeScript />
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

Package Sidebar

Install

npm i varial

Weekly Downloads

6

Version

1.0.0

License

MIT

Unpacked Size

96.5 kB

Total Files

31

Last publish

Collaborators

  • jnuutinen