npm package: @reading-room/primer
Description: A front end primer for Reading Room projects
Latest version: 2.0.1

# Primer

A front end primer for Reading Room projects.

## Prerequisites

This project requires Node.js v24.13.0 or higher.

This project requires sass v1.97.3 or higher.

## Installation

1. Clone the repository
2. Install the dependencies
3. Run the project

## Usage

To run the project, use the following command:

### Development

```bash
npm run dev
```

### Production

```bash
npm run build
```

## Entries

All front end assets need to be passed to Vite via one or more entry points. These are located in the `src/entries` directory.

## Components

### Primer components

The base Primer components are located in the `src/components` directory. These components are designed to be used as a starting point for building out a project.

They can be edited, removed or added to as needed.

See the README.md file in each component directory for usage instructions.

### Primer-library components

The Primer-library components are web components imported via npm from the primer-library package.

See the README.md file in each component directory in the primer-library package for usage instructions.

## TypeScript

Primer uses TypeScript for type checking and to provide a better developer experience.

Any `.ts` or `.tsx` files imported into the project will be type checked.

You may still use `.js` where type checking is not required, but it is recommended to use TypeScript for consistency and to take advantage of the type checking features.

## SVG Sprite

Primer uses [vite-plugin-svg-spritemap](https://github.com/SpiriitLabs/vite-plugin-svg-spritemap) to generate an SVG sprite. To add an SVG to the sprite, add the SVG to the `src/images/sprite` directory and run the the dev or build task.

The SVG will be added to the sprite svg. In dev mode the sprite is injected into the document body automatically. In production the sprite will need to be added manually.

Once the sprite has been added to the document, SVGs can be used in the following way:

```html
<svg>
  <use xlink:href="/__spritemap#sprite-filename"></use>
</svg>
```

where `sprite-filename` is `sprite-` followed by the name of the SVG file without the `.svg` extension.

## Web fonts

Primer uses [vite-plugin-webfont-dl](https://github.com/feat-agency/vite-plugin-webfont-dl) to download web fonts from Google Fonts for better performance.

To add a web font, add the font to the webfontDownload array in the `vite.config.js` file.

When the build task is run, the fonts will be downloaded and output to the `dist` folder.

## Variables

The `$variables` variable in `src\scss\_variables.scss` is a map of variables that override the defaults defined by the design system.

These variables are converted to CSS custom properties which can be used throughout the project.

You can add additional variables here as needed.

```scss
// Override primer-utils colour defaults
$colours-overrides: (
  col-primary: #584b9b,
  col-secondary: #fdd234,
  col-tertiary: #8ae4e6,
);

// Override primer-utils fonts defaults
$fonts-overrides: (
  font-family-base: "'Roboto', sans-serif",
  font-family-heading: "'Roboto', sans-serif",
);
```

Variable names must be unique, even if they are in different maps, this is because they are converted to CSS custom properties.

## Typography

The `$typography-overrides` variable in `src\scss\_typography.scss` is a map of typography styles that override the defaults defined by the design system.

Each typography style is a map of sizes, which are in turn maps of font properties.

The sizes should map to the breakpoints defined in `src\scss\_breakpoints.scss` for consistency.

These variables should be used as the base for all common typography styles in the project.

You must include values for the entire type style (eg "heading1"), even if only one value is being replaced.

```scss
$typography-overrides: (
  'heading1': (
    'xsmall': (
      'font-family': var(--font-family-heading),
      'font-size-in-px': 48,
      'font-weight': var(--font-weight-bold),
      'line-height-in-px': 50,
    ),
    'large': (
      'font-family': var(--font-family-heading),
      'font-size-in-px': 80,
      'font-weight': var(--font-weight-bold),
      'line-height-in-px': 80,
    ),
    'xlarge': (
      'font-family': var(--font-family-heading),
      'font-size-in-px': 104,
      'font-weight': var(--font-weight-bold),
      'line-height-in-px': 104,
    ),
  ),
);
```

You can also add additional type styles here (eg "heading7").

```scss
$typography-overrides: (
  'heading7': (
    'xsmall': (
      'font-family': var(--font-family-heading),
      'font-size-in-px': 16,
      'font-weight': var(--font-weight-bold),
      'line-height-in-px': 20,
    ),
    'large': (
      'font-family': var(--font-family-heading),
      'font-size-in-px': 20,
      'font-weight': var(--font-weight-bold),
      'line-height-in-px': 24,
    ),
    'xlarge': (
      'font-family': var(--font-family-heading),
      'font-size-in-px': 24,
      'font-weight': var(--font-weight-bold),
      'line-height-in-px': 28,
    ),
  ),
);
```

These are converted to css variables that can be used at the component level.

```scss
.Heading1 {
  color: var(--col-primary);
  font-family: var(--type-heading1-font-family-xsmall);
  font-size: var(--type-heading1-font-size-xsmall);
  font-weight: var(--type-heading1-font-weight-xsmall);
  line-height: var(--type-heading1-line-height-xsmall);

  @include mq.mq($from: large) {
    font-size: var(--type-heading1-font-size-large);
    line-height: var(--type-heading1-line-height-large);
  }

  @include mq.mq($from: xlarge) {
    font-size: var(--type-heading1-font-size-xlarge);
    line-height: var(--type-heading1-line-height-xlarge);
  }
}
```

## Storybook

To view the components in Storybook, run the following command:

```bash
npm run storybook
```

To build the Storybook static files, run the following command:

```bash
npm run build-storybook
```

To build the Storybook static files and then deploy the Storybook to Chromatic, run the following command:

```bash
npm run chromatic
```

You can access the Storybook at: `https://branch-name--6835d2396cda6e35df838e6b.chromatic.com/` where `branch-name` is the name of the branch that was deployed, with slashes replaced by dashes.

## Local development across Primer, primer-library and primer-utils

When developing components in Primer and primer-library concurrently, sometimes it's necessary to symlink the primer-library or primer-utils packages to Primer.

This can be done by creating a `link.config.json` file in the root of the Primer project with the following content:

```json
{
  "packages": ["../primer-library", "../primer-utils"]
}
```

Where `../primer-library` and `../primer-utils` are the paths (either relative or absolute) to the primer-library and primer-utils packages.

> **Note:** It's not recommended to commit this file to source control since this is for local development with local paths.

Then run the following command to create the symlinks:

```bash
npx link
```

This will create symlinks to the primer-library and primer-utils packages on your local machine, and will handle them as though they were installed in `node_modules`.

_However_ this causes problems with Vite serve, which won't allow importing of content outside of the root directory.

To work around this, you can create a `.env.development.local` file in the root of the Primer project with the following content:

```env
STORYBOOK_PRIMER_LIBRARY_PATH=../primer-library
STORYBOOK_PRIMER_UTILS_PATH=../primer-utils
```

Where `../primer-library` and `../primer-utils` are the paths (either relative or absolute) to the primer-library and primer-utils packages.

> **Note:** It's not recommended to commit this file to source control since this is for local development with local paths.

The duplicate configs aren't ideal, but you should only need to do this when concurrently developing across Primer, primer-library and primer-utils.

## Updating Primer

Ideally all dependencies should be kept up to date to take advantage of new features and security updates.

Before running npm update, you should run the storybook update script to ensure that the Storybook dependencies are updated correctly and migrated if necessary.

```bash
npx storybook@latest upgrade
```

After running the Storybook upgrade, you can run the following command to update all dependencies to the latest minor version.

```bash
npx npm-check-updates --target minor -u
```

For a major Primer version release, you should update all dependencies to the latest major version.

```bash
npx npm-check-updates -u
```

This will likely require manual intervention to resolve breaking changes introduced by the updates.

**Ensure upgrades are performed across Primer, primer-library and primer-utils at the same time to ensure compatibility.**