Design Tokens for Mesh have just been released!
Skip to content

Theme is central to how our whole design system functions. It is the single most important component in our design system. Our theme component is a Styled Components ThemeProvider that specifies fonts, colors, breakpoints, spacing sizes and more. Each app using Mesh components should have a single high-level theme wrapping the rendered output.

Components must be wrapped by this Theme

Our components rely on being rendered inside this Theme component, otherwise they will render with incorrect styling, no responsive styling or worse, break completely.

Installation

bash
npm install @nib-components/theme

Usage

jsx
import Theme, {nib} from '@nib-components/theme';
const App = () => (
<Theme theme={nib}>
{children}
</Theme>
);

Interactive demo

jsx

Requirements for use

There are two requirements which prevent problems with individual components rendering incorrectly:

  1. You should always include the Theme component once, at the root of your app.
  2. Never should an nib component be rendered outside of the Theme component.

Props

PropTypeDefaultDescription
theme (required)objectThe brand theme to use. Must be one of [nib, gu, iman].
modeobject{form: 'light'}The value of mode.form will override the theme.mode.form value in the theme passed down to all styled components via the ThemeProvider. Must have shape: {form: oneOf(['light', 'white'])}.

Selectors

Our components look to our theme for a lot of their styling information. Navigating the theme tree structure to find the value that you need can be tiresome. It also requires you to know the structure of the theme.

Selectors offer a shorthand to pull values from the theme. Below is a comparison between the two methods. As you can see, the selector pattern simplifies the process significantly. These selectors are mapped to every section of the theme and their values can differ based on the theme brand.

Navigating the theme structure:

jsx
const Heading = styled.h1`
font-family: ${props => props.theme.headings.h1.fontFamily};
font-size: ${props => props.theme.headings.h1.fontSize};
color: ${props => props.theme.colors.shades.darkest};
`;

Using theme selectors:

jsx
import {h1FontFamily, h1FontSize, colorDarkest} from '@nib-components/theme';
const Heading = styled.h1`
font-family: ${h1FontFamily};
font-size: ${h1FontSize};
color: ${colorDarkest};
`;

For the full list of selectors provided by the theme, see the selectors documentation.

Using selectors

These selectors are used by our design system components and should also be used for in-app styling.

Selectors should be used over the chained navigation of the theme to find the value you desire for simplicity, code readability and to protect against breakage if the theme's structure changes.

Color selectors

Color selectors are deprecated

With the introduction of design tokens, color selectors are considered deprecated. They will continue to work but do not source their values from tokens, and as such will not respond to their surrounding mode.

This is because these color selectors are not semantic and therefore would be difficult to point to a token as a sensible default value.

See tokens documentation for more information.

The most useful selectors are those that provide the colors used by the theme. These color selectors are:

Brand:

  • base: colorBrandBase
  • light: colorBrandLight
  • dark: colorBrandDark

Accent:

  • accent: colorAccent

Shades:

  • black: colorBlack
  • darkest: colorDarkest
  • darker: colorDarker
  • dark: colorDark
  • light: colorLight
  • lighter: colorLighter
  • lightest: colorLightest
  • white: colorWhite

Product:

  • hospital: colorHospital
  • extras: colorExtras
  • combined: colorCombined
  • hightlightBg: colorHighlightBg
  • hightlightText: colorHighlightText

Focus state selectors

We provide selectors for our standard focus styling across each brand. These selectors are:

  • outlineColor: focusOutlineColor
  • outlineStyle: focusOutlineStyle
  • outlineWidth: focusOutlineWidth
  • outlineOffset: focusOutlineOffset

These can be used to add our standard styling to the focus state of custom components:

jsx
&:focus-visible {
outline: ${focusOutlineWidth} ${focusOutlineStyle} ${focusOutlineColor};
outline-offset: ${focusOutlineOffset};
}

We also provide an equivalent shorthand utility for applying a standard focus style to interactive elements:

jsx
&:focus-visible {
${standardFocusStyleDeclarations};
}

Whitelabelling

Pulling styling information from the theme helps us to keep our pages consistent and provides us the added benefit of being able to swap out different themes to support multiple brands.

Currently, we have themes to support the following brands:

  • nib (nib)
  • GU Health (gu)
  • IMAN (iman)

Colors

Each whitelabelled theme has a set of colors that are suitable for key uses across each brand. Pulling color directly from the theme ensures that it will work across all brands, as the colors housed within the theme are more limited but referred to by universal names.

nib colors

Brand Base

Brand Light

Brand Dark

Accent

Black

Darkest

Darker

Dark

Light

Lighter

Lightest

White

ModeProvider

In v7.0.0 a new ModeProvider component was introduced to allow for the setting of a mode for a subtree of components.

Check out the ModeProvider docs for usage and guidelines.

token

A "token getter" function. The token function is typed to enable autocomplete and typescript errors when invalid token paths are provided.

The token function has a second parameter to provide a fallback value if the token cannot be found for whatever reason. During the initial migration to tokens it is recommended that fallbacks be provided for all token references. The fallback can be a string or a selector:

tsx
import {token, colorWhite} from '@nib-components/theme';
const Component = styled.div`
background-color: ${token('theme.color.bg.surface', colorWhite)};
color: ${token('theme.color.fg', '#444')};
padding: ${token('common.dimension.spacing.4', '1rem')};
`;