Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .nx/version-plans/illustrations-sync-rewrite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
illustrations: patch
---

Rewrite the `sync-illustrations` tooling as source → engine → sinks, fixing the rename, gradient-fill and short-hex handling of the old script, and regenerate `manifest.json` in the new keyed format. Internal tooling and devDependency changes only; the published `esm`/`dts` output is unchanged for consumers.
85 changes: 66 additions & 19 deletions packages/illustrations/DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,29 @@

## Illustration Assets

Each illustration is published in several forms, all generated from one Figma component:
Each illustration is drawn once in Figma, as a light-mode component in the
[CDS Illustrations library](https://www.figma.com/design/LmkJatvMRVzNgfiIkJDb99). That light SVG is
the canonical artifact; every other form is derived from it by the sync:

- **SVG** — light and dark variants, plus a themeable variant whose fills are CSS variables
- **SVG** — the light original, a dark variant, and a themeable variant whose fills are CSS variables
- **PNG** — light and dark rasterizations, used where SVG is not an option
- **JS/ESM maps** — lazily-required SVG strings consumed by the web and mobile packages

Assets are versioned per illustration rather than per release: an illustration's files are named
`<name>-<version>` and the version increments whenever its artwork changes. `versionMap.ts` records
the current version for each name, which is how consumers build CDN URLs such as
- **JS/ESM modules** — the SVG strings wrapped for the web and mobile packages, with lazy maps

The dark and themeable variants are produced by color substitution. Illustrations use a fixed
palette of 15 `illustration/*` color variables, each with a light and a dark value, defined in the
[CDS colors Figma file](https://www.figma.com/design/AH4N0fma2EvI30IltjBGPy) and read through the
[Variables API](https://developers.figma.com/docs/rest-api/#variables) on every run (this needs
Enterprise org access and the `file_variables:read` scope on the token). The sync swaps each light
palette color in the SVG for its dark value to make the dark variant, and for
`var(--illustration-<name>)` to make the themeable one. Colors outside the palette are left as
drawn in every variant.

Assets are versioned per illustration, not per release: files are named `<name>-<version>` and the
version increments whenever the artwork changes. `versionMap.ts` records the current version of each
name, which is how consumers build CDN URLs such as
`https://static-assets.coinbase.com/design-system/illustrations/pictogram/light/someIllustration-2.svg`.
This is also why renaming an illustration resets its version to `0`.

Colors come from a separate Figma file through the
[Variables API](https://developers.figma.com/docs/rest-api/#variables), which supplies the light and
dark value of every illustration color. The sync uses those pairs to derive the dark variant from
the light artwork design provides, and to substitute CSS variables for the themeable variant.
Reading them requires Enterprise org access and the `file_variables:read` scope on the token.

## Syncing Illustrations

**WARNING: FOLLOW THESE INSTRUCTIONS EXACTLY. Copy and paste these commands directly into your terminal, editing them with the current date as necessary. DO NOT MESS AROUND.**
Expand All @@ -45,7 +50,7 @@ nvm use
yarn install
```

4. Run the illustration sync script. The script will create a new `illustrations/YYYY-MM-DD` branch from `origin/master`, sync the illustrations from Figma, regenerate the docsite stories, then commit and push the branch automatically
4. Run the illustration sync. It creates a new `illustrations/YYYY-MM-DD` branch from `origin/master`, writes the generated assets, web's illustration stories, the manifest and a version plan, then commits and pushes the branch. If it fails or nothing changed, the branch is deleted again

```sh
yarn nx run illustrations:sync-illustrations
Expand Down Expand Up @@ -89,21 +94,63 @@ You can get the Percy link from the GitHub Actions "Visreg Web" job on your PR
**Force a full re-sync** — If you need to re-sync all illustrations regardless of when they were last updated, pass the `--sync-all` flag:

```sh
yarn nx run illustrations:sync-illustrations -- --sync-all
yarn nx run illustrations:sync-illustrations --sync-all
```

**Repo is not clean** — The script requires a clean working tree. Stash or commit any pending changes before running the sync.
**Repo is not clean** — The sync requires a clean working tree so that it can create the release branch. Stash or commit any pending changes before running it.

**Syncing without the release branch** — Pass `--no-git` to write into the current branch instead of creating and pushing `illustrations/YYYY-MM-DD`, for example to inspect a `--sync-all` locally. Scratch runs (below) never touch git.

**"`<type>/<name>` has an SVG the sync cannot publish"** — A layer uses a color theming cannot
handle (an alpha hex such as `#0052FF80`, `currentColor`, `rgba()`, `var()`); the message names the
attribute, the value and links to the node in Figma. Nothing was published. Figma itself never
exports these forms, so the usual cause is a pasted or hand-edited SVG; express transparency with a
layer opacity (exported as `fill-opacity`) rather than a color alpha, republish the library and
re-run.

**An illustration's light and dark variants look identical** — The illustration uses a color that the Variables API did not return a dark value for, so the sync fell back to the light fill. Ask design to bind the layer to a published illustration color variable rather than a raw hex value.
**An illustration's light and dark variants look identical** — Its layers use colors outside the illustration palette, which the sync leaves as drawn in every variant. Ask design to bind the layers to the published `illustration/*` color variables rather than raw hex values.

**"Cannot read properties of undefined (reading 'styles')"** — The Figma token is missing the scopes the sync needs. Retrieve a current token from the Config Service.
**"No published color variables named "illustration/..." found"** or a 403 from the variables endpoints — The Figma token is missing the `file_variables:read` scope or Enterprise access the sync needs. Retrieve a current token from the Config Service. The sync refuses to run without the palette rather than silently publishing light-only assets.

**Names must be `[type]/[name]` in camelCase** — The sync derives an illustration's type and name by splitting its Figma name on `/`, and rejects anything that is not camelCase, or a rename that only changes case. Fix the name in Figma and re-run.

**"Skipping components whose type/name is already taken"** — Two published components share a `[type]/[name]`. The sync keeps the one the manifest already knows (otherwise the oldest) and lists the rest; remove or rename the duplicates in Figma.

## How the sync works

The sync's design — the source/engine/sinks structure, the `Illustration` record, reconciliation
rules, sinks and artifacts, and the testing strategy — is documented in
[`scripts/sync-illustrations/README.md`](scripts/sync-illustrations/README.md). Read it before
changing the sync or adding an output destination.

## Testing

The sync's helpers and its version plan generator are unit tested:
The sync's behaviour (add, update, rename, delete, duplicates, incremental runs) is tested end to
end against an in-memory source with the real package sink, and its formats are pinned byte
for byte to recorded Figma responses and the files previous syncs published:

```sh
yarn nx run illustrations:test
```

### Scratch runs against the test fixture file

[CDS Illustrations — sync-illustrations test fixture](https://www.figma.com/design/qtdIR0QTyK0NZcZoAeJmS8)
(Design Systems/Eng) is a published library laid out like the real file, one page per type with a
handful of `mock*` components, that can be freely edited to exercise additions, deletions, renames,
artwork and description changes. Point the sync target at it and at a scratch directory; nothing
under the package is touched:

```sh
export FIGMA_ACCESS_TOKEN=VALUE-FROM-CONFIG-SERVICE
export SYNC_ILLUSTRATIONS_SCRATCH_DIR=/tmp/illustrations-scratch
export SYNC_ILLUSTRATIONS_FIGMA_FILE_ID=qtdIR0QTyK0NZcZoAeJmS8
yarn nx run illustrations:sync-illustrations
```

The scratch directory receives `__generated__/`, `web-stories/`, `manifest.json` and
`version-plans/`; run again
after editing and re-publishing the library to see the incremental diff. Omit
`SYNC_ILLUSTRATIONS_FIGMA_FILE_ID` to scratch-run against the real file (reads only). Remember that
the `/components` endpoint only lists _published_ components, so publish the library after each
edit.
Loading
Loading