Setup

Installation

Neptune Web is published to npm as two packages: @transferwise/components and @transferwise/neptune-css.

If you want to use the components, you need Neptune CSS and Icons.

# yarn
yarn add @transferwise/components @transferwise/neptune-css @transferwise/icons
yarn add react react-dom react-intl prop-types currency-flags # peer dependencies

# npm
npm install @transferwise/components @transferwise/neptune-css @transferwise/icons
npm install react react-dom react-intl prop-types currency-flags # peer dependencies

Note: Peer dependencies are only necessary if you're using components. currency-flags is only required if you're using the Money Input or if you're using flags on the Select.

Usage

// These CSS files should be imported once in your application
import '@transferwise/neptune-css/dist/css/neptune.css';
import '@transferwise/icons/lib/styles/main.min.css';
import '@transferwise/components/build/main.css';

import {
  Provider,
  Button,
  Size,
  getLangFromLocale,
  translations as componentTranslations,
} from '@transferwise/components';

import appTranslations from '...';

export default function App() {
  // locale is your current locale, e.g. en-GB, en_GB or es
  const lang = getLangFromLocale(locale);
  const messages = { ...componentTranslations[lang], ...appTranslations[lang] };
  return (
    // Components must be wrapped by the Provider component once at the app level
    // See `Translations and the Provider` below for more information
    <Provider i18n={{ locale, messages }}>
      ...
      <Button size={Size.SMALL} block>
        ...
      </Button>
    </Provider>
  );
}

For information on what classes are available, see the styles documentation. Refer to components for usage documentation, live previews and code snippets for each component.

By default, apps come polyfilled. If you would like to use an unpolyfilled version because your app provides its own polyfills, see Advanced Components Usage below.

Polyfills for Web / Browser API

We don't provide polyfills for Web API, please provide it yourself in whichever way it best works for you.

Table of API that require some polyfills.

ItemRequire polyfill(s) for
Provider
Image
DateInput
Upload
adjustLocale, getLangFromLocale,
and getCountryFromLocale locale util functions

Translations and the Provider

Provider supplies translations for our components. It must be used in all applications that bundle components (i.e. has @transferwise/components as a dependency). You need to pass it an object containing the translated messages for the current locale. It doesn't matter what translations library you are using for your app translations, though we recommend react-intl.

Note: Applications which don't bundle components (such as other component libraries, or any repo that has @transferwise/components as a peerDependency) probably do not need Provider.

If you already use react-intl

Internally Provider uses react-intl, which creates a context using RawIntlProvider.

If your code already uses react-intl and its providers (RawIntlProvider, IntlProvider) replace them with Provider. You will need to include all your app translations and translations for @transferwise/components in the translations object you pass to Provider. Translations can be combined as shown below, or you can use the formatjs compile method.

import appTranslations from '...';

import {
  Provider,
  getLangFromLocale,
  translations as componentTranslations,
} from '@transferwise/components';

export default function App() {
  // locale is your current locale, e.g. en-GB, en_GB or es
  const lang = getLangFromLocale(locale);
  const messages = { ...componentTranslations[lang], ...appTranslations[lang] };
  return <Provider i18n={{ locale, messages }}>...</Provider>;
}

If you use another i18n library

If you are not using react-intl, just pass the component translations to Provider, and handle your app translations with your library. Here is an example using retranslate:

import { TranslationProvider } from 'retranslate';
import appTranslations from '...';

import {
  Provider,
  getLangFromLocale,
  translations as componentTranslations,
} from '@transferwise/components';

export default function App() {
  // locale is your current locale, e.g. en-GB, en_GB or es
  const lang = getLangFromLocale(locale);

  return (
    <TranslationProvider messages={appTranslations} language={locale}>
      <Provider i18n={{ locale, messages: componentTranslations[lang] }}>...</Provider>
    </TranslationProvider>
  );
}

Adding Provider to your dev environment

You may need to add Provider to your development environment for our components to work properly. You can do this in Storybook using decorators, and in React Testing Library using a custom render function.

Mapping locales

Provider will make an effort to map from known but unsupported locales (such as en_GB, ES and ZH-HK) to their supported equivalents (i.e en-GB, es and zh-HK).

You do not need to map your locales before passing them to Provider, but if you want to access the adjusted locale you can access the method we use:

import { adjustLocale } from '@transferwise/components';

// Will adjust, or return null if the locale is not recognised
const adjustedLocale = adjustLocale(locale);

Helper functions

If necessary you can access our internal helper functions and some other useful values:

import {
  // `en-GB`
  DEFAULT_LOCALE,
  // `en`
  DEFAULT_LANG,
  // An array of strings of supported languages
  SUPPORTED_LANGUAGES,
  // Verifies and adjusts locale (replace `_` with `-`) returns null if locale is invalid
  adjustLocale,
  // Country code (iso2) for the provided locale, or null if the locale is invalid
  getCountryFromLocale,
  // Lang code (iso2) for the provided locale, or null if the locale is invalid
  getLangFromLocale,
} from '@transferwise/components';

Loading translation files

Translation files can be accessed directly, giving you flexibility in how you load them:

// Statically
import de from '@transferwise/components/build/i18n/de.json';

// Dynamically
const locale = 'zh-HK';
import(`@transferwise/components/build/i18n/${locale}.json`);

Advanced CSS Usage

We expose three bundles for use. Our neptune.css bundle has everything. This is what you should use if using components. If you aren't using components, you have the option of just using neptune-core.css, or that and neptune-addons.css. Core includes normalising and base styles such as typography. Addons provide a number of utility classes for display, spacing and more.

Note: there are other files in the dist/css folder other than those mentioned here. Please do not rely on them, as we may remove them in future releases.

// Everything
import '@transferwise/neptune-css/dist/css/neptune.css';

// Core
import '@transferwise/neptune-css/dist/css/neptune-core.css';

// Addons
import '@transferwise/neptune-css/dist/css/neptune-addons.css';

Advanced Components Usage

The components are exposed in two formats: UMD and ES. We also provide polyfilled and non-polyfilled versions.

Which bundle should I use?

UMD is a combination of CommonJS and AMD. It works in both browser and server environments (Node). ES uses the standardized ES module format.

If you are using a bundler that supports ES module imports, you can use the ES build. If not, you will need the UMD build.

Because we declare standard main and module properties in our package.json file, if you are happy to use the polyfilled version it's likely that you will get the right import for your environment.

"main": "./build/umd/polyfill/main.js",
"module": "./build/es/polyfill/index.js",

We expose polyfilled versions by default, to ensure we meet our Browser Support policy. If your application already includes polyfills, you can optimise your bundle by including non-polyfilled versions of the components.

Below is a comparison of the different bundle options, along with where you can access them.

BundleDefaultSizeTreeshakingExtra setup required
UMD + polyfill520.545 Kb (gzip:~159.622 Kb)None.
UMD465.417 Kb (gzip:~137.724 Kb)You must override the default import and include your own polyfill.
ES + polyfill425.071 KbNone.
ES397.73 KbYou must override the default import and include your own polyfill.

If you need to override the import to use a different bundle, here is where you can find the different combinations.

BundleLocation
UMD + polyfill
@transferwise/components/build/umd/polyfill
UMD
@transferwise/components/build/umd/no-polyfill
ES + polyfill
@transferwise/components/build/es/polyfill
ES
@transferwise/components/build/es/no-polyfill

You will need to find out how to specify module overrides in your particular build environment. Here's an example of how to do it in Webpack:

  resolve: {
    alias: {
      '@transferwise/components': require.resolve(
        '@transferwise/components/build/es/no-polyfill',
      ),
    },
  },

Tree-shaking

By default when importing this - import { Button, Upload } from "@transferwise/components"; - you will get polyfilled UMD if your bundler doesn't support tree-shaking, polyfilled ES if it does.

Edit these docs on Github