Theming is a mechanism by which a consistent look and feel can be applied to all the components within an application.
By using Balance’s theme
, developers can easily customize all of their
components by changing a set of universal variables, eliminating the need to
modify individual components.
Breakpoints
Breakpoints underpin our responsive strategy for the entire system. Breakpoints are used internally by many components and are exposed externally to allow responsive configuration.
Shape
Breakpoints can be defined numerically/unitless for pixels 1024
, or as a string to
provide a unit as 64em
. Below is the default set:
type Breakpoints = { small: 576; medium: 768; large: 992; xlarge: 1200;};
These are the only breakpoints that should be used for responsive styling. If your UI requires additional non-standard media queries you should work with your designer to see what solutions are possible working within the system.
Usage
Hook
Import the useMediaQuery
hook from the utils package.
import { useMediaQuery } from '@balance-web/media-query';
Responsive values
To target a specific value that should change across breakpoints use the mq
utility function. You can pass in a standard CSS object, and array values will
be applied to their respective breakpoints.
Note that if a value is repeated across several breakpoints, a null
value can be
used to prevent generating unnecessary CSS.
This is achieved using Emotion's facepaint library.
Min / Max
For granular control over a group of styles use the minBreak
and maxBreak
utility functions. They accept a single argument, which must be one of the
breakpoint keys supplied to the theme.
Components
Various layout primitives consume the breakpoints as props, similar to the "responsive values".
Padding and Margin
Use the padding
and margin
properties on the Box
component. Each layout primitive extends the Box
component:
Gap
Use the gap
property on components like Stack
and Inline
:
Colors
We use a combination of whitespace and color to aid usability and deliver clean experiences to end users. Color helps distinguish our brand, and delivers a consistent user experience across our various digital products.
Note that the
colors
provided to the theme are only half of the picture. These colours will be operated on to create thepalette
.
Shape
Because we perform functions on these colours they must be provided as hex values.
type Colors = { background: string; text: string; primary: string; accent: string; danger: string; warning: string; success: string; info: string; decorative: string[];};
Usage
Import the useTheme
hook from the theme package.
import { useTheme } from '@balance-web/theme';
You may access colors
from the theme, though it's not recommended. Prefer
using the resolved palette
, also available on the theme
object.
const { colors } = useTheme();
Core colors
These are the core colors that should be used in all designs and serve to distinguish digital assets associated with the brand.
Functional colors
These colors should be reserved for functional elements or messages, such as indicating the outcome of an action or highlighting a success/failure. They should be used sparingly so as not to risk confusing their meaning.
Decorative colors
Decorative colors don't have any semantic meaning; they're applied to avatars etc. They should not overlap with the core or functional colors.
Variant colors
Variant colors are specific to your product; they're applied to tags etc. They should not overlap with the core or functional colors.
Palette
The palette is the complete set of colour values used within the design system components. The default palette is derived from the colours provided to the theme.
Why?
The complete palette contains hundreds of colour declarations, which allow granular control over each component's appearance. Declaring all of them manually would be tedious, and is frankly unnecessary.
To achieve a given appearance a theme author may only need to change a handful of values, but for any given appearance we can't know which values will need to change, so every value must be individually addressable.
How?
The default palette resolver takes the theme's colors and operates with color functions on them to create the entire palette.
Note that you may return a partial palette because it will be deep merged into the default palette for
Core
, and deep merged into the ancestral palette for nestedThemeProvider
.
Global
You can provide a paletteResolver
to the Core
component, which will
influence every component within the app:
<Core paletteResolver={(colors) => ({ /* palette object */ })}> App content</Core>
Nested
If you need to influence only a portion of the app, you can provide a
paletteResolver
to a nested ThemeProvider
component:
<ThemeProvider paletteResolver={(colors) => ({ /* palette object */ })}> Section or portion</ThemeProvider>
Shadow
Shadows are used to add a sense of elevation to an element, above the surface of the page.
{ S100: `0px 1px 2px rgba(0, 0, 0, 0.2)`, S200: `0px 2px 4px rgba(0, 0, 0, 0.2)`, S300: `0px 2px 8px rgba(0, 0, 0, 0.2)`, S400: `0px 4px 16px rgba(0, 0, 0, 0.2)`, S500: `-8px 8px 32px rgba(0, 0, 0, 0.2)`,}
Access shadow
from the theme object.
const { shadow } = useTheme();
Shadow variants:
Radii
Radii values are used to round elements, often in concert with sizing
.
{ none: 0, xsmall: 4, small: 6, medium: 8, large: 12,}
Access radii
from the theme object.
const { radii } = useTheme();
Radii variants:
Sizing
We use sizing to apply heights and widths to elements, maintaining a consistent appearance among components. Sizing is flexible based on the theme.
Shape
Sizing can be defined numerically/unitless for pixels (24
), or as a string to
provide a unit as (2.4rem
).
Usage
Hook
Import the useTheme
hook from the theme package.
import { useTheme } from '@balance-web/theme';
Access sizing
from the theme object.
Components
Various components consume the sizing keys as props.
Avatars
Avatars accept sizing keys.
Buttons and Inputs
Buttons and inputs accept a limited set of the sizing keys.
Spacing
We use spacing to apply padding and margin to elements. Spacing can be applied
uniformly or individually to the sides of an element. Spacing is flexible based
on the theme. The default theme implements a base unit of 4px
.
Shape
Spacing can be defined numerically/unitless for pixels (4
), or as a string to
provide a unit as (0.4rem
).
Usage
Hook
Import the useTheme
hook from the theme package.
import { useTheme } from '@balance-web/theme';
Access spacing
from the theme object.
Components
Various layout primitives consume the spacing keys as props.
Padding and Margin
Use the padding
and margin
properties on the Box
component. Each layout primitive extends the Box
component:
Gap
Use spacing keys for the gap
property on components like Stack
and Inline
:
Typography
Typography helps to create the structure and hierarchy of a page. Typography also helps users read, absorb and comprehend content. Communication should be clear and easy to read. Our font choices are a reflection of this.
Shape
Below is the default typography configuration:
type Typography = { fontFamily: { monospace: 'Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace'; body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif'; heading: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif'; }; fontSize: { xsmall: '0.75rem'; small: '0.875rem'; medium: '1rem'; large: '1.125rem'; xlarge: '1.25rem'; xxlarge: '1.5rem'; xxxlarge: '1.875rem'; xxxxlarge: '2.25rem'; xxxxxlarge: '3rem'; xxxxxxlarge: '4rem'; }; fontWeight: { regular: 400; medium: 500; semibold: 600; bold: 700; heavy: 800; }; leading: { tighter: 1; tight: 1.2; base: 1.4; loose: 1.6; looser: 1.8; };};
Usage
Hook
Import the useTheme
hook from the theme package.
import { useTheme } from '@balance-web/theme';
Access typography
from the theme object.
Components
Various layout primitives consume the typography keys as props.
Text
The Text
component supports leading
.
Heading
The Heading
component supports leading
.