# 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](https://next.wave-design-system.pages.dev/_next/static/chunks/images/developing-banner-34463361594fe16be294981f7cf9881a.png)

## 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](https://www.npmjs.com/) and our organisation's [GitHub Package Registry](https://github.com/orgs/Volue/packages).

<Tabs.Root
  defaultValue="npm"
>
  <Tabs.List css={{ marginBottom: '$spacingM' }}>
    <Tabs.Trigger value="npm">{'NPM'}</Tabs.Trigger>
    <Tabs.Trigger value="ghPackages">{'GitHub packages'}</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="npm">

The best way to authenticate with [npmjs.com registry](https://www.npmjs.com/) is using an [access token](https://docs.npmjs.com/about-access-tokens).
You can find pre-generated authentication token with read-only permissions required to download Wave packages in the [wiki page on GitHub](https://github.com/Volue/wave/wiki/NPM-authentication-token).

```bash
# 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 locally
# 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

# 3. When using GitHub Actions for CI/CD pipeline, point `NPM_TOKEN` environment
# variable to org-wide `secrets.VOLUE_PLATFORM_NPM_TOKEN`, otherwise define a new
# secret using the token from previous step.

```

> **Tip**
>
> If, for some reason, you're not able to access the [NPM authentication token page](https://github.com/Volue/wave/wiki/NPM-authentication-token), please contact the [Design System team](https://github.com/orgs/Volue/teams/design-system).

<Card
  href="https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow"
  title="NPM guide on using private packages in a CI/CD workflow"
  actionIcon="externalLink"
/>

  </Tabs.Content>
  <Tabs.Content value="ghPackages">

By default, the `npm` CLI utility is configured to download packages from [official NPM registry](https://www.npmjs.com/).
To fetch Wave from [GitHub Packages](https://docs.github.com/packages), you need to change registry url and specify a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with read-only permissions inside _.npmrc_ file.

```bash
# 1. Do this on your local machine and commit the `.npmrc` to git
cd path/to/your/app
cat > .npmrc << EOF
registry=https://npm.pkg.github.com/volue
//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_PAT}
EOF

# 2. Add this environment variable both locally and on your CI/CD
# Substitute `READ_ONLY_GITHUB_PAT` with a real token:
export GITHUB_PACKAGES_PAT=READ_ONLY_GITHUB_PAT
```

> **Important**
>
> `READ_ONLY_GITHUB_PAT` should be a [classic personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#personal-access-tokens-classic) with `read:packages` scope.

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
>
  <GridItem>
    <Card
      href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry"
      title="Guide on using GitHub Packages registry"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.blog/2019-09-11-proxying-packages-with-github-package-registry-and-other-updates/"
      title="Proxying packages from npmjs.com"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>

  </Tabs.Content>
</Tabs.Root>

---

## Installation

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

```bash
npm install @volue/wave @volue/wave-react --save
```

```bash
yarn add @volue/wave @volue/wave-react
```

> **Tip**
>
> Bleeding edge pre-release version with the most recent features, can be installed by appending `@next` tag to the package names:
>
> ```bash
> yarn add @volue/wave@next @volue/wave-react@next
> ```

---

## Include Wave core assets

> **Tip**
>
> The guide below is useful for custom setups. As long as you're using [one of our starter project templates](#example-react-projects), you can skip these instructions, as these templates are already preconfigured.

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:

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

> **Tip**
>
> `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:

```js
  "scripts": {
    "sync-wave-assets": "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](https://webpack.js.org/plugins/copy-webpack-plugin/) or [viteStaticCopy](https://github.com/sapphi-red/vite-plugin-static-copy) 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

- Preload the subset web fonts using `<link rel="preload">`. The subset fonts cover the most common characters and are preloaded for instant rendering. Full font files are loaded on demand via `unicode-range` only when characters outside the subset are needed.

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

- Inline [the SVG sprite with Wave icons](https://next.wave-design-system.pages.dev/tokens/icons.md#usage)

The final markup should resemble:

<Accordion>
  <AccordionItem title={<InlineCode>{'index.html'}</InlineCode>}>

```html showLineNumbers=true
<!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="#ff5f00" />
    <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 (preload subset for instant rendering) -->
    <link
      rel="preload"
      href="/wave/fonts/IBMPlexSans-Regular-subset.woff2"
      as="font"
      type="font/woff2"
      crossorigin
    />
    <link
      rel="preload"
      href="/wave/fonts/IBMPlexSans-SemiBold-subset.woff2"
      as="font"
      type="font/woff2"
      crossorigin
    />

    <!-- 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>
```

  </AccordionItem>
</Accordion>

## 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:

```jsx
import { Collapsible, Button, SvgIcon } from '@volue/wave-react';

const Component = () => {
  return (
    <Collapsible.Root>
      <Collapsible.Trigger as={Button} variant="outline">
        <SvgIcon iconName="chevronDown" /> {'Toggle panel'}
      </Collapsible.Trigger>
      <Collapsible.Panel>{'Panel content'}</Collapsible.Panel>
    </Collapsible.Root>
  );
};
```

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:

```jsx
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'
  }}
/>;
```

> **Tip**
>
> [Box component](https://next.wave-design-system.pages.dev/components/layout/box.md) is a low-level primitive that lets you work with the `css` prop.

> **Tip**
>
> 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 customising 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.

```jsx
import { styled } from '@volue/wave-react';

const MyStyledComponent = styled('div', {
  color: '$foregroundAccent',

  size: {
    small: {
      padding: '$spacingS'
    },
    large: {
      padding: '$spacingL'
    }
  }
});

() => <MyStyledComponent size="large" />;
```

> **Tip**
>
> [Box component](https://next.wave-design-system.pages.dev/components/layout/box.md) 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](https://stitches.dev/docs/styling) 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 of Wave with popular bundlers/frameworks and very basic components usage.

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
>
  <GridItem>
    <Card
      href="https://github.com/Volue/wave-vite-example"
      title="Vite example"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.com/Volue/wave-nextjs-app-router-example"
      title="Next.js with app router example"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.com/Volue/wave-nextjs-example"
      title="Next.js with pages router example"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>
