Developing

Wave has everything you need to get started building web interfaces at Volue. Develop a consistent and accessible user interfaces much faster using a range of pre-built components.

Developing

Developing banner

Authenticating to package registry#

Since @volue is a private NPM scope, your project (both locally and in CI pipeline) needs to be authenticated with NPM registry to fetch packages.

Wave packages are published to both official npmjs.com registry and our organization's Github Package Registry.

The best way to authenticate with npmjs.com registry is using an access token. You can find pre-generated authentication token with read-only permissions required to download Wave packages in the wiki page on GitHub.

# 1. Do this on your local machine and commit the `.npmrc` to git
cd path/to/your/app
echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' >> .npmrc
# 2. Add this environment variable both locally and on your CI/CD
# Substitute `READ_ONLY_NPM_TOKEN` with a real token:
# https://github.com/Volue/wave/wiki/NPM-authentication-token
export NPM_TOKEN=READ_ONLY_NPM_TOKEN

If, for some reason, you're not able to access the NPM authentication token page, please contact the Design System team.

NPM guide on using private packages in a CI/CD workflow

Installation#

Inside your project directory, install Wave by running either of the following:

npm install @volue/wave @volue/wave-react --save
yarn add @volue/wave @volue/wave-react

Bleeding edge pre-release version with the most recent features, can be installed by appending @next tag to the package names:

yarn add @volue/wave@next @volue/wave-react@next

Include Wave core assets#

For Wave to work correctly, you need to include its core assets, such as stylesheets, icons and web fonts.

To copy core assets from node_modules/@volue/wave to a location where you store your other bundled and minified assets for production, you may use copy-wave-assets command:

npx copy-wave-assets ./dist
# or
yarn copy-wave-assets ./dist

copy-wave-assets will create a directory named wave in the location you’ve specified (./dist in the example above). See copy-wave-assets -h for more information.

It is recommended to add a script to your package.json that runs copy-wave-assets and call it whenever the build is executed to make sure you’ve always got the latest assets copied over:

"scripts": {
"sync-wave-assets": "npx copy-wave-assets ./public",
"build": "npm run sync-wave-assets && react-scripts build",
"start": "npm run sync-wave-assets && react-scripts start"
}
}

Alternatively, you could use tools such as CopyWebpackPlugin to move core Wave resources to your assets directory as part of your build process.

Include assets in your HTML template#

Once you have a copy task in place and and the assets are copied over, you can serve them using <link> tags in your root HTML template.

  • Add links to favicons

  • Add inline style with @font-face rules in the <head> to load initial, highly optimized versions of our web fonts.

    Remember to preload the initial web fonts using <link rel=”preload”>.

  • Inline wave-head.min.js in the <head> of your HTML template. This is a small chunk of logic that will asynchronously load full versions of our web fonts to enable more stylistic variants and features.

    wave-head.min.js could be specified as <script src="wave/wave-head.min.js">, however it's best to save additional network request for a render-blocking resource.

    You can achieve the inlining by using interpolation syntax of html-webpack-plugin (see example code below).

    You can customize the path to the web fonts directory by adding <meta name="fontsDir" content="/path/to/fonts"> in the <head>. By default fonts will be looked up in /fonts directory.

  • Add link to the CSS bundle to include the core Wave styles.

Your index.html should resemble:

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="theme-color" content="#00829b" />
<title>...</title>
<!-- Favicons -->
<!-- make sure to place `favicon.ico` in the root of your web app (required for legacy browsers) -->
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="icon" type="image/svg+xml" href="/wave/images/favicon.svg" />
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/wave/images/favicon-192.png"
/>
<link rel="apple-touch-icon" href="/wave/images/favicon-180.png" />
<!-- Wave webfonts -->
<link
rel="preload"
href="/wave/fonts/SourceSansPro-Regular-initial.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<link
rel="preload"
href="/wave/fonts/FKDisplay-Regular-initial.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<style>
@font-face {
font-family: 'Source Sans Pro';
src:
url(/wave/fonts/SourceSansPro-Regular-initial.woff2) format('woff2'),
url(/wave/fonts/SourceSansPro-Regular-initial.woff) format('woff');
font-display: swap;
}
@font-face {
font-family: 'FK Display';
src:
url(/wave/fonts/FKDisplay-Regular-initial.woff2) format('woff2'),
url(/wave/fonts/FKDisplay-Regular-initial.woff) format('woff');
font-display: swap;
}
</style>
<!-- wave-head.min.js inlined -->
<script>
<%= require('!!raw-loader!@volue/wave/dist/core/wave-head.min').default %>
</script>
<!-- Wave core styles -->
<link rel="stylesheet" href="wave/wave.min.css" />
</head>
<body>
<!-- Embedded Wave icons sprite -->
<div id="svgSpritePlaceholder" class="is-hidden" aria-hidden="true">
<%= require('!!raw-loader!@volue/wave/dist/core/sprite.svg').default %>
</div>
<div id="appRoot"></div>
</body>
</html>

Use the components#

All components are available as named exports from @volue/wave-react. Import any of the components in your React project and use them in your interface:

import { Collapsible, Button, SvgIcon } from '@volue/wave-react';
const Component = () => {
return (
<Collapsible>
<Collapsible.Trigger as={Button} variant="outline">
<SvgIcon iconName="chevronDown" /> {'Toggle panel'}
</Collapsible.Trigger>
<Collapsible.Panel>{'Panel content'}</Collapsible.Panel>
</Collapsible>
);
};

Refer to the individual component documentation for recommended usage and API references for each component.

Styling APIs#

css#

The css property is available on all of our components to allow you to contextually style them when necessary. It provides a superset of CSS (i.e. it contains all CSS properties and selectors in addition to custom ones) so it's intuitive to pick up and start working with right away if you're comfortable with CSS. You can pass in an object of CSS key-value pairs and the component will apply those styles as a class on the rendered component.

The benefit of using the css prop as opposed to writing inline styles is that we can directly access values from our design tokens to ensure consistency, write responsive styles by referring to the breakpoints defined in the theme etc:

import { Box } from '@volue/wave-react';
<Box
css={{
// we can write standard CSS here
color: 'red',
// we can also access design tokens
backgroundColor: '$backgroundNeutralSubtle',
padding: '$spacingM',
// write inline responsive styles
'@mqLargeAndUp': {
color: '$foregroundAccentModerate'
},
// and utilise shorthand utilities
mb: '$spacingXl'
}}
/>;

Box component is a low-level primitive that lets you work with the css prop.

When working in a TypeScript codebase our design token options will show up with autocompletion depending on the CSS property used.

The css prop is great for customizing only a specific instance of a given component, by defining one-off styles.

styled#

@volue/wave-react also exports the underlying styled() function that is used to create styled components with access to the css prop.

import { styled } from '@volue/wave-react';
const MyStyledComponent = styled('div', {
color: '$foregroundAccent',
size: {
small: {
padding: '$spacingS'
},
large: {
padding: '$spacingL'
}
}
});
() => <MyStyledComponent size="large" />;

Box component is just a styled div element.

In contrast to the css prop, styled() function is ideal for building components that need to support a wide variety of contexts. It allows you to create custom components, with similar capabilities as Wave's standard components.

In addition to the base component styles, styled() lets you define a single variant, multiple variants, and even compound variants which allow you to define styles based on a combination of variants. Those variants can be applied conditionally or responsively.

Refer to the Stitches docs to read more about the difference between css and styled().

Example React projects#

Below you will find various project templates on GitHub, demonstrating the integration with Wave and very basic components usage.

You might also take a look at our internal boilerplate for developing React apps, which comes integrated with Wave.