Building from the Box

Use the versatile Box as your component foundation.

This a follow up post exploring how the power of the sx prop can be used by a single component, the Box, to build up a system of common UI elements.

If you aren't familiar with the sx prop, I recommend checking out this tidbit in my previous post or from the Theme UI documentation.

The humble Box

The Box component is used primarily as a layout primitive to add margin, padding, and colors to content.

In the last post, we implemented a minimal Box component that has the powers of the sx prop baked-in (i.e. without the need for the JSX pragma).

In this version, our Box will also have a private __css prop which will be used to apply base styles for our component, freeing up the sx prop to be used for override styles.

The base styles passed via the __css prop are parsed just like the sx prop. However, by splitting the base styles and sx styles (which we can think of as inline style overrides) into two props, we let Emotion handle the complex merging of object styles. This will hopefully make more sense after seeing how __css is used in a bit!

A quick comparison

We can use both the sx and __css props similar to how the css prop is used in Emotion. Here is an example taken from the Emotion docs using the css prop.

The same result can be created using the Box component, but without the need to import our JSX pragma and with the enhanced features of the sx prop.

Creating new components

By integrating the power of the sx prop into our Box, we can use this as a base component for building other foundational components. Let's create a few more commonly needed UI pieces.

We use React.forwardRef to automatically pass a ref through to our root Box component. This allows users of these foundational components to obtain a ref to the inner DOM element if needed.

If you are curious, check out the React documentation for more on forwarding refs.

Lastly, we will need some theme values to define our design constraints. Here is a simple, sample theme object based on the Theme UI Base Preset.

Just a quick note on the color values used. I'm reusing some already defined CSS custom properties that are being used for this site, e.g. var(--colors-text). This just makes the next example look nice for both light and dark themes.

Theme UI does have a color modes feature which you can also leverage if your application needs to support multiple modes.

Putting them to use

The above Box-based components all have the sx prop baked-in. When necessary, we can sprinkle in any style customizations leveraging the design constraints from our theme.

Now that we have some bits of UI, let's compose a name input for our application.

Wrapping up

In summary, the Box is a versatile foundation component that can be using as a building-block to create other components. Adding the flexible styling feature of the sx prop to the Box shares this capability to all other components created from Box. This creates a simple, consistent styling pattern across components that leverages the theme to promote styling with defined design constraints.

Note: This technique is mostly experimental and an exploration of the component styling pattern used by Theme UI. Applying this pattern at scale for a large component library would need some added refinement and probably best to do in TypeScript 💙

If this was interesting, I encourage you to check out the Theme UI source code for a more detailed look:

Here is a full example in CodeSandbox of the above all pieced together.

Subscribe to the newsletter

Be the first to know when I post something new! Thoughts about code, design, startups and other interesting things.

© 2022 Sam Rose
All Rights Reserved.