diff --git a/guides/ci.md b/guides/ci.md
new file mode 100644
index 000000000..44101cd15
--- /dev/null
+++ b/guides/ci.md
@@ -0,0 +1,84 @@
+# Continuous Integration and automated checks
+
+This guide explains what runs locally versus in CI, how visual testing works, and how to act on failures.
+
+## Overview
+
+- Local: `yarn test` (or `npm run test`) via `dotrun test` runs spelling, formatting/linting, Parker metrics, and Jest
+ tests. Some tasks (e.g., Percy) are CI-only.
+- CI (GitHub Actions): Percy visual tests run on PRs that meet selectivity rules or when labeled.
+ See [Percy workflow](/guides/percy-workflow.md).
+- Legacy deployment jobs run in Jenkins for PS5 (high-level only; see [Deployment](/guides/deployment.md)).
+
+## Local checks
+
+It's good practice to run these checks locally before pushing changes.
+
+```
+npx prettier -c -w . # Formatting/linting, applying safe fixes
+yarn test # Spellcheck, Parker metrics, Jest tests
+```
+
+Locally, you’ll see failures from:
+
+- Spelling (`mdspell`): currently configured with en‑GB; our policy for new docs is en‑US. Use `.spelling` to ignore
+ valid en‑US words and technical terms. See [Language policy](/guides/language.md).
+- Format/lint (e.g., Prettier/Stylelint): Read the output for fix details.
+- Parker CSS metrics: see [Parker CSS metrics](#parker-css-metrics) below for details.
+- Jest tests: snapshot configuration tests; see [Snapshot generation tests (Jest)](#snapshot-generation-tests-jest)
+ below for details.
+
+## Visual testing (Percy)
+
+Percy runs visual snapshot tests against the examples site. On PRs, it triggers when:
+
+- The PR targets `main`, and either:
+ - It passes the selectivity filters (changes to `scss/`, `templates/docs/examples/`, `templates/_macros/`,
+ `tokens/`, or `sd.config.json`, and it’s not a draft), or
+ - The PR carries the label `Review: Percy needed`.
+
+Key points:
+
+- Examples are discovered by `snapshots.js` and include both regular and `standalone/` variants for many paths.
+- Combined examples (`combined.html`) reduce snapshot counts by aggregating variants; this helps control quota.
+- Examples are snapshotted in all themes (light, dark, paper), at the large screen size. On the light theme, examples
+ are also snapshotted at the small screen size. If an example is "responsive" (indicated by including "responsive" in
+ the filename), it will be snapshotted at the medium screen size.
+ See [Percy workflow](/guides/percy-workflow.md) for device widths, themes, and combined-behavior rules.
+- Reviewing Percy: follow the flow in the Percy guide; when in doubt, re-run the job by re-applying the "Review: Percy
+ needed" label.
+
+## Snapshot generation tests (Jest)
+
+The file `tests/snapshots.test.js` validates that `snapshots.js` returns a correct set of snapshots:
+
+- Ensures unique names and URLs.
+- Ensures correct base URL and expected widths.
+- Special-cases combined examples that embed responsive examples.
+
+If you add a `combined.html` for a group that should be treated as responsive, and the test does not infer it from
+filenames, update `RESPONSIVE_COMBINED_EXAMPLES` in `tests/snapshots.test.js`.
+
+## Parker CSS metrics
+
+Parker provides coarse CSS complexity/size guardrails. It’s unmaintained upstream but still catches regressions.
+Thresholds live in `tests/parker.js` (e.g., “Stylesheet size”, “Top specificity”). Example failure:
+
+```
+$ node -e 'require("./tests/parker").parkerTest()'
+✘ - Stylesheet size (519994) exceeds threshold (422850)
+error Command failed with exit code 1.
+```
+
+If your change is justified, update the relevant thresholds in `tests/parker.js` and explain the rationale in your PR.
+
+## Cypress (limited)
+
+Cypress usage is experimental and not central to our process. Some specs exist (for example,
+`cypress/e2e/patterns/accordion.cy.js`). Flakes can happen; re-running in GitHub Actions often resolves transient
+failures. Prefer Percy and unit-level checks unless an E2E adds clear value.
+
+## Spelling (`mdspell`)
+
+Scripts currently use en‑GB dictionaries. Our policy is to write new docs in en‑US. If `mdspell` flags a valid en‑US
+spelling or a technical term, add it to `.spelling`. See [Language policy](/guides/language.md).
diff --git a/guides/hacking.md b/guides/hacking.md
index 94cf93d29..476ffe677 100644
--- a/guides/hacking.md
+++ b/guides/hacking.md
@@ -6,15 +6,26 @@
- [Via dotrun](#via-dotrun)
- [Via Docker](#via-docker)
- [Viewing documentation and examples](#viewing-documentation-and-examples)
+- [Relationship between docs pages and examples](#relationship-between-docs-pages-and-examples)
- [QA testing](#qa-testing)
- [The baseline grid](#the-baseline-grid)
- [Standalone examples](#standalone-examples)
+ - [Combined examples](#combined-examples)
- [Cross browser testing](#cross-browser-testing)
+- [Running tests locally](#running-tests-locally)
+- [Percy](#percy)
+- [CI overview](#ci-overview)
+- [Patterns vs Components](#patterns-vs-components)
+- [Class name prefixes](#class-name-prefixes)
+- [Language policy](#language-policy)
- [Adding new icons](#adding-new-icons)
## Running the project
-The simplest way to run the Vanilla framework on all operating systems is by [installing Docker](https://docs.docker.com/engine/installation/) (Linux users may need to [add your user to the `docker` group](https://docs.docker.com/engine/installation/linux/linux-postinstall/)) and [dotrun](https://github.com/canonical/dotrun/), and using the `dotrun` command to build or serve the project:
+The simplest way to run the Vanilla framework on all operating systems is
+by [installing Docker](https://docs.docker.com/engine/installation/) (Linux users may need to [add your user to the
+`docker` group](https://docs.docker.com/engine/installation/linux/linux-postinstall/))
+and [dotrun](https://github.com/canonical/dotrun/), and using the `dotrun` command to build or serve the project:
```bash
# Build CSS into the ./build/ directory:
@@ -32,33 +43,56 @@ dotrun watch
dotrun exec yarn run --non-interactive
```
-When writing SCSS, it's useful to run `dotrun` and `dotrun watch` in separate terminals so changes are quickly built and ready for the browser to pick up on page reload.
+When writing SCSS, it's useful to run `dotrun` and `dotrun watch` in separate terminals so changes are quickly built and
+ready for the browser to pick up on page reload.
-If you want to speed up the build or watch scripts you can run the project without including the standalone examples, using `dotrun build:essential` or `dotrun watch:essential`.
+If you want to speed up the build or watch scripts you can run the project without including the standalone examples,
+using `dotrun build:essential` or `dotrun watch:essential`.
## Viewing documentation and examples
Once the server is running, you can visit in your browser to see the project.
-The documentation for the latest version of Vanilla framework is hosted at , and the documentation markdown files live in the [`docs` folder](/docs).
+The documentation for the latest version of Vanilla framework is hosted at , and the
+documentation markdown files live in the [`docs` folder](/docs).
-The [examples directory](/docs/examples) contains example markup for each component of the framework, and these examples can be viewed in the browser at .
+The [examples directory](/docs/examples) contains example markup for each component of the framework, and these examples
+can be viewed in the browser at .
+
+## Relationship between docs pages and examples
+
+Vanilla’s documentation pages and example templates live side by side but serve different purposes:
+
+- Docs pages (prose, guidance, and page structure) live under `templates/docs/**`.
+- Example templates (the rendered component/pattern/utility examples) live under `templates/docs/examples/**`.
+
+When adding or updating examples:
+
+- Add or edit the example’s Jinja template under `templates/docs/examples/**`.
+- If a section uses a combined example page (see below), explicitly include your new example in that section’s
+ `combined.html` file.
+- Many URLs and side‑navigation paths still use the legacy `patterns/` segment; this is expected.
+ See [Patterns vs Components](#patterns-vs-components) for the current terminology.
## QA testing
-We rigorously test all new additions to the Vanilla project, and the following are the most commonly used techniques we have in our toolbox.
+We rigorously test all new additions to the Vanilla project, and the following are the most commonly used techniques we
+have in our toolbox.
### The baseline grid
All text within an example should sit neatly on the baseline, unless otherwise agreed with the design team.
-You can check the baseline alignment is correct when viewing an example, using the toggle present in the bottom right of your browser window.
+You can check the baseline alignment is correct when viewing an example, using the toggle present in the bottom right of
+your browser window.
# 
### Standalone examples
-Every example created in Vanilla automatically generates a standalone example. Where a regular example includes the entirety of Vanilla's CSS, the standalone examples exist to ensure that each example works by importing only the bare minimum of CSS needed.
+Every example created in Vanilla automatically generates a standalone example. Where a regular example includes the
+entirety of Vanilla's CSS, the standalone examples exist to ensure that each example works by importing only the bare
+minimum of CSS needed.
So, an example created at:
@@ -68,37 +102,224 @@ will make available a standalone pattern at:
`/docs/examples/standalone/patterns/foo`
-When creating a new example, you will need to create a new, appropriately name SCSS file within [`/scss/standalone`](/scss/standalone), and reference it in your example, using the following block:
+When creating a new example, you will need to create a new, appropriately named SCSS file within [
+`/scss/standalone`](/scss/standalone), and reference it in your example, using the following block:
```
{% block standalone_css %}patterns_foo{% endblock %}
```
-If you are simply updating an existing example, make sure to check the standalone example and, if necessary, add any required includes to that examples standalone SCSS file.
+If you are simply updating an existing example, make sure to check the standalone example and, if necessary, add any
+required includes to that examples standalone SCSS file.
+
+Notes and tips:
+
+- Standalone SCSS filenames generally mirror the example path (e.g., `templates/docs/examples/patterns/accordion/...` →
+ `scss/standalone/patterns_accordion.scss`).
+- Keep the standalone CSS minimal. If you need broader framework CSS for the example, consider whether it belongs in the
+ full (non‑standalone) example instead.
+
+### Combined examples
+
+Combined examples aggregate multiple variants of a component or pattern onto a single page named `combined.html`. We use
+them primarily to reduce the number of screenshots Percy must take (controlling quota usage and noise).
+
+Rules of thumb:
+
+- Place `combined.html` in the directory that groups the variants (e.g.,
+ `templates/docs/examples/patterns/buttons/combined.html`).
+- Explicitly include each example template using `{% include 'path/to/example.html' %}`.
+- Append new includes to the end of the file so later examples don’t shift, which keeps Percy diffs focused on your
+ changes.
+- If any sibling or descendant example includes “responsive” in its name, Percy will capture tablet width in addition to
+ desktop and (for the default theme) mobile. See the Percy workflow guide for details.
+
+See also: [Percy workflow](/guides/percy-workflow.md) for snapshot widths, color themes, how `snapshots.js` discovers
+examples (including combined pages), and when to update tests.
### Cross browser testing
-We are committed to testing our work in [several major browsers](https://vanillaframework.io/browser-support). If you lack access to a particular browser, we have a company [BrowserStack](https://www.browserstack.com/) account available for use.
+We are committed to testing our work in [several major browsers](https://vanillaframework.io/browser-support). If you
+lack access to a particular browser, we have a company [BrowserStack](https://www.browserstack.com/) account available
+for use.
### Running tests locally
-Before proposing a pull request, ensure that the tests pass on your local fork. To kick off the tests, run `dotrun test`.
+Before proposing a pull request, ensure that the tests pass on your local fork. To kick off the tests, run
+`dotrun test`.
### Percy
-When you have [created a pull request](/guides/pull-requests.md), GitHub actions will automatically kick off the Continuous Integration pipeline, including a [Percy](https://percy.io/) check.
+When you have [created a pull request](/guides/pull-requests.md), GitHub actions will automatically kick off the
+Continuous Integration pipeline, including a [Percy](https://percy.io/) check.
+
+Percy builds your branch, then checks each example for changes against the last version of the project that was approved
+by Percy. If there are any changes, the CI checks will fail, and the changes it found will be available to review in
+Percy's dashboard.
+
+## CI overview
+
+This is a brief overview of common checks. See [CI overview](/guides/ci.md) for the full guide.
+
+- Visual testing (Percy): runs on PRs with selective triggers. Combined examples reduce snapshots and quota. See
+ [`guides/percy-workflow.md`](./percy-workflow.md) for details.
+- Snapshot generation tests (Jest): `tests/snapshots.test.js` validates `snapshots.js` behavior (themes, widths,
+ combined examples). If you add a combined example that includes responsive samples, you may need to update the test
+ list.
+- Parker (CSS metrics): still in use as a practical guardrail though unmaintained upstream. Thresholds are configured in
+ `tests/parker.js`. If Parker fails and your change is justified, update thresholds carefully and explain in the PR.
+- Cypress (limited): experimental coverage (e.g., `cypress/e2e/patterns/accordion.cy.js`); flakes happen — rerunning in
+ GitHub Actions often resolves it. Add new specs only when they provide clear value.
+- Spelling (`mdspell`): scripts currently use en‑GB. Our policy is to write new docs in en‑US. If en‑US words are
+ flagged, add them to `.spelling` temporarily. See the [Language policy](/guides/language.md).
+
+## Patterns vs Components
+
+Historically we called components “patterns”, and this legacy remains in URLs and the side navigation. Today we use:
+
+- Components: smaller, reusable building blocks (historically located under `patterns/` in URLs/paths).
+- Patterns: higher‑level compositions built from components via Jinja macros to create larger sections with a small API.
+
+When contributing, follow existing paths and naming conventions. Do not attempt to rename URL paths or navigation
+structure unless undertaking a dedicated migration.
+
+## Class name prefixes
+
+- `.p-` — pattern/component selectors (historical naming), e.g., `.p-accordion`, `.p-accordion__tab`.
+- `.u-` — utilities (single‑purpose helpers), e.g., `.u-align-text--right`.
+- `.l-` — layout helpers (grid/layout utilities).
+
+Use these prefixes consistently when adding new selectors.
+
+## Language policy
+
+New documentation should be written in en‑US. Existing en‑GB content remains acceptable. Use the `.spelling` file to
+suppress `mdspell` warnings for en‑US words and technical terms. See the [Language policy](/guides/language.md) for
+details.
+
+## Icons
+
+### Icon architecture
-Percy builds your branch, then checks each example for changes against the last version of the project that was approved by Percy. If there are any changes, the CI checks will fail, and the changes it found will be available to review in Percy's dashboard.
+Our icons are generated from SVG files and converted to a set of mixins stored in
+the [icon definitions file](../scss/_base_icon-definitions.scss).
+The mixins are:
-## Adding new icons
+- `vf-icon-NAME-url()` - is a function that returns data URL of the SVG generated with the passed color (white/black)
+- `vf-icon-NAME()` - is a legacy mixin for components that want to change the color of the icon, and not depend on the
+ theme
+- `vf-icon-NAME-themed` - is a themed version of the icon, that will automatically respect the theme set on the parent
+ component
-When adding new icons to Vanilla, we need to convert them from SVGs to data URLs so we can use them as background images.
+The [icon pattern file](../scss/_patterns_icons.scss) then defines mixins for each icon that expose an icon class.
+The icon class consumes a base icon placeholder and the appropriate icon mixin. An example is given below:
+
+```scss
+@mixin vf-p-icon-history {
+ .p-icon--history {
+ @extend %icon;
+ @include vf-icon-history-themed;
+ }
+}
+```
+
+Generating these mixins, and the icon class binding, is assisted by
+a [script](../scripts/convert-svgs-to-icon-mixins.js).
+See [adding new icons](#adding-new-icons) for instructions on how to add new icons,
+and [migrating old icons](#migrating-old-icons-to-new-icon-them)
+for instructions on how to migrate existing icons that don't follow this structure.
+
+### Adding new icons
+
+When adding new icons to Vanilla, we need to convert them from SVGs to data URLs so we can use them as background
+images.
To achieve this quickly, you can use the `icon-svgs-to-mixins` script:
- Place the SVGs to be converted in a directory somewhere on your local machine.
- In your terminal, run `dotrun icon-svgs-to-mixins path/to/svg/directory/`.
-This will output a mixin for each SVG in the directory. Each mixin will take its name from the SVG's filename i.e. "tick.svg" will output a mixin named "vf-icon-tick".
+This will output a mixin for each SVG in the directory. Each mixin will take its name from the SVG's filename i.e. "
+tick.svg" will output a mixin named "vf-icon-tick".
+
+Bear in mind that the actual SCSS mixins will evolve over time, so you may need to update the mixin output in this
+script to match them.
+
+### Migrating old icons to new icon theming
+
+Some of our icons predate our current icon architecture. Icons that don't consume a `-themed` mixin may not work as
+expected when used in a dark theme.
+
+```scss
+// _base_icon-definitions.scss
+
+// This icon mixin only sets the color of the icon; it does not adjust according to the active theme.
+@mixin vf-icon-restart($color) {
+ background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.197 1.15v4.931h-1.5l-.001-2.478a5.5 5.5 0 106.302-.215l.75-1.3a7 7 0 11-8.263.562H1.268v-1.5h4.93z' fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd'/%3E%3C/svg%3E");
+}
+
+// _patterns_icons.scss
+@mixin vf-p-icon-restart {
+ .p-icon--restart {
+ @extend %icon;
+ @include vf-icon-restart($colors--light-theme--icon);
+
+ [class*='--dark'] &,
+ body.is-dark &,
+ &.is-light, // DEPRECATED: use is-dark instead
+ &.is-dark {
+ @include vf-icon-restart($colors--dark-theme--icon);
+ }
+ }
+}
+```
+
+There is not currently a script to migrate these icons to the new architecture. To migrate these icons, you can either:
-Bear in mind that the actual SCSS mixins will evolve over time, so you may need to update the mixin output in this script to match them.
+1. Obtain the SVG for the underlying icon following the [adding new icons](#adding-new-icons) process, entirely
+ recreating the icon.
+2. Use the existing icon's data URL and refactor the icon mixin to consume the `-themed` mixin.
+
+Steps for (1) are outlined in the [adding new icons](#adding-new-icons) section. Steps for (2) are outlined below:
+
+1. Copy the existing icon's data URL.
+2. Create a function `vf-icon-NAME-url` in the [icon definitions file](../scss/_base_icon-definitions.scss) that returns
+ the data URL. The function should accept a color as a parameter, and apply that color to the icon using
+ `vf-url-friendly-color()`.
+
+```scss
+@function vf-icon-restart-url($color) {
+ @return url("data:image/svg+xml,%3Csvg width='16' height='16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.197 1.15v4.931h-1.5l-.001-2.478a5.5 5.5 0 106.302-.215l.75-1.3a7 7 0 11-8.263.562H1.268v-1.5h4.93z' fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd'/%3E%3C/svg%3E");
+}
+```
+
+3. Create a mixin `vf-icon-NAME` in the [icon definitions file](../scss/_base_icon-definitions.scss) that consumes the
+ URL function and passes a color parameter (defaulting to
+ `$colors--light-theme--icon`).
+
+```scss
+@mixin vf-icon-restart($color: $colors--light-theme--icon) {
+ background-image: vf-icon-restart-url($color);
+}
+```
+
+4. Create a new mixin `vf-icon-NAME-themed` in the [icon definitions file](../scss/_base_icon-definitions.scss) that
+ uses `vf-themed-icon` to set the icon color based on active theme.
+
+```scss
+@mixin vf-icon-restart-themed {
+ @include vf-themed-icon($light-value: vf-icon-restart-url($colors--light-theme--icon), $dark-value: vf-icon-restart-url($colors--dark-theme--icon));
+}
+```
+
+5. Update the icon pattern file to consume the themed mixin. You can also remove any theme class selectors, as these are
+ handled by `vf-themed-icon`.
+
+```scss
+@mixin vf-p-icon-restart {
+ .p-icon--restart {
+ @extend %icon;
+ @include vf-icon-restart-themed;
+ }
+}
+```
diff --git a/guides/language.md b/guides/language.md
new file mode 100644
index 000000000..46d340908
--- /dev/null
+++ b/guides/language.md
@@ -0,0 +1,11 @@
+# Language policy
+
+New documentation should be written in en‑US per the current company style. Existing pages written in en‑GB are acceptable; do not spend time converting legacy content.
+
+## Spell checking with mdspell
+
+Our spellcheck scripts currently use en‑GB dictionaries. This can flag valid en‑US spellings.
+
+When `mdspell` flags a word that is correct in en‑US, or a highly technical term that is not in the dictionaries (e.g., `h1`, `px`, `rem`, `WCAG`, `Attribution‑ShareAlike`), add it to the `.spelling` file to suppress false positives.
+
+We are not planning a migration of the checker to en‑US at this time; this project is receiving limited changes while focus is on Pragma.
diff --git a/guides/percy-workflow.md b/guides/percy-workflow.md
index e9f0c962a..68989d39f 100644
--- a/guides/percy-workflow.md
+++ b/guides/percy-workflow.md
@@ -1,7 +1,10 @@
## Percy visual testing
We use [Percy](https://percy.io) for visual testing. Percy tests are run against pull requests to
-ensure that PRs do not introduce visual regressions. Your PR will be tested by Percy if it meets the following conditions:
+ensure that PRs do not introduce visual regressions. Your PR will be tested by Percy if it meets the following
+conditions:
+
+See also: [Hacking](/guides/hacking.md) for general guidance on authoring and organizing examples used by Percy.
- PR is against the `main` branch
- One of the following is true:
@@ -14,19 +17,25 @@ ensure that PRs do not introduce visual regressions. Your PR will be tested by P
- `sd.config.json`
- PR is not a draft
- PR is labeled with "Review: Percy needed"
- - Note that a Percy (labeled) workflow will be triggered on each labelling and synchronisation event on PRs to `main`. They will be skipped shortly after starting if the PR does not have the "Review: Percy needed" label.
+ - Note that a Percy (labeled) workflow will be triggered on each labelling and synchronisation event on PRs to
+ `main`. They will be skipped shortly after starting if the PR does not have the "Review: Percy needed" label.
To ensure optimal Percy usage, we suggest the following PR flow:
1. Open the PR (against `main`) as a draft. Ensure that all non-Percy PR status checks pass.
2. Apply the "Review: Percy needed" label to the PR to trigger a Percy test.
-3. Review the initial Percy build. After a few minutes, it will be available on our [Percy dashboard](https://percy.io/bb49709b/vanilla-framework). You can also click the Percy status check on the PR to navigate directly to the test results.
+3. Review the initial Percy build. After a few minutes, it will be available on
+ our [Percy dashboard](https://percy.io/bb49709b/vanilla-framework). You can also click the Percy status check on the
+ PR to navigate directly to the test results.
-4. If there are additional changes needed to the PR through the review process, you can remove the "Review: Percy needed"
- label and mark the PR as a draft to prevent additional Percy tests from running. Any commits you add to the PR will not trigger a Percy test, as long as the PR is a draft and does not have the "Review: Percy needed" label.
-5. Once the PR is ready for final review, remove the draft status and reapply the "Review: Percy needed" label to trigger
+4. If there are additional changes needed to the PR through the review process, you can remove the "Review: Percy
+ needed"
+ label and mark the PR as a draft to prevent additional Percy tests from running. Any commits you add to the PR will
+ not trigger a Percy test, as long as the PR is a draft and does not have the "Review: Percy needed" label.
+5. Once the PR is ready for final review, remove the draft status and reapply the "Review: Percy needed" label to
+ trigger
a final Percy test.
6. If the Percy test passes, apply "Review: Percy +1" to indicate that the PR has passed Percy testing.
@@ -34,7 +43,8 @@ To ensure optimal Percy usage, we suggest the following PR flow:
#### Baseline Workflow
-The [baseline workflow](../.github/workflows/percy-baseline.yml) runs a Percy test on every push to `main`, and sets the results
+The [baseline workflow](../.github/workflows/percy-baseline.yml) runs a Percy test on every push to `main`, and sets the
+results
as the new Percy baseline that all future PRs will be compared against.
#### Prepare Workflow
@@ -44,27 +54,33 @@ uploads all files in the PR that have any affects on the visual appearance of th
#### PR Snapshot Workflow
-The [snapshot workflow](../.github/workflows/pr-percy-snapshots.yml) downloads the artefacts from the [prepare workflow](#prepare-workflow)
-and calls the [Percy snapshot action](../.github/actions/percy-snapshot/action.yml) to build, run, & visually test Vanilla.
+The [snapshot workflow](../.github/workflows/pr-percy-snapshots.yml) downloads the artefacts from
+the [prepare workflow](#prepare-workflow)
+and calls the [Percy snapshot action](../.github/actions/percy-snapshot/action.yml) to build, run, & visually test
+Vanilla.
The PR snapshot workflow is always called after the completion of the [prepare workflow](#prepare-workflow).
### Example snapshots
-Percy is run by executing `yarn percy` or `npm run percy` in the root of the project. The [Percy CLI](https://github.com/percy/cli)
+Percy is run by executing `yarn percy` or `npm run percy` in the root of the project.
+The [Percy CLI](https://github.com/percy/cli)
runs [snapshots.js](../snapshots.js) which returns a list of all the snapshots that Percy will take.
-Percy uses our [examples](https://vanillaframework.io/docs/examples) to take snapshots of all components, patterns, and utilities in Vanilla.
+Percy uses our [examples](https://vanillaframework.io/docs/examples) to take snapshots of all components, patterns, and
+utilities in Vanilla.
[snapshots.js](../snapshots.js) will take a snapshot of an example template file if the following conditions are met:
- Is an HTML file in `templates/docs/examples/`
- File is not a partial (does not start with `_`)
-- File is not included in a combined example (is not in the same directory as a combined example or in a directory that descends from a directory with a combined example)
+- File is not included in a combined example (is not in the same directory as a combined example or in a directory that
+ descends from a directory with a combined example)
#### Snapshot widths
-Each snapshot object returned by [snapshots.js](../snapshots.js) has a `widths` array property that specifies the widths (in pixels) at which the snapshot should be captured.
+Each snapshot object returned by [snapshots.js](../snapshots.js) has a `widths` array property that specifies the
+widths (in pixels) at which the snapshot should be captured.
The following table shows the widths at which snapshots are captured and which examples they apply to:
| Device | Width (px) | Captured on |
@@ -77,29 +93,41 @@ Each width is captured as a separate screenshot, and counts as an additional scr
#### Snapshot browsers
-Percy can be configured to take snapshots in multiple browsers. Each additional browser counts as an additional set of screenshots in Percy's pricing model.
-Vanilla is currently only tested on Chrome. To add additional browsers, view the [Percy project settings page](https://percy.io/bb49709b/vanilla-framework/settings).
+Percy can be configured to take snapshots in multiple browsers. Each additional browser counts as an additional set of
+screenshots in Percy's pricing model.
+Vanilla is currently only tested on Chrome. To add additional browsers, view
+the [Percy project settings page](https://percy.io/bb49709b/vanilla-framework/settings).
#### Combined examples
Combined examples are a way to show all the variants of a component or pattern on the same page. This helps us keep our
Percy usage down by only taking one snapshot of a component or pattern, rather than one for each variant.
Combined examples follow a naming convention: they must be named `combined.html`.
-If `combined.html` is found in a directory, [snapshots.js](../snapshots.js) will assume that every example in that directory (and its subdirectories) is rendered in the `combined.html` file.
+If `combined.html` is found in a directory, [snapshots.js](../snapshots.js) will assume that every example in that
+directory (and its subdirectories) is rendered in the `combined.html` file.
+
+Tip: When adding new includes to a `combined.html`, append them to the end of the file to avoid shifting subsequent
+examples and inflating visual diffs.
-**Combined examples do not currently include the JavaScript or CSS that is included in individual examples by `{% block script %}` and `{% block style %}` tags.**
+**Combined examples do not currently include the JavaScript or CSS that is included in individual examples
+by `{% block script %}` and `{% block style %}` tags.**
##### Creating a combined example
1. Create a Jinja template file named `combined.html` in any subdirectory of `templates/docs/examples/`
-2. In your `content` block, create a `with` block that sets the flag `is_combined` to `true`. This will ensure that the [base example template](../templates/_layouts/examples.html) renders the example without the `{% block script %}` and `{% block style %}` tags and adds links to the individual examples.
-3. Include the examples you want to combine in the `combined.html` file using `{% include 'path/to/example.html' %}` inside the `with` block. It is good practice to separate the examples in `` tags.
+2. In your `content` block, create a `with` block that sets the flag `is_combined` to `true`. This will ensure that
+ the [base example template](../templates/_layouts/examples.html) renders the example without the `{% block script %}`
+ and `{% block style %}` tags and adds links to the individual examples.
+3. Include the examples you want to combine in the `combined.html` file using `{% include 'path/to/example.html' %}`
+ inside the `with` block. It is good practice to separate the examples in `` tags.
-For example, see the [combined example for the button pattern](../templates/docs/examples/patterns/buttons/combined.html).
+For example, see
+the [combined example for the button pattern](../templates/docs/examples/patterns/buttons/combined.html).
##### Spacing below examples
-If an example's content is expected to overflow its body (such as a dropdown or tooltip), you can use the `spacing_below` parameter to add space below the example.
+If an example's content is expected to overflow its body (such as a dropdown or tooltip), you can use the
+`spacing_below` parameter to add space below the example.
`spacing_below` `rems` will be added beneath the example as `margin-bottom`.
For example:
@@ -113,17 +141,24 @@ For example:
### Testing
-[snapshots.test.js](../tests/snapshots.test.js) is a [Jest](https://jestjs.io/) testing file used to test the output of the [snapshots.js](../snapshots.js) file.
-It tests that the snapshots are correctly generated. It is run as part of our wider testing script (`yarn test`), but you can also execute it directly by running `npx jest tests/snapshots.test.js`.
+[snapshots.test.js](../tests/snapshots.test.js) is a [Jest](https://jestjs.io/) testing file used to test the output of
+the [snapshots.js](../snapshots.js) file.
+It tests that the snapshots are correctly generated. It is run as part of our wider testing script (`yarn test`), but
+you can also execute it directly by running `npx jest tests/snapshots.test.js`.
-[snapshots.js](../snapshots.js) considers `combined.html` to require responsive snapshots if a sibling or descendant file contains `responsive` in its name.
-[snapshots.test.js](../tests/snapshots.test.js) does not read the filesystem to decide whether a combined snapshot is responsive.
-If you add a combined example that must be captured responsively, you must add the path of that example to `RESPONSIVE_COMBINED_EXAMPLES` in [snapshots.test.js](../tests/snapshots.test.js).
+[snapshots.js](../snapshots.js) considers `combined.html` to require responsive snapshots if a sibling or descendant
+file contains `responsive` in its name.
+[snapshots.test.js](../tests/snapshots.test.js) does not read the filesystem to decide whether a combined snapshot is
+responsive.
+If you add a combined example that must be captured responsively, you must add the path of that example to
+`RESPONSIVE_COMBINED_EXAMPLES` in [snapshots.test.js](../tests/snapshots.test.js).
### PR File Inclusion
-Only some of a pull request's files are represented in each pull request snapshot test. Depending on which files need to be changed,
-you may need to make a separate pull request to make changes to `main` before a pull request will use your changes in Percy testing.
+Only some of a pull request's files are represented in each pull request snapshot test. Depending on which files need to
+be changed,
+you may need to make a separate pull request to make changes to `main` before a pull request will use your changes in
+Percy testing.
#### Files included in Percy tests