Skip to content

Expose non-color theme values as CSS Variables #979

Description

@iampava

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions