Discovering Theme UI
Laurie
Posted on May 12, 2020
Originally posted on laurieontech.dev
One of my first challenges in my new role has been to make changes to gatsby-plugin-theme-ui. As it turns out, it's a pretty sparse plugin, more of a passthrough than anything.
So, how hard could adding functionality be?
As it turns out, quite difficult if you've never used Theme UI in your life! I consider myself a bit of a global styles girl. My closest experience with CSS-in-JS is the way Vue does scoped styles. Which is to say, not really close at all.
But over the past few weeks I've learned quite a bit and thought I'd share it with you all.
A "theme"
Theme UI works off of a "theme". I know, only slightly confusing since I work on Gatsby themes 😅.
In this case a theme is a JSON object that specifies styling in a number of different ways. You can checkout the base preset for an example of what I mean.
A theme can include various things. The most common is theme.colors
that defines a series of colors such as primary
, background
, etc.
Themes can also specify typography with fonts
, fontSizes
, lineHeights
and more.
The part of themes I spent a lot of time digging into was theme.styles
. Much of what gets included in styles feels very familiar to global CSS people like me. You can assign styling for specific HTML tags such as h1
, p
, etc.
When I first started working with the theme.styles
object I assumed it was applying the styling to the h1
tags in my site, but it didn't appear to be! I was missing something pretty important to understanding Theme UI.
MDX
Theme UI was designed in large part to support styling MDX files. Seems natural that Gatsby uses it once you realize this!
So, as it turns out, my h1
tags do automatically receive my styles. However, it's only the h1
tags that are generated from MDX.
# Like this!
h1
's in my JavaScript files have to do something else. But I'll get back to that in a second.
pre
Once I realized that theme.styles
is for MDX styling I started to understand the internal objects a lot better. One of those objects is theme.styles.pre
. I've been playing around with theme.styles.pre
quite a bit lately, and for good reason. When shadowing themes in Gatsby, code snippets in MDX get wrapped by a Prism component, like this.
import Prism from "@theme-ui/prism"
export default {
pre: props => props.children,
code: Prism,
}
When this happens, the Prism
component uses prism-react-renderer
to tokenize code snippets and create <span>
elements with class names. This allows Theme UI to target those class names with styles found in the theme.styles.pre
object.
Which means I can do something like this:
styles: {
pre: {
".variable": {
color: `#6F0DAB`,
},
}
}
Pretty cool stuff! Plus, it means I can take advantage of a number of prism presets Theme UI has available in its repo.
sx prop
Once I understood that theme.styles
was for MDX, the sx
prop made a lot more sense. sx
allows you to make use of your Theme UI styles inside JSX. This can be inline styles, or reference your theme
object directly.
/** @jsx jsx */
import { jsx } from 'theme-ui'
<div
sx={{
color: 'primary',
bg: '#FFC0CB',
}}
>
Let's test this out!
</div>
Note the pragma up top! That's essential in order to leverage this feature.
Theme composition
One of the most interesting pieces of using Theme UI is the way styles compose. For example, when leveraging Gatsby themes, local styles perform a deep merge with whatever the theme sets. This allows you to make small changes without overriding everything.
What's Next?
As it turns out, gatsby-plugin-theme-ui
can do more than it's doing right now. Make it easier to use the theme and prism presets that are available. Make it simpler to share those between projects.
Excited to finish up some new functionality and see what amazing things the community does with it. Theme UI is incredibly powerful, I might even give up my global styles 😜.
Posted on May 12, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.