question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Fresh eyes needed. We should also take inspiration from https://theme-ui.com/

We can even create a TS language service to tell us what themes are available with intellisense!

Global theming

Define your tokens in your options:

{
  base: {},
  default: {},
  [optionalotherthemes]: {} // every other theme needs to have the same keys from default
}

Then use them in your CSS sourced from default:

css`
  color: primary; // or
  color: theme(primary);
`

Transforms to:

color: #fff;
color: var(--var-123abc);

Hardcodes and use the variable so it works with/without a parent theme.

Prepare a theme provider for consumers (you should only ever create one of these):

import { createThemeProvider } from '@compiled/css-in-js';

export const ThemeProvider = createThemeProvider();

// Optional "runtime" themes.
export const ThemeProvider = createThemeProvider({ ... });

Transforms to:

import { _TP } from '@compiled/css-in-js';

const theme = { base: { ... }, default: { '--var-abc123': '#000', ... }, ... };
// optional runtime themes would be merged in and converted to css variables

export const ThemeProvider = (props) => (
  <_TP theme={props.theme}>
   {props.children(theme[props.mode])
  <_TP>
);

And then your consumers use like:

import { ThemeProvider } from 'your-design-system';

const App = () => (
  <ThemeProvider theme="dark">
     {style => <div style={style}>...</div>
  </ThemeProvider>
);

Component theming

Would be the same as above with one key difference - the theme isn’t sourced from the config. It’s sourced inline.

import { createVariants } from '@compiled/css-in-js';

const useVariants = createVariants<'primary' | 'danger'>({
  default: { default: {}, [optionalotherthemes]: {} },
  [optionalotherthemes]: {},
});

<button style={useVariants('primary')} css={{ border: 'border', color: 'color' }}>
  blah
</button>
import { useMode } from '@compiled/style;

// transformed to css variables
const variants = { default: {}, ... };

const useVariants = (variant: string) => {
  const mode = useMode();
  const defaultVariant = variants.default;

  return { 
    ...defaultVariant.default,
    ...defaultVariant[mode],
    ...variants[variant][mode],
  };
};

The type safety aspect is missing a little. Perhaps instead of using string literals theme(primary) and variant(color) we could import them?

import { themeRefs, createVariants } from '@compiled/css-in-js'; 

const { useVariants, variant } = createVariants({});
const theme = themeRefs();

<div
  style={useVariants('primary')}
  css={{
    backgroundColor: variant('backgroundColor'),
    color: theme('primary'),
  }}
/>

???

Goals

  • Minimal use of react context
  • Css variables for passing style values around
  • Don’t force specific markup to consumers
  • Ensure bleeding of css variables doesn’t affect things it shouldn’t

Lingering thoughts

  • What about runtime themes (i.e. they aren’t known until runtime)?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:12
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
okonetcommented, Apr 25, 2021

Could the problem be split into two? Compile-time and runtime? I think most of us here are interested in compile-time since runtime is well covered by existing CSS-in-JS solutions.

1reaction
itsdougescommented, Apr 25, 2021

Hey! Thanks. Agreed when we start tackling theming we’ll want to make sure theme variables are available in the head, which side-steps some gnarly issues with portaling.

Like variants for a particular region of the page. I don’t know why people would do this, but it’s something only the library could support.

Atlassian has a few use cases for this across a few products interestingly. Media components are always shown in “dark mode” for example.

We should be able to ensure any known theme (CSS) variables are in the head. It’s the “values not known until runtime” that is a bit more difficult. The easy answer is flushing it through inline styles, however the portaling issue comes up that needs either a good solution, or good example patterns to work with it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

RFC Theme - song and lyrics by Breakmaster Cylinder - Spotify
Listen to RFC Theme on Spotify. Breakmaster Cylinder · Song · 2016.
Read more >
RFC: theme emacs with a 6-color palette with semantics theming
Inspired by work of u/Nicolas-Rougier, I have developed a package to give a coherent look to emacs, based on a palette of just...
Read more >
Re: [community-group] [RFC] Theming (#2) - Mailing lists - W3C
However, since this thread is discussing possible approaches to support theming use-cases, I do think it's worth considering and debating ...
Read more >
‎RFC Theme by Breakmaster Cylinder - Song on Apple Music
RFC Theme. Breakmaster Cylinder Songs for Broadcast, Part. III. Song. Play. United States. Español (México) · العربية · Русский · 简体中文 ...
Read more >
Rfc designs, themes, templates and downloadable ... - Dribbble
Rfc. Inspirational designs, illustrations, and graphic elements from the world's best designers. Want more inspiration? Browse our search results.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found