Volue logo
Volue logomark
Wave Core
v1.14.1 16-10-2024
Jump to section

Overview

Wave is a tailor-made library of user interface components, behaviors and utilities for the responsive and modern day web. It provides you with a set of reusable building blocks that establish an extensible design system.

Goal of the library is to provide utilities you need to get started crafting web UI at Volue. It serves both developers and designers: enabling the former to implement consistent user interfaces much faster using a range of pre-built components, while the latter can quickly compose new prototypes by selecting existing materials—without getting lost in specifics. It's a huge win for reduced development and design effort.


Structure

Wave documentation is organized into a few useful sections.

This section includes core typographic and base element styles. Here you will also find a collection of powerful typographic, layout, spacing and color micro-helpers that can be mixed-and-matched in any number of combinations. Micro-helpers are the smallest, most flexible units in Wave—they should help in many situations and contexts.

Components are larger, more complex units: requiring multiple elements, classes and often Javascript behavior. Some features you can find here are: grid system, modals, spinners, overlays, panels and so on. Components live on their own, but together they combine system.

You can find all sorts of useful JavaScript utilities here. Need to trigger JavaScript when a responsive breakpoint is hit? Wave has you covered.

Templates

Templates consist mostly of components and helpers stitched together. They are very concrete and provide context for the smaller building blocks.

Resources

This section includes resources such as icons, color palettes and other assets available in Wave.


Getting started

Include NPM Token

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

The best way to authenticate with NPM is using an access token. You can find the authentication token with read-only permissions required to download the package in the wiki page on GitHub. If, for some reason, you're not able to access the page, please contact the Design Team.

To get more details, please read the instructions at Using private packages in a CI/CD workflow.

# 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

# 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

# Now whenever you `npm install`, NPM will know you have read-only access
# to the private packages in @volue scope.

Installation

The easiest way to get Wave is by installing it via NPM.

Stable version:

npm install @volue/wave --save

Bleeding edge version with the most recent features:

npm install @volue/wave@next --save

Files found in the dist/ folder in the NPM package are minified and unminified resources ready for production. There are also JavaScript source files in src/ folder in case you would like to integrate Wave with a module bundler of your choice.

Include Wave in Your App

Copy resources

Once you’ve installed @volue/wave package into your project, you should copy the library artifacts from node_modules to your assets directory where they can be accessed. This is required to properly serve assets required by Wave such as styles, fonts and favicons.

npx copy-wave-assets ./public

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

It is recommended to add a copy script to your package.json that runs copy-wave-assets. You should call this script while starting up or building your app to make sure you’ve always got the latest artifacts copied over automatically.

"scripts": {
  "sync-wave-assets": "npx copy-wave-assets SPECIFY_PATH",
  "build": "npm run sync-wave-assets && CMD_TO_BUILD_YOUR_APP",
  "start": "npm run sync-wave-assets && CMD_TO_START_YOUR_APP"
}

CMD_TO_BUILD_YOUR_APP could be your custom script or some popular CLI tool such as react-scripts build or ng-build depending on your project.

Include resources in your HTML markup

Once you have a copy task in place and have copied the library over, you can serve Wave's subresources using <link> and <script> tags.

  • Add inline style with @font-face rules in the <head> to load initial, highly optimized versions of our web fonts. Also remember to preload the initial web fonts using <link rel=”preload”>.
  • Inline wave-head.min.js in the <head> of your HTML template. The script will asynchronously load "full" versions of our web fonts to enable more stylistic variants and features. 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.
  • Link to the CSS file in your HTML template to include the main Wave styles.
  • Add a script tag to your HTML template to use the JavaScript (script should be included right before the closing </body> tag, this is to prevent render blocking and provide a faster perceived page load). Wave will be available as Wave in the window object.
<!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">
    <meta name="fontsDir" content="/wave/fonts">
    <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">
    <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>
    <title>...</title>
    <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>!function(e){"use strict";var o,f,r,a,n=function(o){for(var f,r=e.document.getElementsByTagName("meta"),a=0;a<r.length;a++)if(r[a].name&&r[a].name==o){f=r[a];break}return f}("fontsDir");o=null!=n?n.content:"/fonts","fonts"in document&&(f=new FontFace("FK Display","url("+o+"/FKDisplay-Regular.woff2) format('woff2'), url("+o+"/FKDisplay-Regular.woff) format('woff')"),r=new FontFace("Source Sans Pro","url("+o+"/SourceSansPro-Regular.woff2) format('woff2'), url("+o+"/SourceSansPro-Regular.woff) format('woff')"),n=new FontFace("Source Sans Pro","url("+o+"/SourceSansPro-Italic.woff2) format('woff2'), url("+o+"/SourceSansPro-Italic.woff) format('woff')",{style:"italic"}),a=new FontFace("Source Sans Pro","url("+o+"/SourceSansPro-SemiBold.woff2) format('woff2'), url("+o+"/SourceSansPro-SemiBold.woff) format('woff')",{weight:"600"}),Promise.all([f.load(),r.load(),n.load(),a.load()]).then(function(o){o.forEach(function(o){document.fonts.add(o)})})),!("fonts"in document)&&"querySelector"in document&&((a=document.createElement("style")).innerHTML="@font-face { font-family: 'FK Display'; src: url("+o+"/FKDisplay-Regular.woff2) format('woff2'), url("+o+"/FKDisplay-Regular.woff) format('woff'); }@font-face { font-family: 'Source Sans Pro'; src: url("+o+"/SourceSansPro-Regular.woff2) format('woff2'), url("+o+"/SourceSansPro-Regular.woff) format('woff'); }@font-face { font-family: 'Source Sans Pro'; src: url("+o+"/SourceSansPro-Italic.woff2) format('woff2'), url("+o+"/SourceSansPro-Italic.woff) format('woff'); font-style: italic; }@font-face { font-family: 'Source Sans Pro'; src: url("+o+"/SourceSansPro-SemiBold.woff2) format('woff2'), url("+o+"/SourceSansPro-SemiBold.woff) format('woff'); font-weight: 600; }",document.head.appendChild(a))}(this);</script>
    <link rel="stylesheet" href="wave/wave.min.css">
</head>
<body>
    <p class="alpha">Hello, world!</p>
    <script src="wave/wave.min.js"></script>
    <script>
      (function() {
        var initWave = Wave.default;
        // initWave() contains some global bootstrapping logic such as
        // identyfing browser capabilities and appendinng relevant classes to
        // root HTML element as well as instantiating some behaviour (e.g.
        // dropdowns) available via hooks in markup (`.js-triggerDropdown` etc)
        initWave();

        // Create new component instances
        // var toasterInstance = Wave.Toaster(/* options */);
        // var toggleSwitchInstance = Wave.ToggleSwitch(/* options */);

        // Use utils
        // Wave.utils.debounce(/* someFunc */)
      })();
    </script>
</body>
</html>

Usage with JS bundlers

If you're building a web application and already have a bundler in place such as Webpack, it's best to import Wave using ES6 import syntax like this:

// in your app's entry point
import initWave from '@volue/wave';

initWave();

Then when you need some functionality, you import relevant module(s):

import { Toaster, ToggleSwitch } from '@volue/wave';
import { debounce } from '@volue/wave/utils';

This way only imported modules will get included in your final bundle instead of entire library (tree shaking).

Wave is also compatible with legacy CommonJS and AMD formats in case your environment does not support ES6 import syntax. For instance, if you are using CommonJS modules in your application, you can:

// require NPM module
// note that tree shaking benefits mentioned above are absent when using this syntax
var Wave = require('@volue/wave');

var initWave = Wave.default;
initWave();

// var toasterInstance = Wave.Toaster(/* options */);
// var toggleSwitchInstance = Wave.ToggleSwitch(/* options */);
// Wave.utils.debounce(/* someFunc */)

Note on browser support

The complete experience should work in the last two versions of all evergreen browsers: Chrome, Opera, Firefox and Safari. Wave also aims to support Internet Explorer 11+. Support for other browsers is not strictly guaranteed, but accounted for whenever possible.

Compatibility matrix:

IE11 Chrome Firefox Safari Chrome (Android) Mobile Safari
B A A A A A

A-grade browsers are fully supported. B-grade browsers will gracefully degrade the experience without impacting the function.


Contributing

Would you like to help make Wave project better? Awesome!

We use Github issues to track all bugs and potential updates and additions to the design system. To contribute you will need to sign up for a free GitHub account and be a member member of Volue GitHub organization.

If you find an issue or have an idea for a feature, please do file it in our repository issue tracker. We gladly accept pull requests that add documentation, fix bugs and, in some circumstances, add new features to Wave (be sure to read the contribution guide).

Announcement

This is the technical documentation of Wave Core library, the foundational part of Wave Design System.

Currently we are working on brand new design system site and a set of polished React components that aim to work out of the box, be accessible and deliver superior developer and user experience. Browse the new Wave Design System site and Wave React components docs at https://wave.volue.com.