Create utilities


Style utilities are general-purpose helpers for your components. If you ever need to slap a box-shadow on an existing component, style utilities are what you need to stop Warhol from complaining about unexpected styles the component in question has. If we just re-use the pattern library from before and add a shadow to a button component in production, the result is predictable:

The error message's description is not wrong, but what if we want to be able to add a shadow to a button or any other component?

How utilities work #

Style utilities enable us to essentially whitelist certain modifications to the styles of select components, which will stop Warhol from reporting things like additional shadows or adjusted text alignment as errors.

Warhol can read style utilities from your pattern library like it can read the color palette and component styles. Utilities are somewhat special in that you will probably want to be sure that you only whitelist precisely the properties that you have in mind for your utility. There are two style utility sources that Warhol can use:

  • An element in your pattern library, which must only contain the styles that you want to use in your utility. When you use elements as utility sources you must be absolutely certain that only these styles apply to the element.
  • A CSS rule from for pattern library that sets the styles that you want to use in your utility. Compared to elements, it's easier to pick only the right styles for a utility but it makes Warhol depend on some implementation detail of your pattern library.

Utilities are finicky and you should probably read the more detailed explanation in the configuration documentation before you use utilities in your production project. For now, let's power right ahead. Just remember:

  • Utilities are whitelists for style errors on components
  • Utilities only work on components (not on children or non-components)
  • Elements and CSS rules can serve as sources for utilities

Now let's fix our shadow problem!

Adding utilities #

A shadow utility is a great candidate for a utility that we can source from an element. Just add the following to the pattern library:

<div class="shadow-util" style="box-shadow: black 0 0 1em;">
  <p>Placeholder text for box-shadow</p>
</div>

Our pattern library is slowly getting more and more complex, but we can still be sure that only the box-shadow property applies to the div with the class shadow-util. Now we only need to point Warhol to just this div and configure this as a utility source. Let's go to the web app, open up the pattern library configuration and replace null in the “Utils” field with the following:

{
  "sources": [
    {
      "type": "element",
      "selector": ".shadow-util",
      "name": "Shadow utility"
    }
  ]
}

This is probably pretty self-explanatory for you at this point. As usual, the name field is optional and defaults to the selector. When we save the pattern library configuration, re-generate the snapshots and re-download the snapshots into the browser extension, we can see the utility listed in the patterns tab in the devtools panel:

As for the tests, well 

To be positive: the component's name “Basic button + Shadow utility” tells us that Warhol has managed to read and apply the utility styles to the component. Warhol has also stopped complaining about the unexpected CSS declarations and instead now mopes about the shadow color not conforming to the theme. And that's not wrong: there is, after all, no black allowed in our color palette. Every color that you use on a page must be a theme color, down to the last shadow's alpha component. Updating this example's pattern library to make the production page pass without any error is left as a (very trivial) exercise for the reader.

Element utilities vs. rule utilities #

If your pattern library is more complex than our simple example, creating isolated examples for utilities may not be easy. Global styles can make it next to impossible to create elements that contain nothing but the utility styles and such elements, if possible, may be not of much use to your pattern library's human users. Rule utilities are an alternative way to define utilities that have different trade-offs from element utilities and may be a better fit for what you try to accomplish.

With rule utilities, you do not need to build an example element. Instead you just specify selectors for CSS rules and Warhol builds the example element automatically. For each rule utility, Warhol creates a <div> element in an isolated sandbox, applies the CSS declarations from the rule utility's to the element's inline styles and then records the element's styles just like an element utility. This isolates the CSS in question from any global styles that may interfere, but also ties your utility to an implementation detail of your pattern library.

For our shadow utility, as long as we have some style sheet in our pattern library that contains a rule like this 

.shadow {
  box-shadow: black 0 0 1em;
}

and we update the type field in the utility configuration 

{
  "sources": [
    {
      "type": "rule",
      "selector": ".shadow",
      "name": "Shadow utility"
    }
  ]
}

we get back an equivalent utility from before, just defined and built in a slightly different way.

Key takeaways #

  • Use utilities to allow well-defined deviations from a component's usual styles
  • Do not go crazy with utilities! They are tricky to get right and can have very far-reaching consequences. It is often better (and simpler and, for the human consumers of your pattern library, much more clear and intuitive) to define a few extra component variants.

Join our Slack Community

Any question not answered yet? You want to get the latest information on Warhol and discuss new features? Join our Slack Community.