Development workflow
This document aims to provide guidance for consumers on how best to build interfaces that properly leverage Balance.
Working with components
Balance provides consumers with a suite of components that are powered by an underlying theme system.
The goal is that consumers should be able to build their experiences entirely from Balance components using only the prop interfaces they expose. If done correctly, our products should be expressed exclusively using the design system’s language, which means that they can be adapted to any theme that Balance supports.
However, it’s expected that you’ll find gaps in the system, so Balance also provides lower level building blocks for generating custom components.
High level components
Balance’s high level components are most likely the ones you would come to expect from a design system, e.g. Text, Heading, Button, TextField, etc.
An example of composing a simple view using some of these could be:
You’ll notice that each of these components don’t provide any surrounding white space. This is where our layout primitives come in.
Layout primitives
Use layout primitives to distribute white space evenly between components.
Stack
For vertical layouts, wrap sibling elements in a Stack component with a gap
property. For example, if you wanted small
space between items in a Stack:
Inline
For horizontal layouts, Inline renders elements horizontally and allow them to wrap onto a new line.
Columns
For horizontal layouts, Columns provides various ways for laying out content. For example, if you wanted to render a two-column layout:
Or use the template
prop to define relative column widths:
Custom components
If you’re unable to satisfy a design using the built-in set of higher level components, consider the Box component, which provides direct access to the themed styles that Balance uses internally, without the overhead of having to create custom styles.
The prop names for Box mostly mimic CSS properties, while their values are more semantic, allowing the corresponding CSS rules to be computed across themes.
Responsive props
You may provide ‘responsive props’ to specify a set of values for different screen sizes.
For example, if you wanted small spacing on mobile but medium spacing from tablet upwards:
Semantic markup
The Box component accepts the as
prop, which allows you to change the root element that the component renders.
Important: Changing the root element can affect the styles and accessibility of a component. Consider how the component will be used when specifying the
as
prop.
Custom CSS
Balance is styled using emotion to provide powerful and predictable style composition. Custom styles may be provided using the css prop to compose theme tokens.
Important: You should very rarely need custom CSS. If you cannot achieve the design using Balance components + layout primitives, please raise it as an issue in the #balance-support channel first.
Use the jsx pragma (/** @jsx jsx */
) and import jsx
from the core package:
// MyComponent.tsx/** @jsx jsx */import { jsx } from '@balance-web/core';
With those two things you're now able to provide custom styles to the css
prop
of a component.
// MyComponent.tsx/** @jsx jsx */import { ReactNode } from 'react';import { jsx } from '@balance-web/core';import { Box } from '@balance-web/box';import { useTheme } from '@balance-web/theme';type MyComponentProps = { children: ReactNode;};export const MyComponent = (props: MyComponentProps) => { const { spacing } = useTheme(); return <Box css={{ padding: spacing.large }} {...props} />;};
Questions
If you have a question that wasn't answered, reach out to us in #balance-support