@astryxdesign/core 0.7.6-canary.cebf4a9 → 0.7.6-canary.d29fe0f

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../src/Link/Link.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,UAAU,EACV,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAsG/C,MAAM,WAAW,SAAU,SAAQ,SAAS,CAC1C,iBAAiB,GAAG,iBAAiB,CACtC;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;IACvD;;;;;OAKG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B;;OAEG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,2BAA2B,CAAC;IACnD;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;IACzE;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,EACnB,EAAE,EACF,KAAK,EACL,IAAI,EACJ,YAAoB,EACpB,UAAkB,EAClB,cAAsB,EACtB,WAAW,EAAE,oBAAoB,EACjC,MAAM,EAAE,eAAe,EACvB,OAAO,EACP,OAAO,EACP,YAAoB,EACpB,IAAa,EACb,IAAI,EACJ,MAAM,EACN,KAAgB,EAChB,OAAkB,EAClB,QAAY,EACZ,QAAQ,EACR,GAAG,EAAE,YAAY,EACjB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,+BAoJX;yBA7Ke,IAAI"}
1
+ {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../src/Link/Link.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,UAAU,EACV,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,SAAS,CAAC;AA8G/C,MAAM,WAAW,SAAU,SAAQ,SAAS,CAC1C,iBAAiB,GAAG,iBAAiB,CACtC;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;IACvD;;;;;OAKG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B;;OAEG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,2BAA2B,CAAC;IACnD;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;IACzE;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,EACnB,EAAE,EACF,KAAK,EACL,IAAI,EACJ,YAAoB,EACpB,UAAkB,EAClB,cAAsB,EACtB,WAAW,EAAE,oBAAoB,EACjC,MAAM,EAAE,eAAe,EACvB,OAAO,EACP,OAAO,EACP,YAAoB,EACpB,IAAa,EACb,IAAI,EACJ,MAAM,EACN,KAAgB,EAChB,OAAkB,EAClB,QAAY,EACZ,QAAQ,EACR,GAAG,EAAE,YAAY,EACjB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,+BAuJX;yBAhLe,IAAI"}
package/dist/Link/Link.js CHANGED
@@ -53,6 +53,11 @@ const styles = {
53
53
  kAMwcw: "xlr8y92",
54
54
  $$css: true
55
55
  },
56
+ truncating: {
57
+ ks0D6T: "x193iq5w",
58
+ k7Eaqz: "xeuugli",
59
+ $$css: true
60
+ },
56
61
  buttonReset: {
57
62
  kWkggS: "xjbqb8w",
58
63
  ksu8eU: "xng3xce",
@@ -206,7 +211,7 @@ export function Link({
206
211
  }), focusOutlineProps.focusVisible(styles.base, styles.buttonReset, linkColorStyles[color],
207
212
  // The system's pressed overlay behind the text; the hover stays the
208
213
  // colour change above, so a press is the one background it paints.
209
- !isDisabled && interactionOverlayStyles.pressedBackgroundColor, hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, isDisabled && styles.disabled, xstyle), className, style),
214
+ !isDisabled && interactionOverlayStyles.pressedBackgroundColor, hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, isDisabled && styles.disabled, maxLines > 0 && styles.truncating, xstyle), className, style),
210
215
  ...props,
211
216
  ...(isDisabled ? disabledInteractionProps(props.onKeyDown) : null),
212
217
  children: sharedContent
@@ -226,7 +231,7 @@ export function Link({
226
231
  tabIndex: 0,
227
232
  ...mergeProps(themeProps('link', {
228
233
  color
229
- }), focusOutlineProps.focusVisible(styles.base, linkColorStyles[color], hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, styles.disabled, xstyle), className, style),
234
+ }), focusOutlineProps.focusVisible(styles.base, linkColorStyles[color], hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, styles.disabled, maxLines > 0 && styles.truncating, xstyle), className, style),
230
235
  ...props,
231
236
  ...disabledInteractionProps(props.onKeyDown),
232
237
  children: sharedContent
@@ -244,7 +249,7 @@ export function Link({
244
249
  tabIndex: isDisabled ? -1 : undefined,
245
250
  ...mergeProps(themeProps('link', {
246
251
  color
247
- }), focusOutlineProps.focusVisible(styles.base, linkColorStyles[color], !isDisabled && interactionOverlayStyles.pressedBackgroundColor, hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, isDisabled && styles.disabled, xstyle), className, style),
252
+ }), focusOutlineProps.focusVisible(styles.base, linkColorStyles[color], !isDisabled && interactionOverlayStyles.pressedBackgroundColor, hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, isDisabled && styles.disabled, maxLines > 0 && styles.truncating, xstyle), className, style),
248
253
  ...props,
249
254
  children: sharedContent
250
255
  });
@@ -16,7 +16,7 @@ import * as fs from 'node:fs';
16
16
  import * as path from 'node:path';
17
17
  import { expect, test } from '@playwright/test';
18
18
  import { DEFAULT_STORYBOOK_DIR, serveStorybook } from '@astryxdesign/a11y-spec/storybook';
19
- const STORY = 'core-markdown-plugins-heading-links--overview';
19
+ const STORY = 'core-markdown--heading-links';
20
20
  const OUTPUT = path.resolve('test-results/markdown-heading-links');
21
21
  const GEOMETRY_TOLERANCE_PX = 1;
22
22
  let storybook;
@@ -1 +1 @@
1
- {"version":3,"file":"RadioListItem.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,OAAO,EAAO,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AA0I7C,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;;;;;;;OAUG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,KAAK,EACL,WAAW,EACX,UAAU,EAAE,cAAsB,EAClC,YAAY,EACZ,UAAU,EACV,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EACP,GAAG,IAAI,EACR,EAAE,kBAAkB,qBAqKpB;yBApLe,aAAa"}
1
+ {"version":3,"file":"RadioListItem.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,OAAO,EAAO,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AA0I7C,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;;;;;;;OAUG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,KAAK,EACL,WAAW,EACX,UAAU,EAAE,cAAsB,EAClC,YAAY,EACZ,UAAU,EACV,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EACP,GAAG,IAAI,EACR,EAAE,kBAAkB,qBA2KpB;yBA1Le,aAAa"}
@@ -198,7 +198,12 @@ export function RadioListItem({
198
198
  // from submission, matching a natively disabled control.
199
199
  ,
200
200
  form: keepsFocusableForMessage ? '' : undefined,
201
- required: context.isRequired,
201
+ required: context.isRequired
202
+ // Chromium reports an unanswered native-required radio invalid before
203
+ // any interaction; the invalid state follows the group's status
204
+ // instead (RadioList FR6).
205
+ ,
206
+ "aria-invalid": context.isRequired ? context.status?.type === 'error' : undefined,
202
207
  onChange: () => {
203
208
  if (isDisabled) {
204
209
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/Switch/Switch.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/Switch/Switch.tsx"],"names":[],"mappings":"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"}
@@ -401,8 +401,11 @@ export function Switch({
401
401
  // than the field wrapper via `...rest`.
402
402
  ,
403
403
  "aria-labelledby": ariaLabelledByProp,
404
- "aria-describedby": ariaDescribedBy,
405
- "aria-invalid": status?.type === 'error' ? true : undefined,
404
+ "aria-describedby": ariaDescribedBy
405
+ // Chromium reports an unchecked native-required checkbox invalid before
406
+ // any interaction; the invalid state follows status instead.
407
+ ,
408
+ "aria-invalid": status?.type === 'error' ? true : isRequired ? false : undefined,
406
409
  "aria-busy": isBusy || undefined,
407
410
  ...stylex.props(styles.input, rtlStyles.centerInline('-50%'), styles.inputCoarse, inputSizeStyles[size], isDisabled && styles.inputDisabled, isBusy && styles.inputBusy, switchFocusInput)
408
411
  }), /*#__PURE__*/_jsx("div", {
@@ -138,7 +138,6 @@ export declare class GestureArena {
138
138
  setTimer(recognizer: GestureRecognizer, deadline: number, callback: () => void): void;
139
139
  /** @internal */
140
140
  clearTimer(recognizer: GestureRecognizer): void;
141
- /** Cancel an active recognizer, or fail a possible one. */
142
141
  /**
143
142
  * Runs `body`, code outside input that stops recognizers (an Effect that
144
143
  * turns one off or detaches it), without resolving what those stops
@@ -151,6 +150,7 @@ export declare class GestureArena {
151
150
  deferResolution(body: () => void): void;
152
151
  /** The last event's time, or now before any event. */
153
152
  private lastEventTime;
153
+ /** Cancel an active recognizer, or fail a possible one. */
154
154
  stop(recognizer: GestureRecognizer): void;
155
155
  private attemptRecognition;
156
156
  /** Whether `winner` being recognized prevents `other`. */
@@ -1 +1 @@
1
- {"version":3,"file":"GestureArena.d.ts","sourceRoot":"","sources":["../../src/gestures/GestureArena.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GestureArena.d.ts","sourceRoot":"","sources":["../../src/gestures/GestureArena.ts"],"names":[],"mappings":"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"}
@@ -405,7 +405,6 @@ export class GestureArena {
405
405
  }
406
406
  }
407
407
 
408
- /** Cancel an active recognizer, or fail a possible one. */
409
408
  /**
410
409
  * Runs `body`, code outside input that stops recognizers (an Effect that
411
410
  * turns one off or detaches it), without resolving what those stops
@@ -435,6 +434,8 @@ export class GestureArena {
435
434
  lastEventTime() {
436
435
  return Number.isFinite(this.latestTime) ? this.latestTime : this.clock.now();
437
436
  }
437
+
438
+ /** Cancel an active recognizer, or fail a possible one. */
438
439
  stop(recognizer) {
439
440
  // A cancel from code between events happens at the last event's time:
440
441
  // wall time would run deadlines ahead of input still queued (FR16).
@@ -59,7 +59,6 @@ export declare class GestureHost {
59
59
  private readonly touchIds;
60
60
  /** Touch.identifier → the element the finger landed on. */
61
61
  private readonly touchTargets;
62
- /** Finger targets with listeners of their own, and how many fingers each. */
63
62
  /**
64
63
  * Finger targets with listeners of their own: how many fingers each, and
65
64
  * how many of those a recognizer could claim while they move (only those
@@ -102,19 +101,19 @@ export declare class GestureHost {
102
101
  private readonly claimedLifts;
103
102
  /** Fingers still waiting for their pointerdown, by arena id. */
104
103
  private readonly unpairedTouches;
105
- /** The last position fed per contact, so one channel's echo is dropped. */
106
104
  /** The elements each held contact turned selection off on. */
107
105
  private readonly heldSelectionBy;
108
106
  private readonly isPrimaryPointerCoarse;
109
107
  private readonly coarseQuery;
110
108
  private isWatchingPointer;
111
109
  private readonly onPointerKindChange;
110
+ /** The last position fed per contact, so one channel's echo is dropped. */
112
111
  private readonly lastFed;
113
112
  /** When a finger was last down or lifted, and where it landed. */
114
113
  private lastTouch;
115
- /** The last scroll a finger drove, and when. */
116
114
  /** Scrollers a recognizer is scrolling itself this frame (ownScroll). */
117
115
  private readonly ownedScrolls;
116
+ /** The last scroll a finger drove, and when. */
118
117
  private lastScroll;
119
118
  private nextId;
120
119
  private isInstalled;
@@ -1 +1 @@
1
- {"version":3,"file":"GestureHost.d.ts","sourceRoot":"","sources":["../../src/gestures/GestureHost.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GestureHost.d.ts","sourceRoot":"","sources":["../../src/gestures/GestureHost.ts"],"names":[],"mappings":"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"}
@@ -120,10 +120,6 @@ function claimsWhileMoving(recognizer) {
120
120
  return recognizer.acceptsTouchInput && recognizer.kind !== 'tap';
121
121
  }
122
122
 
123
- /**
124
- * Run `task` in the next frame, before it paints: a read there styles what
125
- * the frame must style anyway, and its writes are what the frame shows.
126
- */
127
123
  /**
128
124
  * A CSS-wide keyword, which names no touch-action of its own: the value in
129
125
  * force resolves it (`initial` and `unset` to `auto`, `inherit` to the
@@ -133,6 +129,11 @@ function isCssWideKeyword(value) {
133
129
  return CSS_WIDE_KEYWORDS.has(value.trim().toLowerCase());
134
130
  }
135
131
  const CSS_WIDE_KEYWORDS = new Set(['initial', 'inherit', 'unset', 'revert', 'revert-layer']);
132
+
133
+ /**
134
+ * Run `task` in the next frame, before it paints: a read there styles what
135
+ * the frame must style anyway, and its writes are what the frame shows.
136
+ */
136
137
  function inNextFrame(view, task) {
137
138
  if (view != null && typeof view.requestAnimationFrame === 'function') {
138
139
  view.requestAnimationFrame(task);
@@ -193,7 +194,6 @@ export class GestureHost {
193
194
  touchIds = new Map();
194
195
  /** Touch.identifier → the element the finger landed on. */
195
196
  touchTargets = new Map();
196
- /** Finger targets with listeners of their own, and how many fingers each. */
197
197
  /**
198
198
  * Finger targets with listeners of their own: how many fingers each, and
199
199
  * how many of those a recognizer could claim while they move (only those
@@ -236,17 +236,17 @@ export class GestureHost {
236
236
  claimedLifts = [];
237
237
  /** Fingers still waiting for their pointerdown, by arena id. */
238
238
  unpairedTouches = new Map();
239
- /** The last position fed per contact, so one channel's echo is dropped. */
240
239
  /** The elements each held contact turned selection off on. */
241
240
  heldSelectionBy = new Map();
242
241
  isWatchingPointer = false;
243
242
  onPointerKindChange = () => this.refreshAll();
243
+ /** The last position fed per contact, so one channel's echo is dropped. */
244
244
  lastFed = new Map();
245
245
  /** When a finger was last down or lifted, and where it landed. */
246
246
  lastTouch = null;
247
- /** The last scroll a finger drove, and when. */
248
247
  /** Scrollers a recognizer is scrolling itself this frame (ownScroll). */
249
248
  ownedScrolls = new Set();
249
+ /** The last scroll a finger drove, and when. */
250
250
  lastScroll = null;
251
251
  nextId = 1;
252
252
  isInstalled = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.7.6-canary.cebf4a9",
3
+ "version": "0.7.6-canary.d29fe0f",
4
4
  "displayName": "Astryx Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -847,9 +847,9 @@
847
847
  "react-dom": ">=19.0.0"
848
848
  },
849
849
  "devDependencies": {
850
- "@astryxdesign/a11y-spec": "0.7.6-canary.cebf4a9",
851
- "@astryxdesign/cli": "0.7.6-canary.cebf4a9",
852
- "@astryxdesign/interaction-harness": "0.7.6-canary.cebf4a9",
850
+ "@astryxdesign/a11y-spec": "0.7.6-canary.d29fe0f",
851
+ "@astryxdesign/cli": "0.7.6-canary.d29fe0f",
852
+ "@astryxdesign/interaction-harness": "0.7.6-canary.d29fe0f",
853
853
  "@babel/cli": "^7.29.7",
854
854
  "@babel/core": "^7.29.7",
855
855
  "@babel/preset-react": "^7.29.7",
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  schema_version: 3
3
- template_version: 5
3
+ template_version: 7
4
4
  kind: component
5
5
  id: component:ChatDictationButton
6
- authority: draft
6
+ authority: current
7
7
  archive_reason: null
8
8
  superseded_by: null
9
- approved_by: null
10
- approved_at: null
9
+ approved_by: cixzhang
10
+ approved_at: 2026-10-31
11
11
  owners: [cixzhang]
12
12
  review_triggers: [public-api, behavior, accessibility, theming, testing]
13
13
  verified_by:
@@ -18,7 +18,7 @@ verified_by:
18
18
  ]
19
19
  modules: []
20
20
  families: []
21
- design_specs: []
21
+ design_specs: [design:reduced-motion]
22
22
  architecture:
23
23
  [
24
24
  architecture:public-component-api,
@@ -28,133 +28,178 @@ architecture:
28
28
  architecture:knowledge-contracts,
29
29
  ]
30
30
  contributing: []
31
- system_specs: [spec:AST-029]
31
+ system_specs: [spec:AST-029, spec:AST-027]
32
32
  ---
33
33
 
34
34
  # ChatDictationButton component contract
35
35
 
36
36
  ## Contract at a glance
37
37
 
38
- | Area | Contract |
39
- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
40
- | Public contract | `dictation` supplies support, listening, volume, bands, and toggle state; `size`, `label`, root span props, styles, and ref remain additive inputs. |
41
- | Behavior | The idle button shows the microphone action. Listening replaces the icon with five volume-reactive bars. Unsupported dictation is hidden by default or disabled when explicitly retained. |
42
- | End-user impact | Voice input remains operable and labelled; unsupported browsers do not expose an action that cannot run. |
43
- | Builder impact | Builders can place the control in ChatComposer send actions and safely customize its root layout without owning speech state. |
44
- | Compatibility/readiness | Patch-compatible repair: existing supported behavior is unchanged; the opt-in unsupported-visible state becomes accurately disabled. |
45
- | Review checks | Reject an enabled unsupported action, a missing listening label, raw theme-inaccessible clipping color, or lost root passthrough. |
46
- | Governing rules | `architecture:component-style-authoring/INV1–INV3`; `architecture:theme-tokens/INV3`; `architecture:public-component-api/INV1, INV5–INV6, INV8`; `architecture:component-test-sufficiency/INV1–INV8, INV10–INV11`. |
38
+ | Area | Contract |
39
+ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
+ | Public contract | `ChatDictationButton` with a required `dictation` state (`isSupported`, `isListening`, `volume`, `bands`, `toggle`), `size` (`sm`, `md`; default `md`), `isHiddenWhenUnsupported` (default true), `label`, `ref`, `xstyle`, `className`, `style`, and span props. |
41
+ | Behavior | An icon-only microphone Button that toggles dictation. While listening it shows five volume-reactive bars instead of the microphone; unsupported dictation renders nothing, or a disabled Button when kept visible. |
42
+ | End-user impact | Voice input is one labelled button that says whether it starts or stops dictation; browsers without speech recognition see no action that cannot run. |
43
+ | Builder impact | None. |
44
+ | Compatibility/readiness | Records shipped behavior; no public change. Two implementation gaps, listed under Current-state impact. |
45
+ | Review checks | Reject an enabled unsupported action, a missing or stale start/stop name, bars exposed to assistive technology, or clipping color that a theme cannot retint. |
46
+ | Governing rules | `architecture:public-component-api`; `architecture:theme-tokens` INV3; `architecture:component-style-authoring` INV7; `design:reduced-motion`. |
47
47
 
48
48
  This table is a review projection; the body below is authoritative.
49
49
 
50
50
  ## Intent
51
51
 
52
- ChatDictationButton renders the visible control for an existing speech-recognition
53
- state owner. It translates that owner's support and listening states into one
54
- icon-only Button and a direction-neutral equalizer visualization.
52
+ ChatDictationButton is the visible control for a speech-recognition state
53
+ owner. It turns that owner's support and listening state into one icon-only
54
+ Button and a five-bar volume display. Consumer usage lives in
55
+ `ChatDictationButton.doc.mjs`.
55
56
 
56
57
  ## Compatibility and migration
57
58
 
58
- - Released default preserved: yes
59
- - Compatibility class: behavioral bug fix for the explicit unsupported-visible state
60
- - Supported idle and listening states: unchanged
59
+ - Released default preserved: `yes`
60
+ - Compatibility class: records shipped behavior; no public change
61
+ - Controlled/uncontrolled behavior: listening state is owned by the supplied
62
+ `dictation` value
61
63
  - Migration decision: none
62
64
 
65
+ Consumer migration instructions belong in consumer docs and release notes.
66
+
67
+ ## Current-state impact
68
+
69
+ - **The volume bars are extra elements.** The listening display is a container
70
+ and five bar `span` elements that no theme target paints.
71
+ `architecture:component-style-authoring` INV7 renders one element per
72
+ semantic role or themable part.
73
+
74
+ - **The bars set a z-index without isolation.** The bar container carries
75
+ `z-index: 1` and the wrapper does not isolate it, so the bars take part in
76
+ the page's stacking order. `spec:AST-027` FR1 keeps z-index local and lists
77
+ this case as a containment gap.
78
+
63
79
  ## Ownership boundary
64
80
 
65
81
  **Owns**
66
82
 
67
- - The start/stop accessible label and optional caller label override.
68
- - Hidden-versus-disabled presentation when speech recognition is unsupported.
69
- - The five-bar visual projection of supplied band and volume values.
70
- - Theme-aware accent-to-error clipping feedback.
71
- - Root span ref and accepted neutral span props.
83
+ - The start and stop name, and the caller's `label` override (FR1, FR2).
84
+ - Hiding or disabling the control when speech recognition is unsupported
85
+ (FR3).
86
+ - The five-bar display of the supplied bands and its clipping color (FR2, FR4).
87
+ - The wrapper span's ref, props, and styling (FR5).
72
88
 
73
89
  **Does not own / non-goals**
74
90
 
75
- - Speech recognition support detection, lifecycle, transcripts, or errors.
76
- - Microphone permission UX or audio capture.
77
- - ChatComposer placement beyond documented composition guidance.
78
- - A public color, threshold, or equalizer-shape axis.
91
+ - Speech recognition support detection, lifecycle, transcripts, errors, and
92
+ microphone permission — owned by the `dictation` state owner.
93
+ - Activation, focus, disabled semantics, and icon-only presentation — owned by
94
+ `component:Button`.
95
+ - Placement in ChatComposer — the caller's composition.
96
+ - A public color, threshold, or bar-shape option.
79
97
 
80
98
  ## Public concepts
81
99
 
82
- | Concept | Closed values or states | Meaning | Default | Owner | Stability |
83
- | ------------ | -------------------------------------------------- | ------------------------------------------------------------- | --------------------------- | ---------------------------------------- | --------- |
84
- | support | supported; unsupported-hidden; unsupported-visible | Determines whether the control can render and operate. | unsupported-hidden | speech owner projected by this component | stable |
85
- | listening | idle; listening | Selects the start/stop label and microphone/equalizer visual. | idle | `dictation` | stable |
86
- | size | `sm`; `md` | Sizes the Button and equalizer geometry together. | `md` | component | stable |
87
- | label | translated default; caller override | Names the action for assistive technology. | state-dependent translation | component/caller | stable |
88
- | root surface | ref; DOM/data/ARIA props; className/style/xstyle | Extends the positioning wrapper. | omitted | public component API | stable |
100
+ | Concept | Closed values or states | Meaning | Availability by variant/orientation/state | Default | Owner | Stability | Invalid-value behavior |
101
+ | --------- | -------------------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------- | ----------------------- | ------------------------------- | --------- | -------------------------------- |
102
+ | Support | supported; unsupported and hidden; unsupported and shown | Whether the control renders and whether it can operate. | Every control. | hidden when unsupported | `component:ChatDictationButton` | Stable | TypeScript rejects other values. |
103
+ | Listening | idle; listening | Selects the start or stop name and the microphone or bars. | Supported controls. | idle | `dictation` owner | Stable | Not applicable. |
104
+ | Size | `sm`, `md` | Sizes the Button and bars together. | Every control. | `md` | `component:ChatDictationButton` | Stable | TypeScript rejects other values. |
89
105
 
90
106
  ## Behavioral and layout contract
91
107
 
92
- | ID | Candidate invariant | Basis | Draft review state |
93
- | --- | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ------------------ |
94
- | FR1 | Supported idle state MUST expose an enabled Button named by the start label and invoke `dictation.toggle` on activation. | shipped API and Button contract | verify |
95
- | FR2 | Supported listening state MUST expose the stop label and five aria-hidden visualizer bars derived from `bands`. | shipped implementation and docs | verify |
96
- | FR3 | Unsupported state MUST render nothing by default. If explicitly retained, its Button MUST be disabled. | public option plus operability/accessibility repair | settled |
97
- | FR4 | Clipping feedback MUST derive from portable semantic color tokens so a consumer theme can retint both endpoints. | `architecture:theme-tokens/INV3` and lint enforcement | settled |
98
- | FR5 | Accepted ref, DOM/data/ARIA, className, style, and xstyle inputs MUST reach and compose on the root span. | `architecture:public-component-api` | settled |
108
+ | ID | Invariant | Basis |
109
+ | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
110
+ | FR1 | When supported and idle, the control is an enabled, icon-only ghost Button with the microphone icon, named by `label` or the translated start label, that calls `dictation.toggle` when activated. | Current source and tests |
111
+ | FR2 | While listening, the Button is named by `label` or the translated stop label and shows no icon, and five bars, hidden from assistive technology, scale with the supplied `bands`. | Current source and tests |
112
+ | FR3 | When dictation is unsupported, the control renders nothing; with `isHiddenWhenUnsupported={false}` it renders a disabled Button. | Current source and tests |
113
+ | FR4 | The bars use `--color-accent`, blending toward `--color-error` as `volume` passes the clipping threshold, so a theme retints both ends (`architecture:theme-tokens` INV3). | Current source and tests |
114
+ | FR5 | `ref`, DOM, data, and ARIA props, `className`, `style`, and `xstyle` reach the wrapper span, which carries the `chat-dictation-button` target; `size` sizes the Button and the bars together. | Current source and tests |
115
+ | FR6 | Under reduced motion the bars change scale and color at once, with no transition. | `design:reduced-motion`; current source |
99
116
 
100
117
  ### Allowed variation
101
118
 
102
- - Callers may replace the translated start/stop label with `label`.
103
- - Band amplitudes and clipping strength vary with the supplied dictation owner.
104
- - Consumer themes may change the accent and error colors used by the bars.
119
+ - **AV1 — Label.** Callers may replace the translated start and stop name.
120
+ - **AV2 — Bars.** Bar heights and clipping strength follow the supplied
121
+ `bands` and `volume`.
122
+ - **AV3 — Theme colors.** Themes may change the accent and error colors.
123
+
124
+ ### Representative states
125
+
126
+ | State | Required invariant | Allowed variation |
127
+ | ------------------------- | ---------------------------------------------- | ----------------- |
128
+ | Supported, idle | Enabled microphone Button with the start name. | Label, size. |
129
+ | Listening | Stop name; five hidden bars. | Bar heights. |
130
+ | Clipping | Bars blend from accent toward error. | Theme colors. |
131
+ | Unsupported, default | Nothing renders. | — |
132
+ | Unsupported, kept visible | A disabled Button. | Label. |
133
+
134
+ ### Transformation and precedence order
135
+
136
+ - **ORD1 — Name.** The caller's `label`, then the translated start or stop
137
+ label for the listening state.
138
+ - **ORD2 — Support.** Unsupported and hidden renders nothing before any other
139
+ state applies.
140
+
141
+ ### Performance and resources
142
+
143
+ - No resource rule.
105
144
 
106
145
  ## Accessibility contract
107
146
 
108
- - The nested Button owns keyboard and pointer activation, focus, and disabled semantics.
109
- - The equalizer is decorative and MUST remain hidden from the accessibility tree.
110
- - The visible control MUST have a state-appropriate accessible label.
111
- - An unsupported visible control MUST communicate disabled state and MUST NOT activate.
112
- - Reduced-motion preference removes the equalizer's transition duration.
147
+ - **AR1 — Name.** The control always has a name that says whether it starts or
148
+ stops dictation, unless the caller overrides it (FR1, FR2).
149
+ - **AR2 — Decorative bars.** The bars are hidden from assistive technology
150
+ (FR2).
151
+ - **AR3 — Unavailable action.** A visible unsupported control is disabled
152
+ (FR3); Button owns how disabled is conveyed.
113
153
 
114
154
  ## Design relationships
115
155
 
116
- - Idle uses the shared microphone Icon through Button.
117
- - Listening bars begin at `--color-accent` and blend toward `--color-error` as clipping increases.
118
- - The component adds no portable token or public theme target.
119
- - Equalizer dimensions remain private component geometry.
120
-
121
- ## Responsive and bidirectional behavior
156
+ | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
157
+ | ---------------- | -------------------------------------------------- | ------------------------ | -------------- | ------------------ |
158
+ | Button | Icon-only microphone action. | `component:Button` | Prominent | FR1, FR3 |
159
+ | Volume bars | Five bars that show live input level and clipping. | Current source | Supporting | FR2, FR4, FR6 |
122
160
 
123
- The control has fixed `sm` and `md` sizes and no viewport-owned behavior. Its
124
- microphone glyph, centered bars, and block-axis scale are direction-neutral; the
125
- verified-N/A ledger records this with source evidence.
161
+ No anatomy-theming map is recorded yet; the block is optional during
162
+ migration, so the map is deferred.
126
163
 
127
164
  ## Family and system relationships
128
165
 
129
- - ChatComposer owns placement through its `sendActions` slot.
130
- - Button owns activation, focus, disabled semantics, hit target, and icon-only presentation.
131
- - Icon owns the microphone glyph.
132
- - `useChatDictation` and `useSpeechRecognition` own speech lifecycle and state.
133
- - Theme token architecture owns the accent and error semantic roles.
166
+ - `component:Button` owns activation, focus, disabled semantics, and icon-only
167
+ presentation.
168
+ - `architecture:theme-tokens` owns the accent and error roles the bars use.
169
+ - `design:reduced-motion` owns the reduced-motion rule FR6 follows.
170
+ - The glyph and centered bars are direction-neutral; the RTL audit records
171
+ this as not applicable.
134
172
 
135
173
  ## Verification map
136
174
 
137
- | Contract | Evidence |
138
- | ----------------------- | --------------------------------------------------------------------- |
139
- | FR1, labels, activation | `ChatDictationButton.test.tsx` idle activation and custom-label cases |
140
- | FR2 | listening structure test and Listening/Speaking stories |
141
- | FR3 | unsupported hidden and visible-disabled tests/stories |
142
- | FR4 | clipping semantic-color test, lint, and Clipping story |
143
- | FR5 | typed ref and root-passthrough test |
144
- | rendered states | exact-head Storybook, a11y, and visual CI |
145
- | RTL N/A | `apps/storybook/rtl-audit/verified-not-applicable.json` |
175
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
176
+ | -------- | ----------------------------------------------------------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------- | ----------------------------------------- |
177
+ | FR1, AR1 | `ChatDictationButton.test.tsx` "labels and toggles the idle button" | Idle | A missing name, or activation that does not toggle, fails. | `audit:ChatDictationButton/behavior` |
178
+ | FR2, AR2 | `ChatDictationButton.test.tsx` "shows five hidden visualizer bars and the stop label while listening" | Listening | A wrong bar count, exposed bars, or a start name while listening fails. | `audit:ChatDictationButton/behavior` |
179
+ | FR3, AR3 | `ChatDictationButton.test.tsx` unsupported tests | Unsupported, hidden and shown | A rendered or enabled unsupported control fails. | `audit:ChatDictationButton/accessibility` |
180
+ | FR4 | `ChatDictationButton.test.tsx` "uses theme-owned colors for clipping feedback" | Clipping | A raw color in place of the theme roles fails. | `audit:ChatDictationButton/theming` |
181
+ | FR5 | `ChatDictationButton.test.tsx` "forwards the root ref and accepted span props" | Ref and span props | A dropped ref or prop fails. | `audit:ChatDictationButton/api` |
182
+ | RTL N/A | `apps/storybook/rtl-audit/verified-not-applicable.json` | — | — | `audit:ChatDictationButton/rtl` |
183
+
184
+ Read from source, with no focused test yet:
185
+
186
+ - FR1: the ghost variant and the microphone icon.
187
+ - FR2: no icon while listening, the bars scaling with `bands`, and the
188
+ caller's `label` while listening.
189
+ - FR4: the plain accent below the clipping threshold.
190
+ - FR5: ARIA props reaching the wrapper, `className`, `style`, and `xstyle` composing on the wrapper, the
191
+ `chat-dictation-button` target, and `sm` sizing.
192
+ - FR6: the reduced-motion transition removal.
146
193
 
147
194
  ## Decision log
148
195
 
149
- | Decision | Reason | Authority |
150
- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------ |
151
- | Keep unsupported dictation hidden by default and disabled when explicitly visible. | An unavailable action must not present as operable. | objective accessibility/operability repair |
152
- | Blend portable accent and error tokens for clipping. | Preserves the existing progressive clipping cue while keeping both endpoints theme-owned. | `architecture:theme-tokens/INV3` |
196
+ No component-local decision is recorded.
153
197
 
154
198
  ## Open questions
155
199
 
156
- None for this repair.
200
+ None.
157
201
 
158
202
  ## Content boundary
159
203
 
160
- Labels may be translated defaults or caller overrides. The component does not own transcript text, permission errors, microphone instructions, or product-specific voice-input guidance.
204
+ This file does not duplicate consumer prop tables, speech-recognition
205
+ behavior, or Button's rules. It links to their owners.
@@ -16,6 +16,7 @@ verified_by:
16
16
  packages/core/src/Link/__tests__/Link.a11y.test.tsx,
17
17
  packages/core/src/Link/__tests__/Link.a11y.chromium.spec.ts,
18
18
  packages/core/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts,
19
+ packages/core/src/Link/__tests__/Link.truncation.a11y.chromium.spec.ts,
19
20
  ]
20
21
  modules: []
21
22
  families: [family:navigation-destinations]
@@ -107,7 +108,7 @@ Consumer migration instructions belong in consumer docs and release notes.
107
108
  | FR3 | An external Link that is not rendered as a button shows a trailing extra-small external-link icon that inherits the root's color, followed by visually hidden new-tab text: `newTabLabel`, else the localized default. | Current source and tests |
108
109
  | FR4 | A destination reaches the link component only through the shared navigation rule; a rejected destination renders an inert anchor and never invokes a router. | `family:navigation-destinations` FR1–FR6; `spec:AST-005` |
109
110
  | FR5 | A disabled Link stays focusable with `aria-disabled="true"`, never navigates, and never runs `onClick`. The disabled anchor form omits `href`, `target`, and `rel`, takes a Tab stop, and skips the custom link component. In every form, clicks are cancelled and stopped, Enter and Space are suppressed, other keys reach the caller's `onKeyDown`, and the Link paints at half opacity with no pointer events and no press paint. A focused Link that becomes disabled MUST keep focus and expose the change on that element (`spec:AST-085` FR4, FR5), and a caller `aria-disabled`, `role`, or `tabIndex` MUST NOT replace the disabled exposure (`architecture:public-component-api` INV5). Implementation gap: caller props spread after Link's own, so a caller `aria-disabled`, `role`, or `tabIndex` overrides them. Implementation gap: an enabled link renders through the safe link component and a disabled one as a plain anchor (or a `<button>` when it has `onClick`), so a focused link that becomes disabled (or re-enabled) is replaced and focus falls to the page. | `spec:AST-085` FR1, FR2, FR4, FR5; `family:navigation-destinations` FR7; current tests |
110
- | FR6 | Children render inside Text with `type` (default `body`), `size`, `weight`, `color` (default `accent`), `display` (default `inline`), and `maxLines` (default `0`). The root inherits font family, size, weight, and line height and lays content out with a small gap; `isStandalone` sets the body size and leading on the root. A Link inside a Text with `maxLines` MUST truncate with that text. Implementation gap: the root is `inline-flex`, so an ancestor Text clamp does not truncate it. | Current source and tests |
111
+ | FR6 | Children render inside Text with `type` (default `body`), `size`, `weight`, `color` (default `accent`), `display` (default `inline`), and `maxLines` (default `0`). The root inherits font family, size, weight, and line height and lays content out with a small gap; with `maxLines` above 0 it stops at its container, so its Text truncates inside a constrained line; `isStandalone` sets the body size and leading on the root. A Link inside a Text with `maxLines` MUST truncate with that text. Implementation gap: the root is `inline-flex`, so an ancestor Text clamp does not truncate it. | Current source and tests |
111
112
  | FR7 | The root paints the chosen color for the six built-in colors, which the underline and the external icon take; the label's color comes from Text (FR6). On hover-capable pointers an enabled Link underlines on hover, and for `primary`, `secondary`, and `accent` the root color mixes in the hover tint. `hasUnderline` underlines at rest. | Current source and tests |
112
113
  | FR8 | Press feedback follows `design:user-states` DR1 and DR2 for Link's text surface: an enabled link or button form paints the pressed overlay, and a disabled Link does not. | `design:user-states` DR1, DR2; current tests |
113
114
  | FR9 | `label`, when non-empty, becomes `aria-label` and replaces the content as the accessible name; a caller `aria-label` overrides it; otherwise the content is the name. | Current tests |
@@ -191,7 +192,7 @@ carries no anatomy-theming map.
191
192
  | FR2, FR3, AR3 | `Link.test.tsx` external, target, rel, and new-tab cases; `Link.a11y.chromium.spec.ts` external state | External; explicit `_blank`; custom label | A missing safety token, icon, or new-tab text fails. Evidence gap: no test checks the accessible name of an external link with `label`. Evidence gap: no test sets `referrerPolicy` or asserts the external icon's size or color. | `audit:Link/accessibility` |
192
193
  | FR4 | `Link.navigation.a11y.chromium.spec.ts` | Rejected and ordinary schemes; native, router, downloads | A rejected destination that navigates or reaches a router fails. | `audit:Link/behavior` |
193
194
  | FR5, AR2 | `Link.test.tsx` disabled cases | Disabled anchor; disabled button form; with `onClick` | Navigation, a consumer `onClick`, a lost Tab stop, or a custom component on a disabled link fails. Evidence gap: no test disables a focused link or passes a caller `aria-disabled`, `role`, or `tabIndex`. Evidence gap: no test asserts that other keys reach the caller's `onKeyDown`, or the half-opacity, no-pointer-events paint. | `audit:Link/accessibility` |
194
- | FR6 (type) | `Link.test.tsx` text-type cases | Default `body`; `type="inherit"` | A dropped Text `type` fails. Evidence gap: no test asserts that `size`, `weight`, `color`, `display`, or `maxLines` reach Text, or the `isStandalone` root size. | `audit:Link/visual` |
195
+ | FR6 (type) | `Link.test.tsx` text-type cases | Default `body`; `type="inherit"` | A dropped Text `type` fails. `Link.truncation.a11y.chromium.spec.ts`: an anchor and a button Link with `maxLines={1}` in a fixed-width line stop at the line and draw an ellipsis. Evidence gap: no test asserts that `size`, `weight`, `color`, or `display` reach Text, or the `isStandalone` root size. | `audit:Link/visual` |
195
196
  | FR6, FR7 (paint) | Evidence gap: the color, underline, and standalone cases assert only that a link renders; hover paint is untested | Each color; `hasUnderline`; `isStandalone` | — | `audit:Link/visual` |
196
197
  | FR8 | `Link.test.tsx` pressed-state suite | Link, button form, disabled | No press paint, or press paint on a disabled Link, fails. | `audit:Link/behavior` |
197
198
  | FR9, FR11, AR4 | `Link.test.tsx` label, ref, and theme-class cases | With and without `label`; `data-color` | A missing or extra `aria-label`, target, `data-color`, or ref fails. The accessibility suites assert a passed `data-*` attribute and `aria-current` on the root, and the navigation suite asserts `download`. Evidence gap: no test passes both `label` and `aria-label`, or passes `className`, `style`, or `xstyle`. | `audit:Link/theming` |
package/src/Link/Link.tsx CHANGED
@@ -76,6 +76,14 @@ const styles = stylex.create({
76
76
  transitionDuration: durationVars['--duration-fast'],
77
77
  transitionTimingFunction: easeVars['--ease-standard'],
78
78
  },
79
+ // A truncating label needs a box that stops at its container: an
80
+ // inline-flex root otherwise grows to its whole text, so its Text never
81
+ // overflows and draws no ellipsis (`component:Link` FR6, `component:Text`
82
+ // FR4).
83
+ truncating: {
84
+ maxWidth: '100%',
85
+ minWidth: 0,
86
+ },
79
87
  /**
80
88
  * Reset styles for rendering as a <button> when href is undefined.
81
89
  * Strips all native button chrome so it looks identical to a link.
@@ -370,6 +378,7 @@ export function Link({
370
378
  hasUnderline && styles.hasUnderline,
371
379
  isStandalone && styles.standalone,
372
380
  isDisabled && styles.disabled,
381
+ maxLines > 0 && styles.truncating,
373
382
  xstyle,
374
383
  ),
375
384
  className,
@@ -403,6 +412,7 @@ export function Link({
403
412
  hasUnderline && styles.hasUnderline,
404
413
  isStandalone && styles.standalone,
405
414
  styles.disabled,
415
+ maxLines > 0 && styles.truncating,
406
416
  xstyle,
407
417
  ),
408
418
  className,
@@ -434,6 +444,7 @@ export function Link({
434
444
  hasUnderline && styles.hasUnderline,
435
445
  isStandalone && styles.standalone,
436
446
  isDisabled && styles.disabled,
447
+ maxLines > 0 && styles.truncating,
437
448
  xstyle,
438
449
  ),
439
450
  className,
@@ -0,0 +1,58 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // @pr-a11y scope ^(packages/core/src/Link/|packages/core/src/Text/|apps/storybook/stories/Link\.stories)
3
+
4
+ /**
5
+ * Real-browser evidence for `component:Link` FR6 with `component:Text` FR4: a
6
+ * Link with `maxLines={1}` in a fixed-width line, as an anchor and as a
7
+ * button, stops at the line and its label overflows with an ellipsis.
8
+ */
9
+
10
+ import {expect, test} from '@playwright/test';
11
+ import {
12
+ DEFAULT_STORYBOOK_DIR,
13
+ serveStorybook,
14
+ type StaticServer,
15
+ } from '@astryxdesign/a11y-spec/storybook';
16
+
17
+ let storybook: StaticServer;
18
+
19
+ test.beforeAll(async () => {
20
+ storybook = await serveStorybook(
21
+ process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
22
+ );
23
+ });
24
+
25
+ test.afterAll(async () => storybook?.close());
26
+
27
+ for (const form of ['anchor', 'button'] as const) {
28
+ test(`a ${form} Link with maxLines={1} truncates inside a fixed-width line`, async ({
29
+ page,
30
+ }) => {
31
+ await page.goto(
32
+ `${storybook.origin}/iframe.html?id=core-link--truncated-in-constrained-line&viewMode=story`,
33
+ );
34
+ const line = page.locator(`[data-truncation-line="${form}"]`);
35
+ await expect(line).toBeVisible();
36
+ const measured = await line.evaluate(el => {
37
+ const root = el.firstElementChild as HTMLElement;
38
+ const label = root.firstElementChild as HTMLElement;
39
+ const style = getComputedStyle(label);
40
+ return {
41
+ tag: root.tagName,
42
+ line: el.getBoundingClientRect().width,
43
+ root: root.getBoundingClientRect().width,
44
+ labelClient: label.clientWidth,
45
+ labelScroll: label.scrollWidth,
46
+ textOverflow: style.textOverflow,
47
+ };
48
+ });
49
+ expect(measured.tag, 'the Link renders its own element').toBe(
50
+ form === 'anchor' ? 'A' : 'BUTTON',
51
+ );
52
+ // The root stops at the line instead of growing to its whole text.
53
+ expect(measured.root).toBeLessThanOrEqual(measured.line + 0.5);
54
+ // The label itself overflows and draws the ellipsis.
55
+ expect(measured.labelScroll).toBeGreaterThan(measured.labelClient);
56
+ expect(measured.textOverflow).toBe('ellipsis');
57
+ });
58
+ }
@@ -21,7 +21,7 @@ import {
21
21
  type StaticServer,
22
22
  } from '@astryxdesign/a11y-spec/storybook';
23
23
 
24
- const STORY = 'core-markdown-plugins-heading-links--overview';
24
+ const STORY = 'core-markdown--heading-links';
25
25
  const OUTPUT = path.resolve('test-results/markdown-heading-links');
26
26
  const GEOMETRY_TOLERANCE_PX = 1;
27
27
  let storybook: StaticServer;
@@ -120,7 +120,7 @@ Consumer migration instructions belong in consumer docs and release notes.
120
120
  | FR3 | Selecting an enabled option calls `onChange(value)` once; RadioList holds no selection of its own. | Current tests |
121
121
  | FR4 | With an empty `value`, keyboard focus entering the group lands on the first radio that is not natively disabled (in a group disabled with a reason, that is its first `aria-disabled` radio, keeping the enabled focus order under `spec:AST-085` FR1), or stays on the last one when entering backward. Focus moving between radios inside the group is not redirected. With a selection, the selected radio is the Tab stop. Arrow keys follow the browser's native radio behavior, which stops on `aria-disabled` radios. | WAI-ARIA radio group pattern; current tests |
122
122
  | FR5 | `isDisabled` MUST disable every item: each radio stays focusable with `aria-disabled="true"`, is detached from the form so it does not submit, and refuses selection (`spec:AST-085` FR1–FR3, FR7). With `disabledMessage`, a reason tooltip also opens on group hover and keyboard focus, and the reason MUST describe each focusable radio (`spec:AST-085` FR5, FR7). Implementation gap: the reason describes only the radiogroup, so a focused radio is not described by it; and without a `disabledMessage`, each radio gets native `disabled` instead, which removes it from the tab order, and a radio focused when the group becomes disabled loses focus (`spec:AST-085` FR4). | `spec:AST-085` FR1–FR5, FR7; current tests |
123
- | FR6 | `status.type === 'error'` sets `aria-invalid` on the radiogroup. The radiogroup exposes the effective required state (including a form-level default) with `aria-required`, while each radio's native `required` follows only the explicit `isRequired`. | Current source and tests |
123
+ | FR6 | `status.type === 'error'` sets `aria-invalid` on the radiogroup. The radiogroup exposes the effective required state (including a form-level default) with `aria-required`, while each radio's native `required` follows only the explicit `isRequired`; a natively required radio's `aria-invalid` follows the same status, so the browser's own invalid state never shows before an error. | Current source and tests |
124
124
  | FR7 | The radiogroup lays options in a column with a small gap, or a row with a wider gap when horizontal, and passes `size` to every item. | Current source and tests |
125
125
  | FR8 | Base props (`ref`, `id`, `aria-*`, `data-*`, `hidden`, `inert`, `dir`, DOM handlers) reach the radiogroup; a caller `onFocus` runs after FR4's entry handling. `container*` reaches the Field box where one renders (in a `horizontal-labels` FormLayout none renders, and `container*` has no effect and warns), and `control*` the radiogroup; root `xstyle`, `className`, and `style` are not accepted. | `family:input-fields` FR10; current tests |
126
126
  | FR9 | The radiogroup carries `astryx-radio-list` and reflects `data-orientation` and `data-size`. | `architecture:component-theming-surface`; current tests |
@@ -165,6 +165,34 @@ describe('RadioList', () => {
165
165
  expect(screen.getByText(/Required/)).toBeInTheDocument();
166
166
  });
167
167
 
168
+ it('keeps required radios valid until the group shows an error', () => {
169
+ const {rerender} = render(
170
+ <RadioList label="Preference" value="" onChange={() => {}} isRequired>
171
+ <RadioListItem label="Option A" value="a" />
172
+ <RadioListItem label="Option B" value="b" />
173
+ </RadioList>,
174
+ );
175
+ // Native required alone makes Chromium report every radio invalid.
176
+ for (const radio of screen.getAllByRole('radio')) {
177
+ expect(radio).toBeRequired();
178
+ expect(radio).toHaveAttribute('aria-invalid', 'false');
179
+ }
180
+ rerender(
181
+ <RadioList
182
+ label="Preference"
183
+ value=""
184
+ onChange={() => {}}
185
+ isRequired
186
+ status={{type: 'error', message: 'Pick one'}}>
187
+ <RadioListItem label="Option A" value="a" />
188
+ <RadioListItem label="Option B" value="b" />
189
+ </RadioList>,
190
+ );
191
+ for (const radio of screen.getAllByRole('radio')) {
192
+ expect(radio).toHaveAttribute('aria-invalid', 'true');
193
+ }
194
+ });
195
+
168
196
  it('shows Optional indicator when isOptional is true', () => {
169
197
  render(
170
198
  <RadioList label="Preference" value="" onChange={() => {}} isOptional>
@@ -326,6 +326,12 @@ export function RadioListItem({
326
326
  // from submission, matching a natively disabled control.
327
327
  form={keepsFocusableForMessage ? '' : undefined}
328
328
  required={context.isRequired}
329
+ // Chromium reports an unanswered native-required radio invalid before
330
+ // any interaction; the invalid state follows the group's status
331
+ // instead (RadioList FR6).
332
+ aria-invalid={
333
+ context.isRequired ? context.status?.type === 'error' : undefined
334
+ }
329
335
  onChange={() => {
330
336
  if (isDisabled) {
331
337
  return;
@@ -123,7 +123,7 @@ Consumer migration instructions belong in consumer docs and release notes.
123
123
  | FR5 | A change calls `onChange(checked, event)`; unless that call prevents default, `changeAction(checked, event)` runs in a transition and the switch shows the proposed state while the Action is pending, and `value` once it settles. | Current tests |
124
124
  | FR6 | While `isLoading`, or while the shown state differs from `value`, the input sets `aria-busy`, ignores pointer input, refuses changes, keeps focus, and the switch announces its busy start once per busy period through the shared channel. | `spec:AST-086` FR8; current tests |
125
125
  | FR7 | Disabled: `aria-disabled="true"` on a focusable input, no `name`, detached from its form (so it neither submits nor blocks submission when required), no change, no caller `onClick` on the field, no hover or press paint, and a half-opacity track. With `disabledMessage`, a reason tooltip opens on row hover and keyboard focus and describes the input. Implementation gap: caller DOM handlers other than `onClick`, such as `onKeyDown`, still run on the field root while disabled (`spec:AST-085` FR2). | `spec:AST-085` FR1–FR3, FR5; current tests |
126
- | FR8 | Enabled, the input submits `on` under `htmlName` when on and nothing when off; `isRequired` sets native `required`, while `aria-required` follows the effective required state. | Current tests |
126
+ | FR8 | Enabled, the input submits `on` under `htmlName` when on and nothing when off; `isRequired` sets native `required`, while `aria-required` follows the effective required state; `aria-invalid` follows `status` (`false` on a required switch without an error), so the browser's own invalid state never shows before an error. | Current tests |
127
127
  | FR9 | Keyboard focus paints the shared focus outline on the track. Hovering the enabled row tints the track; pressing paints the pressed overlay on both, applying `design:user-states` DR1 and DR2; a touch press fades out from the row. Track color transitions are instant under reduced motion. | `architecture:interaction-modality` INV1; `design:user-states` DR1, DR2 for the pressed overlay; `design:reduced-motion`; current tests |
128
128
  | FR10 | The thumb travels toward the inline end when on, mirrored under RTL, and moves without a transition under reduced motion (`design:reduced-motion` DR1). On coarse pointers the input's hit area is at least 24 by 24 CSS pixels (WCAG 2.5.8) and follows the inline direction. Under `spec:AST-094` FR42 a coarse-pointer target MUST reach 44 CSS pixels through an invisible hit area where neighbors allow. Implementation gap: the input's hit area stops at 24 by 24. | WCAG 2.5.8; current tests; `design:reduced-motion` DR1; `spec:AST-094` FR42 |
129
129
  | FR11 | Under forced colors, on and off stay distinguishable (Highlight track when on), and the hover tint does not hide the thumb. | WCAG 1.4.11; current tests |
@@ -429,7 +429,9 @@ describe('Switch', () => {
429
429
  continue;
430
430
  }
431
431
  for (const node of record.addedNodes) {
432
- if (node.textContent) {written.push(node.textContent);}
432
+ if (node.textContent) {
433
+ written.push(node.textContent);
434
+ }
433
435
  }
434
436
  }
435
437
  });
@@ -563,6 +565,24 @@ describe('Switch', () => {
563
565
  expect(screen.getByRole('switch')).toBeRequired();
564
566
  });
565
567
 
568
+ it('keeps a required switch valid until status shows an error', () => {
569
+ const {rerender} = render(
570
+ <Switch label="Accept" value={false} onChange={() => {}} isRequired />,
571
+ );
572
+ // Native required alone makes Chromium report the switch invalid.
573
+ expect(screen.getByRole('switch')).toHaveAttribute('aria-invalid', 'false');
574
+ rerender(
575
+ <Switch
576
+ label="Accept"
577
+ value={false}
578
+ onChange={() => {}}
579
+ isRequired
580
+ status={{type: 'error', message: 'Required'}}
581
+ />,
582
+ );
583
+ expect(screen.getByRole('switch')).toHaveAttribute('aria-invalid', 'true');
584
+ });
585
+
566
586
  describe('disabledMessage', () => {
567
587
  const h = {hidden: true} as const;
568
588
 
@@ -679,7 +679,11 @@ export function Switch({
679
679
  // than the field wrapper via `...rest`.
680
680
  aria-labelledby={ariaLabelledByProp}
681
681
  aria-describedby={ariaDescribedBy}
682
- aria-invalid={status?.type === 'error' ? true : undefined}
682
+ // Chromium reports an unchecked native-required checkbox invalid before
683
+ // any interaction; the invalid state follows status instead.
684
+ aria-invalid={
685
+ status?.type === 'error' ? true : isRequired ? false : undefined
686
+ }
683
687
  aria-busy={isBusy || undefined}
684
688
  {...stylex.props(
685
689
  styles.input,
@@ -471,7 +471,6 @@ export class GestureArena {
471
471
  }
472
472
  }
473
473
 
474
- /** Cancel an active recognizer, or fail a possible one. */
475
474
  /**
476
475
  * Runs `body`, code outside input that stops recognizers (an Effect that
477
476
  * turns one off or detaches it), without resolving what those stops
@@ -504,6 +503,7 @@ export class GestureArena {
504
503
  : this.clock.now();
505
504
  }
506
505
 
506
+ /** Cancel an active recognizer, or fail a possible one. */
507
507
  stop(recognizer: GestureRecognizer): void {
508
508
  // A cancel from code between events happens at the last event's time:
509
509
  // wall time would run deadlines ahead of input still queued (FR16).
@@ -217,10 +217,6 @@ function claimsWhileMoving(recognizer: GestureRecognizer): boolean {
217
217
  return recognizer.acceptsTouchInput && recognizer.kind !== 'tap';
218
218
  }
219
219
 
220
- /**
221
- * Run `task` in the next frame, before it paints: a read there styles what
222
- * the frame must style anyway, and its writes are what the frame shows.
223
- */
224
220
  /**
225
221
  * A CSS-wide keyword, which names no touch-action of its own: the value in
226
222
  * force resolves it (`initial` and `unset` to `auto`, `inherit` to the
@@ -238,6 +234,10 @@ const CSS_WIDE_KEYWORDS: ReadonlySet<string> = new Set([
238
234
  'revert-layer',
239
235
  ]);
240
236
 
237
+ /**
238
+ * Run `task` in the next frame, before it paints: a read there styles what
239
+ * the frame must style anyway, and its writes are what the frame shows.
240
+ */
241
241
  function inNextFrame(view: Window | null, task: () => void): void {
242
242
  if (view != null && typeof view.requestAnimationFrame === 'function') {
243
243
  view.requestAnimationFrame(task);
@@ -328,7 +328,6 @@ export class GestureHost {
328
328
  private readonly touchIds = new Map<number, number>();
329
329
  /** Touch.identifier → the element the finger landed on. */
330
330
  private readonly touchTargets = new Map<number, EventTarget>();
331
- /** Finger targets with listeners of their own, and how many fingers each. */
332
331
  /**
333
332
  * Finger targets with listeners of their own: how many fingers each, and
334
333
  * how many of those a recognizer could claim while they move (only those
@@ -374,20 +373,20 @@ export class GestureHost {
374
373
  private readonly claimedLifts: PlacedContact[] = [];
375
374
  /** Fingers still waiting for their pointerdown, by arena id. */
376
375
  private readonly unpairedTouches = new Map<number, PlacedContact>();
377
- /** The last position fed per contact, so one channel's echo is dropped. */
378
376
  /** The elements each held contact turned selection off on. */
379
377
  private readonly heldSelectionBy = new Map<number, HTMLElement[]>();
380
378
  private readonly isPrimaryPointerCoarse: () => boolean;
381
379
  private readonly coarseQuery: MediaQueryList | null;
382
380
  private isWatchingPointer = false;
383
381
  private readonly onPointerKindChange = (): void => this.refreshAll();
382
+ /** The last position fed per contact, so one channel's echo is dropped. */
384
383
  private readonly lastFed = new Map<number, TouchSample>();
385
384
  /** When a finger was last down or lifted, and where it landed. */
386
385
  private lastTouch: {readonly target: Node; readonly time: number} | null =
387
386
  null;
388
- /** The last scroll a finger drove, and when. */
389
387
  /** Scrollers a recognizer is scrolling itself this frame (ownScroll). */
390
388
  private readonly ownedScrolls = new Set<Node>();
389
+ /** The last scroll a finger drove, and when. */
391
390
  private lastScroll: {readonly scroller: Node; readonly time: number} | null =
392
391
  null;
393
392
  private nextId = 1;