npm package: @scb-dmc/scb-nav
Description: scb-nav is a project for a unified React based navigation menu.
Latest version: 2.0.2

# scb-nav

scb-nav is a project for a unified React based navigation menu.

## Node Versions

Ensure that Node version 16.0.0 or greater is installed and available.

## Getting Started

Create a file in the root of the project called `.env` with the following contents:

```
SCB_PRISMIC_URL=<prismic api url from scb-static>
SCB_PRISMIC_TOKEN=<prismic token from scb-static>
FETCH_MENU=true
LOCALE=en-us
IMAGE_PREPROCESSOR=https://www.santacruzbicycles.com/_next/image
```

Start the development server:

```
$ yarn start
```

The app will be running at [http://localhost:9000](http://localhost:9000).

### Menu Data

By default, the app will fetch new menu data and write it to `./src/assets/menu/<site>/<locale>.json`
when running the development server or building the web artifacts. This behavior can be overridden
by either changing `FETCH_MENU` in your environment file to `false`, or by overriding the
variable through the CLI. For example:

```sh
$ DOTENV_CONFIG_FETCH_MENU=false yarn build:web
```

#### Images

The menu is capable of displaying images in two components: the MegaMenu and the SubNav. The images
can be served through an optional preprocessor by supplying a URL to the `imagePreprocessor` prop
of `NavMenu`. This prop is required, but can be bypassed with an empty string (`""`). Currently,
this assumes a route to `/_next/image`.

##### Sizes

- SubNav: 700px by 700px
- MegaMenu: 700px by 750px

### i18n

When running the dev server or building the web artifacts, localized menu data will be pulled
from Prismic for all locales and saved to `./src/assets/menu/<site>/<locale>.json`. By default, the
dev server will use `en-us` menu data, but this can be overridden by changing the path to the
menu JSON in `webpack.dev.config.js`.

#### scb-static

i18n in scb-static happens as part of the Next build. Simply pass the localized menu data to
the `NavMenu` component like any other translated object.

### TagManager

Events are tracked using tag manager and requires the user to have the `react-gtm-module` peer dependency installed.

### Creating Menus in Prismic

Menus come in four different types, and certain types of menus are built out of _other_
types of menus. These types are:

- `single`: The most basic menu item. When used at the top most level, this are standard
  links.
- `subnav`: SubNav menus are built out of one or more `single` or `pill` type menus. The
  `subnav` menu item will be the top level menu item and the `single` or `pill` items that
  follow will make up its children.
- `megamenu`: MegaMenu menus are similarly built out of one or more `single` or `pill` type
  menus. MegaMenus represent several distinct sub-menus, so they have a special `header` type
  menu to associate child menus with a particular sub-menu.
- `pill`: Pill menu items are much like `single` menu items, except they are pill buttons.

##### The Rules of Pills

Pill menu items are special cases that need to follow some rules:

1. Pill menu items don't belong in the top most level.
2. Pill menu items only belong as direct children of SubNav or MegaMenus.
3. When used with a MegaMenu, Pills will be treated like standard sub-menu
   items. This means that they will appear in the list of items _as entered_,
   under the closest MegaMenu header. They will not reorder themselves.

## Building

scb-nav builds two kinds of artifacts: a web artifact which can by included in a page
using standard `<script>` tags, or a Node artifact that can be imported into other
Node projects. To build both artifacts at once:

```
$ yarn build
```

The `build` target will also clean the `dist/` directory before building the new
artifacts. For this reason, it's generally the best target to use.

### Shopify and Drupal

To produce a web artifact for use in Shopify or Drupal:

```
$ yarn build:web
```

The component will look for a mount point with the ID `scb-nav-menu`.

#### The Web Artifacts

Because the menu data is packaged with the web artifacts, a new version of the web artifacts
must be built when menu changes are made in Prismic.

### scb-static

To product a Node compatible artifact:

```
$ yarn build:node
```

Type declaration files will be generated automatically.

## Using scb-nav

### Shopify

Below is a suggested workflow for updating ubergoober-theme to a new release of
scb-nav:

_Note:_ Shopify only uses the en-US version of the menu. No other locales are needed.

```sh
# build scb-nav
~/D/scb-nav $ yarn build # or yarn build-web

# start ThemeKit to allow it to automatically update files on the Shopify site
~/D/ubergoober-theme $ theme watch --env=$UBERGOOBER_CERVELO_DEV_ENV

# Remove existing version of scb-nav-menu
~/D/ubergoober-theme $ rm assets/scb-nav-menu.en-us.[contenthash].js

# Copy new English artifact into the project
~/D/ubergoober-theme $ cp ../scb-nav/dist/web/scb-nav-menu.en-us.[contenthash].js assets/
```

**Important:** Remember to update the asset URL in `layout/theme.liquid`.

### scb-static (or other Node project)

Simply install the `@scb-dmc/scb-nav` package and import it as normal:

```jsx
import { NavMenu } from "@scb-dmc/scb-nav";

const MyPage = () => {
  return (
    <Layout>
      <NavMenu
        menu={menuData}
        site={site}
        lang={lang}
        imagePreprocessor={imagePreprocessor}
      />
    </Layout>
  );
};

export default MyPage;
```

`@scb-dmc/scb-nav` exports an object `MenuUtilities` with the following functions:

- `createMenu` - transform Prismic response data into menu data
- `withNavMenuLinkUrls` - Serializes Prismic Document links in menu data

For example:

```jsx
import { MenuUtilities } from "@scb-dmc/scb-nav";

const client = Prismic.client(process.env.SCB_PRISMIC_URL, {
  accessToken: process.env.SCB_PRISMIC_TOKEN,
});

const getSiteHeaderData = async (prismicClient) => {
  return prismicClient
    .query(Prismic.Predicates.at("document.type", "site_header"))
    .then((response) =>
      MenuUtilities.createMenu(
        MenuUtilities.withNavMenuLinkUrls(response.results[0])
      )
    );
};
```

### Drupal

Below is a suggested workflow for updating scb to a new release of scb-nav:

```sh
# build scb-nav
~/D/scb-nav $ yarn build # or yarn build-web

# Remove existing versions of scb-nav-menu
~/D/scb $ rm sites/all/themes/scb2017/assets/js/scb-nav-menu.*.js

# Copy new artifacts into the project
~/D/scb $ cp ../scb-nav/dist/web/scb-nav-menu.*.js sites/all/themes/scb2017/assets/js/
```

**Important:** Remember to update the asset URLs in `sites/all/themes/scb2017/includes/templatephp.preprocess.inc`.

```php
function _scb2017_include_nav_menu() {
  global $language;

  $langs = [
    'en' => 'scb-nav-menu.en-us.[contenthash].js', // replace hashes
    'de' => 'scb-nav-menu.de-de.[contenthash].js',
    ...
  ];

  $js = 'sites/all/themes/scb2017/assets/js/' . $langs[$language->language];

  // Include React and ReactDOM dependencies
  ...

  drupal_add_js(
    $js,
    array(
      'scope' => 'footer'
    )
  );
}
```

### Maintainer Publish

Remember to bump versions and build before publishing.

```sh
npm version
yarn build
yarn publish
```