Design tokens technical implementation

Pajamas components

When you use a Pajamas component, you're automatically using design tokens under the hood. Use Pajamas components as your first approach when implementing a UI.

CSS utilities

If you need something more custom or you need to customize a Pajamas component, CSS utilities can help you out. Since these are powered by Tailwind, your IDE will be able to autocomplete, see the documentation for available classes.

For predictable styling between color modes use semantic design token utility classes, for example, .gl-text-subtle or .gl-bg-default. Using color scale values directly like .gl-text-green-900 or .gl-bg-white with utility classes is deprecated. Constant design tokens are not currently exposed as CSS utility classes for use as they do not provide values for color modes.

There are multiple ways to apply these utility classes. For the current guidance on how best to do this, please refer to the SCSS style guide.

CSS custom properties

While utility classes handle most styling needs, sometimes you need to work directly with a design token in a more flexible way. For these cases, CSS custom properties (also known as CSS variables) let you apply a design token to a specific CSS properties not covered by a utility class.

For example, to change the caret color of an input (don't actually do this), use a design token like so:

.exampleInput {
  caret: var(--gl-text-color-info);
}

Remember to use them semantically. Don't use info if you only want the color blue. In different modes, info may be a different color. So only use that token if the element it applies to is an informational element.

Dark mode

When you use design tokens correctly (focusing on their semantic meaning rather than specific colors), dark mode for your UI elements works out of the box.

However, there are times when you might need to change how something behaves in dark mode. Before implementing a custom dark mode style, ask yourself three times: "Do I really need to deviate from the standard pattern?" Consult with the design systems team, they can help determine if this is truly a gap in our design system that needs addressing.

Using @apply

This is the preferred method. Use the @apply method to specify dark variants inline. For example, to override a subtle background in dark mode:

<div class="gl-bg-subtle dark:gl-bg-neutral-900">
  <!-- Content -->
</div>
.my-component-class {
  @apply gl-bg-subtle dark:gl-bg-neutral-900;
}

See the SCSS style guide for additional guidance on utility classes in HTML directly (preferred) vs. component classes (when necessary).

Always override a semantic token with specific color token:

  • @apply gl-bg-subtle dark:gl-bg-neutral-900
  • @apply gl-bg-neutral-10 dark:gl-bg-neutral-900
  • @apply gl-bg-subtle dark:gl-bg-section

Whilst this is the preferred method, it still comes with side-effects and should only be used when necessary.

Legacy Approaches

.gl-dark Selector (Deprecated)

In the olden days, you could add dark mode overrides with the .gl-dark selector. Today, you still can, but this approach is deprecated as it doesn't scale for additional color modes and requires manual updates with parent CSS selectors:

.exampleSelector {
  color: black;

  .gl-dark & {
    color: white;
  }
}

While you'll see this pattern in our codebase, we are actively phasing it out. If you believe you have a legitimate reason to use .gl-dark, reach out to the design system team - this likely indicates a gap in our design system that we need to fix.

Last updated at: