Installation
Start by making sure you have an npm token from the @ovotech npm org.
yarn add @ovotech/element
or
yarn add @ovotech/element-native
Or if you prefer:
npm install --save @ovotech/element
or
npm install --save @ovotech/element-native
Element has been built with an opinionated stack of react and styled-component. This means you'll need to make sure you’ve installed the following peer dependencies:
- react
- styled-components (react-native)
- react-native (react-native)
- react-native-svg (react-native)
- react-native-reanimated (react-native)
- react-native-gesture-handler (react-native)
- react-native-safe-area-context (react-native)
- @react-native-masked-view/masked-view (react-native)
CSS reset
When using them on the web, the design system components rely on global styles to provide a CSS reset.
We export one of these that uses sensible defaults, and most crucially, responsive font sizing. It can be imported as below:
// Webpack will need a css-loader to import this.
import '@ovotech/element/reset.css';
Cascade Layers
Starting with version 4.6.1 of the Element web package, cascade layers now wrap the reset (`reset` layer) and all component CSS module styles (`element` layer). This helps with loading our CSS in a predictable order, so it is possible to configure it at a lower level than any required overrides in a consuming project, e.g.
/* from lowest to highest priority, with overrides as an example of YOUR styles. */
@layer reset, element, overrides;
When working with NextJS, it isn’t always simple to predict the loading order of CSS files.
For this reason, it’s important to place the above @layer declaration at the top of a global file in src/app/global.css as this will load before other CSS files and set the cascading order correctly.
When working with NextJS <16, it has also been found that setting Turbopack as the compiler (with the --turbo flag) is required for this loading order (Oct. ‘25). Version 16 sets Turbo as the default compiler.
Using the fonts
Download the font files here: 2023.04.03-OVOCircular.zip (opens in new window)
It's best to use the fonts locally to your project. Use @font-face declarations to load these and set up the family in line with the typography tokens in Element.
For example:
@font-face {
font-family: 'OVOCircular';
src: url('./path/to/OVOCircularWeb-Book.woff2') format('woff2');
font-weight: 450;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'OVOCircular';
src: url('./path/to/OVOCircularWeb-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'OVOCircular';
src: url('./path/to/OVOCircularWeb-Black.woff2') format('woff2');
font-weight: 900;
font-style: normal;
font-display: swap;
}
Setting the theme
Element native uses styled-components, which need a theme - you can import from @ovotech/element-native. Use styled-component's <ThemeProvider> at the root of the app.
Element (web) uses CSS Modules under the hood, which need a theme.css from @ovotech/element . These are a set of CSS variables set on the :root element, with a capability in the Core package to generate sets for modes and brands (please reach out if this is of interest!).
import '@ovotech/element/theme.css'
ReactDOM.createRoot(document.getElementById('root')).render(<MyApp />)
import { ThemeProvider } from 'styled-components/native';
import { themeNative } from '@ovotech/element-native';
<ThemeProvider theme={themeNative}>
<MyApp />
</ThemeProvider>;
Using the components
Element exports all components as named exports as documented throughout, for example:
import { Button } from '@ovotech/element';
const Example = () => (
<Button onClick={() => alert('Yippee!')}>
I ❤ Design Systems
</Button>
);
import { PrimaryCTAButton } from '@ovotech/element-native';
const Example = () => (
<PrimaryCTAButton onPress={() => alert('Yippee!')}>
I ❤ Design Systems
</PrimaryCTAButton>
)
Using the theme object
In an ideal scenario user interfaces (UIs) would be built entirely using Element components. However, considering the components and layout utilities provided by the system are far from a complete set, there will be times when you will need to build your UI using custom styling. In these situations, we'd recommend leveraging the theme object provided by Element in order to maintain consistency with our components, and by extension enabling themability in future.
The theme comprises of core, semantic, and component tokens, with core containing unique values that are generally aliased in the two other sub-objects. For this reason, unless modifying the underlying theme and visuals, it is recommended to always use semantic and component tokens wherever possible when working with the Element theme.
import '@ovotech/element/theme.css'
export default function Theme() {
return (
<div>
<p>Some text</p>
</div>
);
}
import { createTheme } from '@ovotech/element-native';
const theme = createTheme({});
export default function Theme() {
return (
<View>
{theme}
</View>
);
}