By Paul Scanlon

Understanding Theme UI: 1 - Jsx Pragma

  • JavaScript
  • React
  • Theme UI

In this post Iā€™m going to try and explain Theme UIā€™s Jsx Pragma. I hope to create a series of these posts that might help lower to the barrier to entry when learning Theme UIā€¦ letā€™s see how that goes ay!

Iā€™ll assume at this point youā€™ve already installed Theme UI but if you havenā€™t, have a read of the Getting Started section from the docs

Before starting to explain the Jsx Pragma Iā€™m going to walk you through some steps which I feel are important to understand. The explanation might be a little convoluted but bear with me and hopefully once you reach the Jsx Pragma section itā€™ll make more sense.

To help demonstrate some of the Theme UIā€™s principles weā€™re going to build a very simple component which you can see below, iā€™ve called it <MrPragma /> and you can find the src here

Theme Object

A core principle of Theme UI is the theme object itā€™s a little bit like global CSS but without all the headaches.

This is key to understanding how Theme UI works so feel free to bookmark the theme-spec page as iā€™ll be referring it frequently.

When your first start your site after installing Theme UI youā€™ll notice the background is a kind of fuchsia color. Thatā€™s fine, it means Theme UI is working and is applying its default styles.

Depending on which install method youā€™ve used will determine the file name and location of the theme object. Iā€™m going to base this post on the install method for gatsby-plugin-theme-ui

To change the default background and text colour youā€™ll need to add a colors key to the theme object that contains key value pairs for both text and background

// src/gatsby-plugin-theme-ui/index.js

export default {
  colors: {
    text: '#FFFFFF',
    background: '#131127',
  },
};

By default Theme UI will use text and background to style the body color and the body background-color and before we go any further Iā€™d like to explain why.

Theme UIā€™s opening gambit if you like is as follows:

Build themeable design systems based on constraint-based design principles

The bit iā€™d like to point out is where it says ā€œconstraint-based design principlesā€. Theme UI makes some decisions for us so we donā€™t have to, and when working with CSS some constraints are actually really really helpful. In a later post Iā€™ll explain how to use Theme UIā€™s escape hatches if you donā€™t want or canā€™t in some scenarios work with the constraints

CSS Property maps

This is my opinion is one of the hardest concepts to grasp. The TLDR is Theme UI has made decisions regarding which CSS properties map to which objects in the theme object. The HTML color and background-color are mapped to the colors object which is why the changes above will have an effect on your overall site theme. More on this later

Object-oriented Programming (OOP):

Theme UI uses OOP to allow access to CSS properties defined in the theme object.

As a practical example go ahead and create a <MrPragma /> component and ensure you can render it to a page as weā€™ll need to see the output of a console.log()

// MrPragma.js

import React from 'react';
import theme from '../gatsby-plugin-theme-ui';

console.log(theme);

export const MrPragma = () => {
  return <div>MrPragma</div>;
};

The above will log out the entire theme object. You should see all the default styles and if youā€™ve implemented the above change to colors you should see that text and background are the same as the values youā€™ve defined.

To go one step further change the console.log() so it only logs out the values for the text key

// MrPragma.js
import React from "react"
import theme from "../gatsby-plugin-theme-ui"

- console.log(theme)
+ console.log(theme.colors.text)

export const MrPragma = () => {
  return <div>MrPragma</div>
}

And now finally use this text value to style the <div />

// MrPragma.js

import React from "react"
import theme from "../gatsby-plugin-theme-ui"

console.log(theme.colors.text)

export const MrPragma = () => {
  return (
    <div
+     style={{
+       color: theme.colors.text,
+      }}
    >
      MrPragma
    </div>
  )
}

šŸšØšŸšØ This is NOT how you use Theme UI šŸšØšŸšØ

ā€¦ but it does go some way to understanding what the theme object is and how you can access key value pairs contained within it.

Jsx Pragma

In the next step Iā€™ll explain how to achieve the same thing but by leverageing Theme UIā€™s super power, The Jsx Pragma.

Step One

W.T.Flip is Jsx Pragma?ā€¦ well, to quote the Gatsby docs

A pragma is a compiler directive. It tells the compiler how it should handle the contents of a file.

You can take from that what you will but in short the Jsx Pragma allows Jsx to compile things in a special way. In the case of Theme UI we need the compiler to understand and compile something called The sx Prop and it looks like the below.

Theme UIā€™s Jsx Pragma already includes React so youā€™ll notice in the below iā€™ve removed the React import

// MrPragma.js

+ /** @jsx jsx */
+ import { jsx } from "theme-ui"
- import React from "react"
- import theme from "../gatsby-plugin-theme-ui"

- console.log(theme.colors.text)

export const MrPragma = () => {
  return (
    <div
+     sx={{}}
-     style={{
-       color: theme.colors.text,
-      }}
    >
      MrPragma
    </div>
  )
}

If youā€™re familiar with HTML youā€™ll know that sx isnā€™t a valid HTML attribute but by including Theme UIā€™s Jsx Pragma the compiler understands what it is and will know what to do with it before the Jsx is returned to the browser.

Step Two

Use the sx prop to style a <div />

// MrPragma.js

/** @jsx jsx */
import { jsx } from "theme-ui"

export const MrPragma = () => {
  return (
    <div
     sx={{
+     color: "text"
     }}
    >
      MrPragma
    </div>
  )
}

Youā€™ll notice here that text is a string. The word or string ā€œtextā€ in CSS wouldnā€™t normally mean anything since CSS will be expecting an actual hex reference for a color property e.g: #FFFFFF but since the sx prop is compiled using the Jsx Pragma Theme UI is able to look up what the string value refers to in theme object.

The reason you donā€™t need to write theme.colors.text is because Theme UI shorthands the OOP lookup for us by mapping CSS properties of certain types to a constrained set of objects from the theme object

This is a small glimpse into Theme UI making decisions for us

In the case of the CSS property color Theme UI will map it to theme.colors which does indeed contain the key value pair of text

Moreover if we introduce a new colour to the theme object called surface and give it a hex value we can then use it with another CSS property that is also mapped to the colors object

// src/gatsby-plugin-theme-ui/index.js

export default {
  colors: {
    text: "#FFFFFF",
    background: "#131127",
+   surface: "#232140"
  },
}
// MrPragma.js

/** @jsx jsx */
import { jsx } from "theme-ui"

export const MrPragma = () => {
  return (
    <div
      sx={{
        color: "text",
+       backgroundColor: "surface",
      }}
    >
      MrPragma
    </div>
  )
}
diagram of theme object map

The relationship between the CSS properties and where in the theme objet Theme UI will shorthand the lookup is detailed in the Theme Scales

The first part of the Theme Scales table explains the following:

Theme KeyCSS Properties
colorscolor, background-color, border-color

This means that whenever youā€™re applying a CSS property of color, background-color or border-color Theme UI will automatically look to the colors object and return the resulting value.

This is just an introduction to Theme UI and in later posts iā€™ll be explaining the relationship between CSS properties and the theme object in more depth, so stay tuned and give me a follow on Twitter šŸ•ŗ

Hey!

Leave a reaction and let me know how I'm doing.

  • 0
  • 0
  • 0
  • 0
  • 0
Powered byNeon