Theme-ui: Expose theme values as CSS Variables

Created on 4 Jun 2020  路  4Comments  路  Source: system-ui/theme-ui

Right now we can't use theme values when styling native HTML elements. We have to either

  1. Wrap them in custom components <H1>, <H2>, etc
  2. Use the sx prop

I'd like to extend ThemeProvider with the ability to expose theme values as CSS Variables so that in a stylesheet we could do something like:

h1 {
  margin: var(--space-3);
  font-size: var(--font-sizes-3);
}

h2 {
  margin: var(--space-2);  
  font-size: var(--font-sizes-2);
}

I've already done this (just for the colors property as a proof of concept), here's the code:

import React, { useRef, useEffect } from 'react';
import { ThemeProvider, ThemeProviderProps, Theme, useThemeUI } from 'theme-ui';

export const ThemeAdapter = (props: ThemeProviderProps<Theme>) => {
  const ref = useRef(null);
  const { theme: outerTheme } = useThemeUI();

  useEffect(() => {
    const theme =
      typeof props.theme === 'function' ? props.theme(outerTheme) : props.theme;

    Object.entries(theme?.colors || {}).forEach(([key, value]) => {
      ref.current.style.setProperty(`--colors-${key}`, value);
    });
  });

  return (
    <div ref={ref} className='theme-ui-adapter'>
      <ThemeProvider {...props} />
    </div>
  );
};

Thus, any elements inside the <div className="theme-ui-adapter"> can make use of the CSS Variables. Also, because of the way scope works, we have theme/sub-theme functionality by default.

enhancement

Most helpful comment

I don't think this sort of functionality should be part of the core packages, but I think you could achieve what you're looking for in the @theme-ui/custom-properties package as an additional export, if you want to look into a PR there then go for it!

All 4 comments

You might be interested in this package: https://github.com/system-ui/theme-ui/tree/master/packages/custom-properties -- it's missing a few nice-to-have features, so PRs are welcome :)

Yep, seen it. Could be used to create the name/value pairs, but it doesn't fix the need for adjusting code inside ThemeProvider (as in the snippet above).

Or maybe, we could export a HOC from there, and use it something like

import { ThemeProvider } from 'theme-ui`;
import { withCustomProperties } from '@theme-ui/custom-properties';

export const ThemeAdapter = withCustomProperties(ThemeProvider);

What do you think?

PS: I'd be happy to do the PRs, but first "point me in the right direction" as it's said :D

I don't think this sort of functionality should be part of the core packages, but I think you could achieve what you're looking for in the @theme-ui/custom-properties package as an additional export, if you want to look into a PR there then go for it!

Great! I'll work on it as soon as possible. Thanks for the input

Was this page helpful?
0 / 5 - 0 ratings

Related issues

moshemo picture moshemo  路  3Comments

blummis picture blummis  路  4Comments

VinSpee picture VinSpee  路  3Comments

muhajirdev picture muhajirdev  路  3Comments

K-Kit picture K-Kit  路  4Comments