@motion-proto/live-tokens 0.97.0 → 0.98.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +5 -0
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +4 -3
  3. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +71 -11
  4. package/CHANGELOG.md +272 -0
  5. package/README.md +2 -2
  6. package/bin/check-component.mjs +8 -0
  7. package/bin/check-page.mjs +6 -0
  8. package/bin/cli.mjs +36 -6
  9. package/bin/contractRunner.mjs +142 -17
  10. package/bin/lib/findings.mjs +20 -4
  11. package/bin/rules/a11y.mjs +53 -0
  12. package/dist-plugin/{chunk-A4TBP4MM.js → chunk-SLICH4IH.js} +2 -2
  13. package/dist-plugin/index.cjs +148 -3
  14. package/dist-plugin/index.js +250 -105
  15. package/dist-plugin/setColors/index.js +1 -1
  16. package/package.json +47 -2
  17. package/src/demo/LabeledSelect.svelte +1 -1
  18. package/src/editor/bootstrap.ts +3 -1
  19. package/src/editor/component-editor/BadgeEditor.svelte +13 -0
  20. package/src/editor/component-editor/ButtonEditor.svelte +33 -2
  21. package/src/editor/component-editor/CalloutEditor.svelte +13 -0
  22. package/src/editor/component-editor/CardEditor.svelte +12 -2
  23. package/src/editor/component-editor/CodeSnippetEditor.svelte +11 -1
  24. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +18 -1
  25. package/src/editor/component-editor/CornerBadgeEditor.svelte +13 -0
  26. package/src/editor/component-editor/DialogEditor.svelte +15 -0
  27. package/src/editor/component-editor/IconButtonEditor.svelte +29 -1
  28. package/src/editor/component-editor/ImageEditor.svelte +20 -9
  29. package/src/editor/component-editor/ImageLightboxEditor.svelte +44 -0
  30. package/src/editor/component-editor/InlineEditActionsEditor.svelte +13 -1
  31. package/src/editor/component-editor/InputEditor.svelte +23 -0
  32. package/src/editor/component-editor/MenuSelectEditor.svelte +27 -1
  33. package/src/editor/component-editor/NotificationEditor.svelte +15 -0
  34. package/src/editor/component-editor/PanelEditor.svelte +1 -1
  35. package/src/editor/component-editor/ProgressBarEditor.svelte +13 -0
  36. package/src/editor/component-editor/RadioButtonEditor.svelte +20 -1
  37. package/src/editor/component-editor/SectionDividerEditor.svelte +41 -13
  38. package/src/editor/component-editor/SegmentedControlEditor.svelte +29 -1
  39. package/src/editor/component-editor/SideNavigationEditor.svelte +40 -1
  40. package/src/editor/component-editor/SlidePagerEditor.svelte +20 -0
  41. package/src/editor/component-editor/SliderEditor.svelte +33 -0
  42. package/src/editor/component-editor/TabBarEditor.svelte +23 -2
  43. package/src/editor/component-editor/TableEditor.svelte +14 -0
  44. package/src/editor/component-editor/ToggleEditor.svelte +17 -0
  45. package/src/editor/component-editor/TooltipEditor.svelte +11 -2
  46. package/src/editor/component-editor/VideoFrameEditor.svelte +8 -0
  47. package/src/editor/component-editor/VideoLightboxEditor.svelte +10 -0
  48. package/src/editor/component-editor/registration.ts +2 -1
  49. package/src/editor/component-editor/registry.ts +69 -27
  50. package/src/editor/component-editor/scaffolding/DemoHeader.svelte +2 -0
  51. package/src/editor/component-editor/scaffolding/StateBlock.svelte +19 -8
  52. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +3 -0
  53. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +70 -3
  54. package/src/editor/component-editor/scaffolding/editorContext.ts +7 -0
  55. package/src/editor/core/a11y/a11yReport.ts +101 -0
  56. package/src/editor/core/a11y/a11yReportTypes.ts +69 -0
  57. package/src/editor/core/a11y/contrastFailures.ts +22 -0
  58. package/src/editor/core/components/contrastPairRegistry.ts +18 -0
  59. package/src/editor/core/palettes/contrast.ts +44 -0
  60. package/src/editor/core/palettes/contrastPairs.ts +79 -0
  61. package/src/editor/core/palettes/resolveColor.ts +77 -0
  62. package/src/editor/core/store/editorStore.ts +4 -0
  63. package/src/editor/core/store/editorViewStore.ts +2 -2
  64. package/src/editor/core/store/unsavedEdits.ts +10 -0
  65. package/src/editor/core/themes/liveStateStream.ts +7 -1
  66. package/src/editor/core/themes/parsers/gradient.ts +5 -2
  67. package/src/editor/docs/chapters.ts +1 -0
  68. package/src/editor/docs/content/accessibility.md +362 -0
  69. package/src/editor/docs/content/editing-tokens.md +28 -1
  70. package/src/editor/docs/content.generated.ts +2 -1
  71. package/src/editor/pages/ComponentEditorPage.svelte +10 -1
  72. package/src/editor/pages/EditorShell.svelte +96 -10
  73. package/src/editor/skill-atlas/skillSources.generated.ts +3 -3
  74. package/src/editor/skill-atlas/trees/check-compliance.ts +3 -3
  75. package/src/editor/skill-atlas/trees/create-component.ts +12 -12
  76. package/src/editor/ui/EditorViewSwitcher.svelte +15 -2
  77. package/src/editor/ui/GradientEditor.svelte +9 -1
  78. package/src/editor/ui/ThemePanel.svelte +4 -4
  79. package/src/editor/ui/UIContrastReadout.svelte +186 -0
  80. package/src/editor/ui/UIInfoPopover.svelte +16 -2
  81. package/src/editor/ui/UIPaletteSelector.svelte +9 -0
  82. package/src/editor/ui/UITokenSelector.svelte +26 -2
  83. package/src/editor/ui/a11y/A11yComponentIssues.svelte +103 -0
  84. package/src/editor/ui/a11y/A11yFindingRow.svelte +57 -0
  85. package/src/editor/ui/a11y/A11yIssueRow.svelte +121 -0
  86. package/src/editor/ui/a11y/A11yOverview.svelte +242 -0
  87. package/src/editor/ui/a11y/A11yPanel.svelte +128 -0
  88. package/src/editor/ui/a11y/A11yPropertyMark.svelte +84 -0
  89. package/src/editor/ui/a11y/A11yRailMark.svelte +34 -0
  90. package/src/editor/ui/a11y/AccessibilityTab.svelte +334 -0
  91. package/src/editor/ui/a11y/a11yView.ts +218 -0
  92. package/src/editor/ui/contrastReadout.ts +45 -0
  93. package/src/live-tokens/data/themes/autumn.json +20 -20
  94. package/src/live-tokens/data/themes/halloween.json +20 -20
  95. package/src/live-tokens/data/themes/midnight-study.json +20 -20
  96. package/src/live-tokens/data/themes/ocean.json +20 -20
  97. package/src/live-tokens/data/themes/royal-velvet.json +20 -20
  98. package/src/live-tokens/data/themes/sketchy.json +20 -20
  99. package/src/live-tokens/data/themes/spring-meadow.json +20 -20
  100. package/src/live-tokens/data/themes/sunset.json +20 -20
  101. package/src/system/components/Badge.svelte +3 -3
  102. package/src/system/components/Button.svelte +9 -3
  103. package/src/system/components/CodeSnippet.svelte +8 -1
  104. package/src/system/components/CornerBadge.svelte +3 -3
  105. package/src/system/components/Dialog.svelte +43 -14
  106. package/src/system/components/IconButton.svelte +1 -1
  107. package/src/system/components/Image.svelte +7 -0
  108. package/src/system/components/ImageLightbox.svelte +18 -25
  109. package/src/system/components/Input.svelte +8 -1
  110. package/src/system/components/MenuSelect.svelte +30 -2
  111. package/src/system/components/Notification.svelte +1 -1
  112. package/src/system/components/ProgressBar.svelte +6 -0
  113. package/src/system/components/RadioButton.svelte +36 -3
  114. package/src/system/components/SegmentedControl.svelte +36 -2
  115. package/src/system/components/SlidePager.svelte +2 -2
  116. package/src/system/components/Slider.svelte +13 -9
  117. package/src/system/components/TabBar.svelte +33 -3
  118. package/src/system/components/Toggle.svelte +2 -2
  119. package/src/system/components/VideoFrame.svelte +1 -1
  120. package/src/system/components/VideoLightbox.svelte +2 -2
  121. package/src/system/internal/focusTrap.ts +35 -0
  122. package/src/testing-js/__aria__/badge.yml +40 -0
  123. package/src/testing-js/__aria__/button.yml +88 -0
  124. package/src/testing-js/__aria__/callout.yml +12 -0
  125. package/src/testing-js/__aria__/card.yml +8 -0
  126. package/src/testing-js/__aria__/codesnippet.yml +21 -0
  127. package/src/testing-js/__aria__/collapsiblesection.yml +23 -0
  128. package/src/testing-js/__aria__/cornerbadge.yml +24 -0
  129. package/src/testing-js/__aria__/dialog.yml +42 -0
  130. package/src/testing-js/__aria__/iconbutton.yml +57 -0
  131. package/src/testing-js/__aria__/image.yml +10 -0
  132. package/src/testing-js/__aria__/imagelightbox.yml +50 -0
  133. package/src/testing-js/__aria__/inlineeditactions.yml +16 -0
  134. package/src/testing-js/__aria__/input.yml +61 -0
  135. package/src/testing-js/__aria__/menuselect.yml +30 -0
  136. package/src/testing-js/__aria__/notification.yml +30 -0
  137. package/src/testing-js/__aria__/panel.yml +2 -0
  138. package/src/testing-js/__aria__/progressbar.yml +2 -0
  139. package/src/testing-js/__aria__/radiobutton.yml +20 -0
  140. package/src/testing-js/__aria__/sectiondivider.yml +9 -0
  141. package/src/testing-js/__aria__/segmentedcontrol.yml +35 -0
  142. package/src/testing-js/__aria__/sidenavigation.yml +304 -0
  143. package/src/testing-js/__aria__/slidepager.yml +72 -0
  144. package/src/testing-js/__aria__/slider.yml +28 -0
  145. package/src/testing-js/__aria__/tabbar.yml +35 -0
  146. package/src/testing-js/__aria__/table.yml +144 -0
  147. package/src/testing-js/__aria__/toggle.yml +12 -0
  148. package/src/testing-js/__aria__/tooltip.yml +2 -0
  149. package/src/testing-js/__aria__/videoframe.yml +6 -0
  150. package/src/testing-js/__aria__/videolightbox.yml +12 -0
  151. package/src/testing-js/{chunk-WIZ6W7UT.js → chunk-3WCLMOM7.js} +2 -2
  152. package/src/testing-js/{chunk-SHBYZUPD.js → chunk-5HNZHIHG.js} +211 -14
  153. package/src/testing-js/chunk-5HNZHIHG.js.map +1 -0
  154. package/src/testing-js/{chunk-NB3NZRBM.js → chunk-7CM5D7PF.js} +5 -1
  155. package/src/testing-js/chunk-7CM5D7PF.js.map +1 -0
  156. package/src/testing-js/chunk-EWSGE27V.js +168 -0
  157. package/src/testing-js/chunk-EWSGE27V.js.map +1 -0
  158. package/src/testing-js/{chunk-GKO27NGN.js → chunk-R54I7YL6.js} +2 -2
  159. package/src/testing-js/{chunk-X6KHEVIG.js → chunk-RWH46IU5.js} +97 -29
  160. package/src/testing-js/chunk-RWH46IU5.js.map +1 -0
  161. package/src/testing-js/chunk-SHLPDNAQ.js +658 -0
  162. package/src/testing-js/chunk-SHLPDNAQ.js.map +1 -0
  163. package/src/testing-js/{chunk-3UKGXCDL.js → chunk-YVVR3GJZ.js} +1 -1
  164. package/src/testing-js/chunk-YVVR3GJZ.js.map +1 -0
  165. package/src/testing-js/component-a11y.contract.js +283 -0
  166. package/src/testing-js/component-a11y.contract.js.map +1 -0
  167. package/src/testing-js/component-alias.contract.js +2 -2
  168. package/src/testing-js/component-behavior.contract.js +2 -2
  169. package/src/testing-js/component-editor.contract.js +6 -5
  170. package/src/testing-js/component-editor.contract.js.map +1 -1
  171. package/src/testing-js/component-render.contract.js +10 -6
  172. package/src/testing-js/component-render.contract.js.map +1 -1
  173. package/src/testing-js/index.d.ts +44 -16
  174. package/src/testing-js/index.js +9 -9
  175. package/src/testing-js/page-compliance.contract.js +132 -13
  176. package/src/testing-js/page-compliance.contract.js.map +1 -1
  177. package/src/testing-js/vitest.js +3 -3
  178. package/template/package.json +9 -0
  179. package/src/testing-js/chunk-3UKGXCDL.js.map +0 -1
  180. package/src/testing-js/chunk-NB3NZRBM.js.map +0 -1
  181. package/src/testing-js/chunk-SHBYZUPD.js.map +0 -1
  182. package/src/testing-js/chunk-X6KHEVIG.js.map +0 -1
  183. /package/src/testing-js/{chunk-WIZ6W7UT.js.map → chunk-3WCLMOM7.js.map} +0 -0
  184. /package/src/testing-js/{chunk-GKO27NGN.js.map → chunk-R54I7YL6.js.map} +0 -0
@@ -1,14 +1,26 @@
1
1
  import {
2
- isInapplicable
3
- } from "./chunk-3UKGXCDL.js";
2
+ MOTION_MS,
3
+ MOTION_URL,
4
+ TEXT_SPACING_RULE,
5
+ TEXT_SPACING_URL,
6
+ newUnderTextSpacing
7
+ } from "./chunk-SHLPDNAQ.js";
8
+ import {
9
+ missingEngine,
10
+ recordA11y,
11
+ scanAxe
12
+ } from "./chunk-EWSGE27V.js";
4
13
  import {
5
14
  DEFAULT_PAGE_VIEWPORTS,
6
15
  PAGES_ENV,
7
16
  PAGE_VIEWPORTS_ENV
8
- } from "./chunk-NB3NZRBM.js";
17
+ } from "./chunk-7CM5D7PF.js";
18
+ import {
19
+ isInapplicable
20
+ } from "./chunk-YVVR3GJZ.js";
9
21
  import {
10
22
  allContracts
11
- } from "./chunk-SHBYZUPD.js";
23
+ } from "./chunk-5HNZHIHG.js";
12
24
 
13
25
  // src/testing/page-compliance.contract.ts
14
26
  import { test } from "@playwright/test";
@@ -258,6 +270,12 @@ var TEXT_STYLES = [
258
270
  // src/editor/core/palettes/contrast.ts
259
271
  var AA_BODY = 4.5;
260
272
  var AA_LARGE = 3;
273
+ var LARGE_TEXT_PX = 24;
274
+ var LARGE_BOLD_PX = 18.66;
275
+ var BOLD = 700;
276
+ function isLargeText(px, weight) {
277
+ return px >= LARGE_TEXT_PX || px >= LARGE_BOLD_PX && weight >= BOLD;
278
+ }
261
279
  function linearizeChannel(v8) {
262
280
  const s = v8 / 255;
263
281
  return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
@@ -379,9 +397,6 @@ var GRID_TOLERANCE = 1;
379
397
  var GRID_VIEWPORT = 768;
380
398
  var SETTLE_QUIET_MS = 300;
381
399
  var SETTLE_BUDGET_MS = 5e3;
382
- var LARGE_TEXT_PX = 24;
383
- var LARGE_BOLD_PX = 18.66;
384
- var BOLD = 700;
385
400
  var cssName = (camel) => camel.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
386
401
  function report(failures, scope, describe) {
387
402
  const lines = failures.map(describe);
@@ -393,8 +408,7 @@ function hex(rgb) {
393
408
  return `#${[r, g, b].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
394
409
  }
395
410
  function aaFloor(pair) {
396
- const large = pair.fontSize >= LARGE_TEXT_PX || pair.fontSize >= LARGE_BOLD_PX && pair.fontWeight >= BOLD;
397
- return large ? AA_LARGE : AA_BODY;
411
+ return isLargeText(pair.fontSize, pair.fontWeight) ? AA_LARGE : AA_BODY;
398
412
  }
399
413
  function reasons(skipped) {
400
414
  return Object.entries(skipped).map(([reason, count]) => `${reason} (${count})`).join(", ");
@@ -411,7 +425,11 @@ var PageHarness = class _PageHarness {
411
425
  static async open(page, target, viewport) {
412
426
  await installPageProbe(page);
413
427
  await page.setViewportSize(viewport);
414
- await page.goto(target.route);
428
+ await _PageHarness.load(page, target.route);
429
+ return new _PageHarness(page, target, viewport);
430
+ }
431
+ static async load(page, route) {
432
+ await page.goto(route);
415
433
  await page.locator(PAGE_CONTAINER).waitFor();
416
434
  await page.waitForFunction((selectors) => {
417
435
  const container = document.querySelector(selectors.container);
@@ -420,7 +438,6 @@ var PageHarness = class _PageHarness {
420
438
  }, { container: PAGE_CONTAINER, chrome: CHROME });
421
439
  await page.waitForLoadState("networkidle");
422
440
  await _PageHarness.settle(page);
423
- return new _PageHarness(page, target, viewport);
424
441
  }
425
442
  /**
426
443
  * Every rule here measures geometry, and the geometry moves for as long as
@@ -868,13 +885,14 @@ var PageHarness = class _PageHarness {
868
885
  });
869
886
  }
870
887
  }
871
- const clips = (style) => style.overflowX !== "visible" || style.overflowY !== "visible";
872
888
  for (const spec of list) {
873
889
  for (const instance of root.querySelectorAll(spec.root)) {
874
890
  if (instance.closest(chrome)) continue;
875
891
  let clipper = null;
876
892
  for (let node = instance.parentElement; node; node = node.parentElement) {
877
- if (clips(getComputedStyle(node))) {
893
+ const overflowX = getComputedStyle(node).overflowX;
894
+ if (overflowX === "auto" || overflowX === "scroll") break;
895
+ if (overflowX !== "visible") {
878
896
  clipper = node;
879
897
  break;
880
898
  }
@@ -983,6 +1001,91 @@ var PageHarness = class _PageHarness {
983
1001
  }
984
1002
  return null;
985
1003
  }
1004
+ /**
1005
+ * The accessibility rules return their results. The suite passes them to
1006
+ * `recordA11y`, and the run reports each one at `warn` (decision 3 of
1007
+ * docs/plans/a11y-testing.md).
1008
+ *
1009
+ * axe over the page's own markup. The router's chrome and every shipped
1010
+ * component root stay out, since the component suite answers for what a
1011
+ * component renders, and `color-contrast` stays off, since `page-contrast`
1012
+ * owns page contrast (decision 8).
1013
+ */
1014
+ async scanA11y(componentRoots2) {
1015
+ const results = await scanAxe(this.page, PAGE_CONTAINER, [CHROME, ...componentRoots2], "a11y-page");
1016
+ const lines = await this.page.evaluate(({ targets: targets2, source }) => targets2.map((target) => {
1017
+ try {
1018
+ const element = document.querySelector(target);
1019
+ return element ? window.__liveTokensPageLine(element, source) : 1;
1020
+ } catch {
1021
+ return 1;
1022
+ }
1023
+ }), { targets: results.map((result) => result.target), source: this.target.source });
1024
+ return results.map((result, index) => ({ ...result, line: lines[index] }));
1025
+ }
1026
+ /** The overflow observation again under the SC 1.4.12 override, minus every
1027
+ * failure the page already has without it, which `page-overflow` reports. */
1028
+ async scanTextSpacing(specs) {
1029
+ const found = await newUnderTextSpacing(
1030
+ this.page,
1031
+ async () => (await this.observeOverflow(specs)).failures,
1032
+ (failure) => `${failure.kind}|${failure.line}|${failure.tag}`
1033
+ );
1034
+ return found.map((failure) => ({
1035
+ rule: "a11y-text-spacing",
1036
+ engineRule: TEXT_SPACING_RULE,
1037
+ impact: null,
1038
+ target: failure.kind === "instance" ? failure.tag : `<${failure.tag}>`,
1039
+ html: "",
1040
+ help: `Under the text spacing override, ${failure.detail}`,
1041
+ helpUrl: TEXT_SPACING_URL,
1042
+ line: failure.line
1043
+ }));
1044
+ }
1045
+ /**
1046
+ * Loads the page again under `prefers-reduced-motion: reduce`, so a script
1047
+ * that reads the preference at mount sees it too, and reports every
1048
+ * animation still running whose run lasts past `MOTION_MS`. The page stays
1049
+ * under the emulation afterwards.
1050
+ */
1051
+ async scanReducedMotion() {
1052
+ await this.page.emulateMedia({ reducedMotion: "reduce" });
1053
+ await _PageHarness.load(this.page, this.target.route);
1054
+ return this.page.evaluate(({ container, chrome, source, limit, url }) => {
1055
+ const root = document.querySelector(container);
1056
+ if (!root) return [];
1057
+ const results = [];
1058
+ const seen = /* @__PURE__ */ new Set();
1059
+ for (const animation of document.getAnimations()) {
1060
+ if (animation.playState !== "running") continue;
1061
+ const effect = animation.effect;
1062
+ if (!(effect instanceof KeyframeEffect) || !effect.target) continue;
1063
+ const element = effect.target;
1064
+ if (!root.contains(element) || element.closest(chrome)) continue;
1065
+ const end = Number(effect.getComputedTiming().endTime ?? 0);
1066
+ if (end <= limit) continue;
1067
+ const name = animation instanceof CSSAnimation ? `The animation ${animation.animationName.replace(/^svelte-[a-z0-9]+-/, "")}` : animation instanceof CSSTransition ? `A transition of ${animation.transitionProperty}` : `A script animation${animation.id ? ` ${animation.id}` : ""}`;
1068
+ const classes = [...element.classList].filter((c) => !/^svelte-[a-z0-9]+$/.test(c));
1069
+ const target = `${element.tagName.toLowerCase()}${classes.map((c) => `.${c}`).join("")}` + (effect.pseudoElement ?? "");
1070
+ if (seen.has(`${target}
1071
+ ${name}`)) continue;
1072
+ seen.add(`${target}
1073
+ ${name}`);
1074
+ const html = element.outerHTML;
1075
+ results.push({
1076
+ rule: "a11y-reduced-motion",
1077
+ engineRule: "prefers-reduced-motion",
1078
+ impact: null,
1079
+ target,
1080
+ html: html.slice(0, html.indexOf(">") + 1),
1081
+ help: `${name} keeps running under prefers-reduced-motion: reduce, ` + (Number.isFinite(end) ? `for ${Math.round(end)} ms` : "without end"),
1082
+ helpUrl: url,
1083
+ line: window.__liveTokensPageLine(element, source)
1084
+ });
1085
+ }
1086
+ return results;
1087
+ }, { container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source, limit: MOTION_MS, url: MOTION_URL });
1088
+ }
986
1089
  };
987
1090
  async function installPageProbe(page) {
988
1091
  await page.addInitScript(() => {
@@ -1041,6 +1144,22 @@ for (const target of targets) {
1041
1144
  const inapplicable = await harness.assertOverflow(specs);
1042
1145
  test.skip(inapplicable !== null, inapplicable ?? "");
1043
1146
  });
1147
+ test(`page-a11y | ${target.source} | ${at}`, async ({ page }) => {
1148
+ const missing = await missingEngine(["axe"]);
1149
+ test.skip(missing !== null, missing ?? "");
1150
+ const roots = await componentRoots();
1151
+ const harness = await PageHarness.open(page, target, viewport);
1152
+ recordA11y(await harness.scanA11y(roots));
1153
+ });
1154
+ test(`page-text-spacing | ${target.source} | ${at}`, async ({ page }) => {
1155
+ const specs = await paintSpecs();
1156
+ const harness = await PageHarness.open(page, target, viewport);
1157
+ recordA11y(await harness.scanTextSpacing(specs));
1158
+ });
1159
+ test(`page-reduced-motion | ${target.source} | ${at}`, async ({ page }) => {
1160
+ const harness = await PageHarness.open(page, target, viewport);
1161
+ recordA11y(await harness.scanReducedMotion());
1162
+ });
1044
1163
  }
1045
1164
  }
1046
1165
  //# sourceMappingURL=page-compliance.contract.js.map