@astryxdesign/core 0.7.3-canary.8f392ec → 0.7.3-canary.968130f

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 (43) hide show
  1. package/dist/ClickableCard/ClickableCard.d.ts +2 -2
  2. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  3. package/dist/ClickableCard/ClickableCard.js +11 -9
  4. package/dist/DateInput/DateInput.d.ts +4 -4
  5. package/dist/DateInput/DateInput.d.ts.map +1 -1
  6. package/dist/DateInput/DateInput.js +27 -20
  7. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  8. package/dist/DateInput/NativeDateField.js +14 -8
  9. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  10. package/dist/DateInput/TouchDateField.js +14 -10
  11. package/dist/Link/Link.d.ts +2 -3
  12. package/dist/Link/Link.d.ts.map +1 -1
  13. package/dist/Link/Link.js +11 -19
  14. package/dist/Popover/Popover.d.ts.map +1 -1
  15. package/dist/Popover/Popover.js +8 -4
  16. package/dist/Token/Token.d.ts.map +1 -1
  17. package/dist/Token/Token.js +8 -3
  18. package/dist/astryx.css +2 -0
  19. package/dist/utils/disabledInteraction.d.ts +21 -0
  20. package/dist/utils/disabledInteraction.d.ts.map +1 -0
  21. package/dist/utils/disabledInteraction.js +33 -0
  22. package/package.json +3 -3
  23. package/src/Banner/Banner.spec.md +37 -32
  24. package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
  25. package/src/ClickableCard/ClickableCard.test.tsx +5 -4
  26. package/src/ClickableCard/ClickableCard.tsx +9 -9
  27. package/src/DateInput/DateInput.doc.mjs +9 -8
  28. package/src/DateInput/DateInput.test.tsx +88 -13
  29. package/src/DateInput/DateInput.tsx +49 -21
  30. package/src/DateInput/DateInputTouch.test.tsx +22 -1
  31. package/src/DateInput/NativeDateField.test.tsx +29 -3
  32. package/src/DateInput/NativeDateField.tsx +20 -7
  33. package/src/DateInput/TouchDateField.tsx +24 -9
  34. package/src/FieldStatus/FieldStatus.spec.md +3 -2
  35. package/src/Link/Link.test.tsx +21 -7
  36. package/src/Link/Link.tsx +16 -24
  37. package/src/Link/__tests__/Link.a11y.states.ts +1 -1
  38. package/src/Popover/Popover.test.tsx +15 -0
  39. package/src/Popover/Popover.tsx +19 -8
  40. package/src/PowerSearch/PowerSearchToken.test.tsx +7 -5
  41. package/src/Token/Token.test.tsx +26 -4
  42. package/src/Token/Token.tsx +6 -2
  43. package/src/utils/disabledInteraction.ts +40 -0
@@ -55,8 +55,8 @@ export interface ClickableCardProps extends BaseProps {
55
55
  target?: string;
56
56
  /**
57
57
  * Set to true to disable the card.
58
- * Disabled action cards use a native disabled button. Disabled link cards
59
- * render no live destination, leave the tab order, and expose aria-disabled.
58
+ * Disabled cards keep their tab stop and expose aria-disabled; activation is
59
+ * blocked, and disabled link cards render no live destination.
60
60
  */
61
61
  isDisabled?: boolean;
62
62
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ClickableCard.d.ts","sourceRoot":"","sources":["../../src/ClickableCard/ClickableCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAE,KAAK,UAAU,EAAU,KAAK,GAAG,EAAC,MAAM,OAAO,CAAC;AASxE,OAAO,KAAK,EAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAGtE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuI5C,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAE1B;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAEnD;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,yBAAyB;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,IAAI,EACJ,MAAM,EACN,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,OAAmB,EACnB,SAAkB,EAClB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,aAAa,EACxB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,kBAAkB,+BAsFpB;yBAzGe,aAAa"}
1
+ {"version":3,"file":"ClickableCard.d.ts","sourceRoot":"","sources":["../../src/ClickableCard/ClickableCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAE,KAAK,UAAU,EAAU,KAAK,GAAG,EAAC,MAAM,OAAO,CAAC;AASxE,OAAO,KAAK,EAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAGtE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAwI5C,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAE1B;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAEnD;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,yBAAyB;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,IAAI,EACJ,MAAM,EACN,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,OAAmB,EACnB,SAAkB,EAClB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,aAAa,EACxB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,kBAAkB,+BAyFpB;yBA5Ge,aAAa"}
@@ -41,6 +41,7 @@ import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
41
41
  import { interactionOverlayStyles } from "../utils/interactionOverlay.stylex.js";
42
42
  import { usePressFeedback } from "../hooks/usePressFeedback.js";
43
43
  import { useMergedRefs } from "../hooks/useMergedRefs.js";
44
+ import { disabledInteractionProps } from "../utils/disabledInteraction.js";
44
45
  // =============================================================================
45
46
  // Styles — only the interactive layer, Card handles everything else
46
47
  // =============================================================================
@@ -106,10 +107,6 @@ const styles = {
106
107
  // Component
107
108
  // =============================================================================
108
109
 
109
- function preventDisabledLinkClick(event) {
110
- event.preventDefault();
111
- }
112
-
113
110
  /**
114
111
  * An interactive card that acts as a single navigation or action target.
115
112
  *
@@ -210,11 +207,13 @@ export function ClickableCard({
210
207
  ref: interactiveRef,
211
208
  href: isDisabled ? undefined : href,
212
209
  target: isDisabled ? undefined : target,
213
- onClick: isDisabled ? preventDisabledLinkClick : undefined,
214
210
  role: isDisabled ? 'link' : undefined,
211
+ ...(isDisabled ? disabledInteractionProps() : null),
215
212
  "aria-label": label,
216
- "aria-disabled": isDisabled || undefined,
217
- tabIndex: isDisabled ? -1 : 0,
213
+ "aria-disabled": isDisabled || undefined
214
+ // A disabled card keeps its Tab stop (spec:AST-085 FR1).
215
+ ,
216
+ tabIndex: 0,
218
217
  ...{
219
218
  className: "x10l6tqk x1i1rx1s xjm9jq1 x1717udv xkdpibf xb3r6kr xzpqnlu xuxw1ft xc342km"
220
219
  }
@@ -222,8 +221,11 @@ export function ClickableCard({
222
221
  ref: interactiveRef,
223
222
  type: "button",
224
223
  "aria-label": label,
225
- disabled: isDisabled,
226
- onClick: onClickProp,
224
+ "aria-disabled": isDisabled || undefined,
225
+ onClick: onClickProp
226
+ // Focusable while disabled (FR1), but inert (FR2).
227
+ ,
228
+ ...(isDisabled ? disabledInteractionProps() : null),
227
229
  ...{
228
230
  className: "x10l6tqk x1i1rx1s xjm9jq1 x1717udv xkdpibf xb3r6kr xzpqnlu xuxw1ft xc342km"
229
231
  }
@@ -82,13 +82,13 @@ export interface DateInputProps extends Omit<FieldInputBaseProps<HTMLInputElemen
82
82
  isDisabled?: boolean;
83
83
  /**
84
84
  * Explains why the input is disabled. When set together with
85
- * `isDisabled`, the input shows a tooltip with this text on hover and
86
- * keyboard focus, and the field stays focusable (via `aria-disabled`)
85
+ * `isDisabled`, the field shows a tooltip with this text on hover and
86
+ * keyboard focus, and the field's focusable controls are described by it,
87
87
  * so the reason is discoverable by keyboard and assistive technology.
88
88
  * Typing and calendar activation stay blocked.
89
89
  *
90
- * Use this instead of wrapping a disabled input in `Tooltip` — disabled
91
- * controls don't emit the pointer events an external tooltip needs.
90
+ * Use this instead of wrapping a disabled input in `Tooltip`, so the
91
+ * reason is tied to the field.
92
92
  *
93
93
  * @example
94
94
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../src/DateInput/DateInput.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../src/DateInput/DateInput.tsx"],"names":[],"mappings":"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"}
@@ -41,6 +41,11 @@ import { plainDateFromISO, plainDateToISO, formatSharedDate } from "../utils/pla
41
41
  import { effectivePickerPresentation, resolvePickerPresentation } from "../utils/inputPresentation.js";
42
42
  import { useDevWarning } from "../hooks/useDevWarning.js";
43
43
  const styles = {
44
+ disabledFocusRing: {
45
+ kVAM5u: "xvy26l8 x2uiyk",
46
+ kGVxlE: "x1gnnqk1 xxsos93",
47
+ $$css: true
48
+ },
44
49
  iconButton: {
45
50
  k1xSpc: "x78zum5",
46
51
  kGNEyG: "x6s0dn4",
@@ -212,11 +217,11 @@ function PointerDateField({
212
217
  const isBusy = isLoading || optimisticValue !== value;
213
218
  const isEffectivelyDisabled = isDisabled || isBusy;
214
219
 
215
- // Disabled-reason tooltip. Disabled controls swallow pointer events, so the
216
- // tooltip listeners attach to the input container (which already exists) and
217
- // the text input stays perceivable via aria-disabled instead of the disabled
218
- // attribute. Typing is blocked with readOnly and value mutation guards;
219
- // calendar activation is blocked by the isEffectivelyDisabled guards. Only
220
+ // A disabled or busy field never renders native `disabled` (spec:AST-085
221
+ // FR1): the input and calendar button stay focusable via aria-disabled.
222
+ // Typing is blocked with readOnly and value mutation guards; calendar
223
+ // activation is blocked by the isEffectivelyDisabled guards. The
224
+ // disabled-reason tooltip's listeners attach to the input container. Only
220
225
  // the persistent isDisabled state (not the transient busy state) surfaces a
221
226
  // reason.
222
227
  const showsDisabledMessage = isDisabled && !!disabledMessage;
@@ -357,8 +362,8 @@ function PointerDateField({
357
362
 
358
363
  // Handle input text change - update immediately if valid and allowed
359
364
  const handleInputChange = useCallback(e => {
360
- // With a disabledMessage the input drops `disabled` for focusability, so
361
- // guard value mutation explicitly (readOnly also blocks typing).
365
+ // The input is never natively disabled (spec:AST-085 FR1), so guard
366
+ // value mutation explicitly (readOnly also blocks typing).
362
367
  if (isEffectivelyDisabled) {
363
368
  return;
364
369
  }
@@ -381,6 +386,11 @@ function PointerDateField({
381
386
  if (pendingInput === null) {
382
387
  return;
383
388
  }
389
+ // Disabled or busy: keep the value, drop the draft (spec:AST-085 FR2).
390
+ if (isEffectivelyDisabled) {
391
+ setPendingInput(null);
392
+ return;
393
+ }
384
394
  if (!pendingInput.trim()) {
385
395
  if (value !== undefined) {
386
396
  fireChange(undefined);
@@ -396,7 +406,7 @@ function PointerDateField({
396
406
  }
397
407
  }
398
408
  setPendingInput(null);
399
- }, [pendingInput, value, fireChange, isDateDisabled, locale]);
409
+ }, [pendingInput, isEffectivelyDisabled, value, fireChange, isDateDisabled, locale]);
400
410
 
401
411
  // Handle blur - validate, check constraints, and clear pending input
402
412
  const handleBlur = useCallback(() => {
@@ -442,14 +452,17 @@ function PointerDateField({
442
452
  size,
443
453
  status: status?.type ?? null,
444
454
  disabled: isDisabled ? 'disabled' : null
445
- }), stylex.props(inputWrapperStyles.base, sizeStyles[size], isEffectivelyDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], inputGroup && groupStyles.inGroup, controlXstyle), controlClassName, controlStyle),
455
+ }), stylex.props(inputWrapperStyles.base, sizeStyles[size], isEffectivelyDisabled && inputWrapperStyles.disabled, isEffectivelyDisabled && styles.disabledFocusRing, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], inputGroup && groupStyles.inGroup, controlXstyle), controlClassName, controlStyle),
446
456
  children: [inputGroup && /*#__PURE__*/_jsx(VisuallyHidden, {
447
457
  id: inputLabelID,
448
458
  children: label
449
459
  }), /*#__PURE__*/_jsx("button", {
450
460
  type: "button",
451
461
  onClick: handleToggle,
452
- disabled: isEffectivelyDisabled,
462
+ "aria-disabled": isEffectivelyDisabled || undefined
463
+ // A tab stop while disabled too, so it carries the reason (FR5).
464
+ ,
465
+ "aria-describedby": showsDisabledMessage ? disabledMessageTooltip.describedBy : undefined,
453
466
  "aria-label": popover.isOpen ? t('@astryx.dateInput.toggleCalendarClose') : t('@astryx.dateInput.openCalendar'),
454
467
  ...stylex.props(focusOutlineStyles.focusVisible, styles.iconButton, isEffectivelyDisabled && styles.iconButtonDisabled),
455
468
  children: /*#__PURE__*/_jsx(Icon, {
@@ -476,17 +489,11 @@ function PointerDateField({
476
489
  value: displayValue,
477
490
  onChange: handleInputChange,
478
491
  onBlur: chainEventHandlers(handleBlur, onBlurProp),
479
- onClick: chainEventHandlers(handleInputClick, onClickProp),
492
+ onClick: isEffectivelyDisabled ? undefined : chainEventHandlers(handleInputClick, onClickProp),
480
493
  onKeyDown: chainEventHandlers(handleInputKeyDown, onKeyDownProp),
481
- placeholder: placeholder
482
- // With a disabledMessage the input keeps focusability via
483
- // aria-disabled so the reason is focus-discoverable; typing is
484
- // blocked with readOnly and the mutation guards, and calendar
485
- // activation is blocked by the isEffectivelyDisabled guards.
486
- ,
487
- disabled: isEffectivelyDisabled && !showsDisabledMessage,
488
- "aria-disabled": showsDisabledMessage ? 'true' : undefined,
489
- readOnly: showsDisabledMessage || undefined,
494
+ placeholder: placeholder,
495
+ "aria-disabled": isEffectivelyDisabled ? 'true' : undefined,
496
+ readOnly: isEffectivelyDisabled || undefined,
490
497
  "aria-labelledby": ariaLabelledByProp != null ? joinAriaIDs(ariaLabelledBy ?? fieldLabelID, ariaLabelledByProp) : ariaLabelledBy,
491
498
  "aria-describedby": ariaDescribedBy,
492
499
  "aria-required": isEffectivelyRequired ? 'true' : undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"NativeDateField.d.ts","sourceRoot":"","sources":["../../src/DateInput/NativeDateField.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AA6MhD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAe,EACf,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,SAAiB,EACjB,GAAG,EACH,GAAG,EACH,eAAe,EACf,WAAW,EAAE,oBAAoB,EACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,aAA0B,EAC1B,YAAY,EACZ,QAAgB,EAGhB,cAAc,EAAE,eAAe,EAC/B,YAAY,EAAE,aAAa,EAC3B,MAAoB,EACpB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,GAAG,SAAS,EACb,EAAE,cAAc,+BA+ahB;yBAlde,eAAe"}
1
+ {"version":3,"file":"NativeDateField.d.ts","sourceRoot":"","sources":["../../src/DateInput/NativeDateField.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AAwNhD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAe,EACf,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,SAAiB,EACjB,GAAG,EACH,GAAG,EACH,eAAe,EACf,WAAW,EAAE,oBAAoB,EACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,aAA0B,EAC1B,YAAY,EACZ,QAAgB,EAGhB,cAAc,EAAE,eAAe,EAC/B,YAAY,EAAE,aAAa,EAC3B,MAAoB,EACpB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,GAAG,SAAS,EACb,EAAE,cAAc,+BAibhB;yBApde,eAAe"}
@@ -49,6 +49,11 @@ import { focusOutlineStyles, formatSharedDate, getInputARIA, mergeProps, parseDa
49
49
  import { chainEventHandlers } from "../utils/chainEventHandlers.js";
50
50
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
51
51
  const styles = {
52
+ disabledFocusRing: {
53
+ kVAM5u: "xvy26l8 x2uiyk",
54
+ kGVxlE: "x1gnnqk1 xxsos93",
55
+ $$css: true
56
+ },
52
57
  wrapper: {
53
58
  kOIVth: "x1txdalj",
54
59
  $$css: true
@@ -174,9 +179,10 @@ export function NativeDateField({
174
179
  // platform picker from its input.
175
180
  const isEffectivelyDisabled = isDisabled || isLoading;
176
181
 
177
- // Disabled-reason tooltip, same contract as the other two surfaces: a
178
- // disabled control swallows pointer events, so the listeners attach to the
179
- // wrapper and the input stays focusable via aria-disabled.
182
+ // Same contract as the other two surfaces: a disabled field never renders
183
+ // native `disabled` (spec:AST-085 FR1); the input stays focusable via
184
+ // aria-disabled and readOnly. The disabled-reason tooltip's listeners
185
+ // attach to the wrapper.
180
186
  const showsDisabledMessage = isDisabled && !!disabledMessage;
181
187
  const disabledMessageTooltip = useTooltip({
182
188
  placement: 'above',
@@ -395,14 +401,14 @@ export function NativeDateField({
395
401
  size,
396
402
  status: status?.type ?? null,
397
403
  disabled: isDisabled ? 'disabled' : null
398
- }), stylex.props(inputWrapperStyles.base, sizeStyles[size], styles.wrapper, isEffectivelyDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], inputGroup && groupStyles.inGroup, controlXstyle), controlClassName, controlStyle),
404
+ }), stylex.props(inputWrapperStyles.base, sizeStyles[size], styles.wrapper, isEffectivelyDisabled && inputWrapperStyles.disabled, isEffectivelyDisabled && styles.disabledFocusRing, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], inputGroup && groupStyles.inGroup, controlXstyle), controlClassName, controlStyle),
399
405
  children: [inputGroup && /*#__PURE__*/_jsx(VisuallyHidden, {
400
406
  id: inputLabelID,
401
407
  children: label
402
408
  }), /*#__PURE__*/_jsx("button", {
403
409
  type: "button",
404
410
  onClick: openPicker,
405
- disabled: isEffectivelyDisabled,
411
+ "aria-disabled": isEffectivelyDisabled || undefined,
406
412
  "aria-label": t('@astryx.dateInput.openCalendar'),
407
413
  tabIndex: -1,
408
414
  ...stylex.props(focusOutlineStyles.focusVisible, styles.iconButton, isEffectivelyDisabled && styles.iconButtonDisabled),
@@ -420,6 +426,7 @@ export function NativeDateField({
420
426
  },
421
427
  children: [/*#__PURE__*/_jsx("input", {
422
428
  ...controlProps,
429
+ onClick: isEffectivelyDisabled ? undefined : controlProps.onClick,
423
430
  ref: mergedInputRef,
424
431
  id: id,
425
432
  type: "date"
@@ -432,9 +439,8 @@ export function NativeDateField({
432
439
  onBlur: chainEventHandlers(handleBlur, onBlurProp),
433
440
  min: min,
434
441
  max: max,
435
- disabled: isEffectivelyDisabled && !showsDisabledMessage,
436
- "aria-disabled": showsDisabledMessage ? 'true' : undefined,
437
- readOnly: showsDisabledMessage || undefined,
442
+ "aria-disabled": isEffectivelyDisabled ? 'true' : undefined,
443
+ readOnly: isEffectivelyDisabled || undefined,
438
444
  "aria-labelledby": ariaLabelledByProp != null ? joinAriaIDs(ariaLabelledBy ?? fieldLabelID, ariaLabelledByProp) : ariaLabelledBy,
439
445
  "aria-describedby": ariaDescribedBy,
440
446
  "aria-required": isEffectivelyRequired ? 'true' : undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"TouchDateField.d.ts","sourceRoot":"","sources":["../../src/DateInput/TouchDateField.tsx"],"names":[],"mappings":"AAgEA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AAgehD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAe,EACf,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,SAAiB,EACjB,GAAG,EACH,GAAG,EACH,eAAe,EACf,WAAW,EAAE,oBAAoB,EACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,aAA0B,EAC1B,YAAY,EACZ,QAAgB,EAIhB,cAAc,EAAE,eAAe,EAC/B,YAAY,EAAE,gBAAoB,EAClC,MAAoB,EACpB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,GAAG,SAAS,EACb,EAAE,cAAc,+BAmvBhB;yBAvxBe,cAAc"}
1
+ {"version":3,"file":"TouchDateField.d.ts","sourceRoot":"","sources":["../../src/DateInput/TouchDateField.tsx"],"names":[],"mappings":"AAgEA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AA2ehD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAe,EACf,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,SAAiB,EACjB,GAAG,EACH,GAAG,EACH,eAAe,EACf,WAAW,EAAE,oBAAoB,EACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,aAA0B,EAC1B,YAAY,EACZ,QAAgB,EAIhB,cAAc,EAAE,eAAe,EAC/B,YAAY,EAAE,gBAAoB,EAClC,MAAoB,EACpB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,GAAG,SAAS,EACb,EAAE,cAAc,+BAuvBhB;yBA3xBe,cAAc"}
@@ -122,6 +122,11 @@ const sizeStyles = {
122
122
  }
123
123
  };
124
124
  const styles = {
125
+ disabledFocusRing: {
126
+ kVAM5u: "xvy26l8 x2uiyk",
127
+ kGVxlE: "x1gnnqk1 xxsos93",
128
+ $$css: true
129
+ },
125
130
  wrapper: {
126
131
  kOIVth: "x1txdalj",
127
132
  $$css: true
@@ -276,11 +281,11 @@ export function TouchDateField({
276
281
  const isBusy = isLoading || optimisticValue !== value;
277
282
  const isEffectivelyDisabled = isDisabled || isBusy;
278
283
 
279
- // Disabled-reason tooltip, same contract as DateInput: a disabled control
280
- // swallows pointer events, so the listeners attach to the wrapper and the
281
- // input stays focusable via aria-disabled rather than the disabled
282
- // attribute. Only the persistent disabled state surfaces a reason, never
283
- // the transient busy one.
284
+ // Same contract as DateInput: a disabled or busy field never renders native
285
+ // `disabled` (spec:AST-085 FR1); the input stays focusable via
286
+ // aria-disabled. The disabled-reason tooltip's listeners attach to the
287
+ // wrapper. Only the persistent disabled state surfaces a reason, never the
288
+ // transient busy one.
284
289
  const showsDisabledMessage = isDisabled && !!disabledMessage;
285
290
  const disabledMessageTooltip = useTooltip({
286
291
  placement: 'above',
@@ -791,14 +796,14 @@ export function TouchDateField({
791
796
  size,
792
797
  status: status?.type ?? null,
793
798
  disabled: isDisabled ? 'disabled' : null
794
- }), stylex.props(inputWrapperStyles.base, sizeStyles[size], styles.wrapper, isEffectivelyDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], inputGroup && groupStyles.inGroup, controlXstyle), controlClassName, controlStyle),
799
+ }), stylex.props(inputWrapperStyles.base, sizeStyles[size], styles.wrapper, isEffectivelyDisabled && inputWrapperStyles.disabled, isEffectivelyDisabled && styles.disabledFocusRing, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], inputGroup && groupStyles.inGroup, controlXstyle), controlClassName, controlStyle),
795
800
  children: [inputGroup && /*#__PURE__*/_jsx(VisuallyHidden, {
796
801
  id: inputLabelID,
797
802
  children: label
798
803
  }), /*#__PURE__*/_jsx("button", {
799
804
  type: "button",
800
805
  onClick: openSheet,
801
- disabled: isEffectivelyDisabled,
806
+ "aria-disabled": isEffectivelyDisabled || undefined,
802
807
  "aria-label": t('@astryx.dateInput.openCalendar'),
803
808
  tabIndex: -1,
804
809
  ...stylex.props(focusOutlineStyles.focusVisible, styles.iconButton, isEffectivelyDisabled && styles.iconButtonDisabled),
@@ -825,11 +830,10 @@ export function TouchDateField({
825
830
  readOnly: true,
826
831
  inputMode: "none",
827
832
  onChange: () => {},
828
- onClick: chainEventHandlers(openSheet, onClickProp),
833
+ onClick: isEffectivelyDisabled ? undefined : chainEventHandlers(openSheet, onClickProp),
829
834
  onKeyDown: chainEventHandlers(handleInputKeyDown, onKeyDownProp),
830
835
  placeholder: placeholder,
831
- disabled: isEffectivelyDisabled && !showsDisabledMessage,
832
- "aria-disabled": showsDisabledMessage ? 'true' : undefined,
836
+ "aria-disabled": isEffectivelyDisabled ? 'true' : undefined,
833
837
  "aria-labelledby": ariaLabelledByProp != null ? joinAriaIDs(ariaLabelledBy ?? fieldLabelID, ariaLabelledByProp) : ariaLabelledBy,
834
838
  "aria-describedby": ariaDescribedBy,
835
839
  "aria-required": isEffectivelyRequired ? 'true' : undefined,
@@ -47,9 +47,8 @@ export interface LinkProps extends BaseProps<HTMLAnchorElement | HTMLButtonEleme
47
47
  /**
48
48
  * Whether the link is disabled.
49
49
  * A disabled link renders as a plain anchor without an href (and without
50
- * target/rel/onClick), so it cannot be focused or activated — no
51
- * navigation and no onClick, even via programmatic focus or assistive
52
- * technology activation.
50
+ * target/rel/onClick), so it cannot navigate or run onClick. It keeps a tab
51
+ * stop and is announced as a disabled link.
53
52
  * @default false
54
53
  */
55
54
  isDisabled?: boolean;
@@ -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;AAqG/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;;;;;;;OAOG;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;AAWD;;;;;;;;;;;;;;;;;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,+BAmJX;yBA5Ke,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;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"}
package/dist/Link/Link.js CHANGED
@@ -31,6 +31,7 @@ import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
31
31
  import { interactionOverlayStyles } from "../utils/interactionOverlay.stylex.js";
32
32
  import { usePressFeedback } from "../hooks/usePressFeedback.js";
33
33
  import { useTranslator } from "../i18n/index.js";
34
+ import { disabledInteractionProps } from "../utils/disabledInteraction.js";
34
35
 
35
36
  /**
36
37
  * Base link styles
@@ -107,15 +108,6 @@ const linkColorStyles = {
107
108
  $$css: true
108
109
  }
109
110
  };
110
- /**
111
- * Click handler for disabled links. The disabled anchor renders without an
112
- * href, so there is no navigation to block in practice; preventDefault is a
113
- * defensive guard against synthetic/programmatic clicks.
114
- */
115
- function preventDefaultClick(event) {
116
- event.preventDefault();
117
- }
118
-
119
111
  /**
120
112
  * A styled anchor link component.
121
113
  *
@@ -209,8 +201,6 @@ export function Link({
209
201
  ...(isDisabled ? undefined : pressable),
210
202
  "aria-label": label || undefined,
211
203
  "aria-disabled": isDisabled || undefined,
212
- tabIndex: isDisabled ? -1 : undefined,
213
- disabled: isDisabled,
214
204
  ...mergeProps(themeProps('link', {
215
205
  color
216
206
  }), focusOutlineProps.focusVisible(styles.base, styles.buttonReset, linkColorStyles[color],
@@ -218,25 +208,27 @@ export function Link({
218
208
  // colour change above, so a press is the one background it paints.
219
209
  !isDisabled && interactionOverlayStyles.pressedBackgroundColor, hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, isDisabled && styles.disabled, xstyle), className, style),
220
210
  ...props,
211
+ ...(isDisabled ? disabledInteractionProps(props.onKeyDown) : null),
221
212
  children: sharedContent
222
213
  });
223
214
  } else if (isDisabled) {
224
- // A disabled link renders as a plain <a> with no href: an href-less
225
- // anchor is not focusable and exposes no link affordance, so programmatic
226
- // focus + Enter, AT activation commands, and middle-click cannot navigate
227
- // or fire the consumer onClick. The router LinkComponent is deliberately
228
- // skipped — a disabled link performs no navigation, and custom router
229
- // links may require a live href. target/rel are omitted with the href.
215
+ // A disabled link renders as an <a> with no href, so nothing can navigate
216
+ // and the consumer onClick never fires. It keeps a Tab stop and the link
217
+ // role so keyboard and screen-reader users still find it (spec:AST-085
218
+ // FR1, FR5). The router LinkComponent is deliberately skipped — a disabled
219
+ // link performs no navigation, and custom router links may require a live
220
+ // href. target/rel are omitted with the href.
230
221
  linkElement = /*#__PURE__*/_jsx("a", {
231
222
  ref: ref,
232
- onClick: preventDefaultClick,
223
+ role: "link",
233
224
  "aria-label": label || undefined,
234
225
  "aria-disabled": true,
235
- tabIndex: -1,
226
+ tabIndex: 0,
236
227
  ...mergeProps(themeProps('link', {
237
228
  color
238
229
  }), focusOutlineProps.focusVisible(styles.base, linkColorStyles[color], hasUnderline && styles.hasUnderline, isStandalone && styles.standalone, styles.disabled, xstyle), className, style),
239
230
  ...props,
231
+ ...disabledInteractionProps(props.onKeyDown),
240
232
  children: sharedContent
241
233
  });
242
234
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../src/Popover/Popover.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAIZ,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AAMtE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAuBhD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,2EAA2E;IAC3E,GAAG,EAAE,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACtC,sHAAsH;IACtH,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,KAAK,IAAI,CAAC;IAC5C,0EAA0E;IAC1E,eAAe,EAAE,QAAQ,CAAC;IAC1B,6DAA6D;IAC7D,eAAe,EAAE,OAAO,CAAC;IACzB,4DAA4D;IAC5D,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,yBAAyB,KAAK,SAAS,CAAC,CAAC;IAEzE;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAEzC;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAEzB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAuDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,OAAO,EACP,SAAmB,EACnB,SAAmB,EACnB,MAAM,EACN,YAAY,EACZ,SAAgB,EAChB,KAAK,EACL,OAAW,EACX,KAAK,EACL,IAAe,EACf,OAAO,EACP,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,eAAsB,EACtB,gBAAuB,EACvB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,GACtB,EAAE,YAAY,GAAG,YAAY,CA8U7B;yBArWe,OAAO"}
1
+ {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../src/Popover/Popover.tsx"],"names":[],"mappings":"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"}
@@ -234,8 +234,11 @@ export function Popover({
234
234
  }, [content, popover.isOpen, scheduleOverflowMeasurement]);
235
235
 
236
236
  // Shared handler for click events on the trigger button.
237
- const handleTriggerClick = useCallback(() => {
238
- if (!isEnabled) {
237
+ const handleTriggerClick = useCallback(event => {
238
+ // An aria-disabled trigger stays focusable but opens nothing
239
+ // (spec:AST-085 FR2), even for a click dispatched straight on it.
240
+ const trigger = event?.currentTarget;
241
+ if (!isEnabled || trigger instanceof Element && trigger.getAttribute('aria-disabled') === 'true') {
239
242
  return;
240
243
  }
241
244
  popover.toggle();
@@ -247,7 +250,7 @@ export function Popover({
247
250
  const handleTriggerKeyDown = useCallback(e => {
248
251
  if (e.key === 'Enter' || e.key === ' ') {
249
252
  e.preventDefault();
250
- handleTriggerClick();
253
+ handleTriggerClick(e);
251
254
  }
252
255
  }, [handleTriggerClick]);
253
256
 
@@ -379,7 +382,8 @@ export function Popover({
379
382
  if (isRenderProp) {
380
383
  const triggerProps = {
381
384
  ref: popover.triggerRef,
382
- onClick: handleTriggerClick,
385
+ // The caller renders and owns this trigger element.
386
+ onClick: () => handleTriggerClick(),
383
387
  'aria-haspopup': 'dialog',
384
388
  'aria-expanded': popover.isOpen,
385
389
  'aria-controls': popover.id
@@ -1 +1 @@
1
- {"version":3,"file":"Token.d.ts","sourceRoot":"","sources":["../../src/Token/Token.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAiBrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAM5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AAM3C;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,WAAW,CAAC;IACxD,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA2JD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,IAAW,EACX,KAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,WAAW,EACX,UAAU,EACV,aAAqB,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,UAAU,+BA+LZ;yBAjNe,KAAK"}
1
+ {"version":3,"file":"Token.d.ts","sourceRoot":"","sources":["../../src/Token/Token.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAiBrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAM5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AAO3C;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,WAAW,CAAC;IACxD,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA2JD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,IAAW,EACX,KAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,WAAW,EACX,UAAU,EACV,aAAqB,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,UAAU,+BAkMZ;yBApNe,KAAK"}
@@ -29,6 +29,7 @@ import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
29
29
  import { interactionOverlayStyles } from "../utils/interactionOverlay.stylex.js";
30
30
  import { usePressFeedback } from "../hooks/usePressFeedback.js";
31
31
  import { useTranslator } from "../i18n/index.js";
32
+ import { disabledInteractionProps } from "../utils/disabledInteraction.js";
32
33
 
33
34
  // =============================================================================
34
35
  // Types
@@ -235,8 +236,11 @@ export function Token({
235
236
  onClick: e => {
236
237
  e.stopPropagation();
237
238
  onRemove(e);
238
- },
239
- disabled: isDisabled,
239
+ }
240
+ // Focusable while disabled (spec:AST-085 FR1), but inert (FR2).
241
+ ,
242
+ "aria-disabled": isDisabled || undefined,
243
+ ...(isDisabled ? disabledInteractionProps() : null),
240
244
  ...focusOutlineProps.focusVisible(styles.removeButton),
241
245
  children: /*#__PURE__*/_jsx(Icon, {
242
246
  icon: "close",
@@ -344,7 +348,8 @@ export function Token({
344
348
  children: [icon, /*#__PURE__*/_jsx("button", {
345
349
  type: "button",
346
350
  onClick: effectiveOnClick,
347
- disabled: isDisabled,
351
+ "aria-disabled": isDisabled || undefined,
352
+ ...(isDisabled ? disabledInteractionProps() : null),
348
353
  ...{
349
354
  className: "xmper1u x16khyan x1heor9g x1a2a7pz xb3r6kr xeuugli"
350
355
  },
package/dist/astryx.css CHANGED
@@ -646,6 +646,7 @@
646
646
  .xa1yw2k:focus-within:not(#\#):not(#\#){border-color:var(--color-warning)}
647
647
  .x1bax923.x1bax923:where(.xgy66g5:has(:focus-visible) *):not(#\#):not(#\#){outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color)}
648
648
  .x1dordxg:focus-within:not(#\#):not(#\#){overflow:visible}
649
+ .x2uiyk:has(input:focus):not(#\#):not(#\#){border-color:var(--color-accent)}
649
650
  .xb0m1lw:has(> div > .astryx-layout-content):not(#\#):not(#\#){margin-inline:0}
650
651
  .x16s19ga:has(:focus-visible):not(#\#):not(#\#){outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color)}
651
652
  .xf0xpto:placeholder-shown:not(#\#):not(#\#){flex:0 0 auto}
@@ -1535,6 +1536,7 @@
1535
1536
  .x1qf1n5z.x1qf1n5z:where(.astryx-input-group > *):focus-visible:not(#\#):not(#\#):not(#\#){z-index:2}
1536
1537
  .x1s2lk0z.x1s2lk0z:where(:not(:disabled,[aria-disabled="true"]))[data-astryx-press="fading"]:not(#\#):not(#\#):not(#\#){--_press-overlay:var(--_press-paint)}
1537
1538
  .x1sad4of.x1sad4of:where(:not(:disabled,[aria-disabled="true"]))[data-astryx-press="on"]:not(#\#):not(#\#):not(#\#){--_press-overlay:var(--_press-paint)}
1539
+ .xxsos93:has(input:focus):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 0 2px var(--color-accent-muted)}
1538
1540
  .x1btxeh5:has(input:focus-visible):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 0 2px var(--color-accent)}
1539
1541
  .xsw3flo:has(> div > .astryx-layout-content):not(#\#):not(#\#):not(#\#){container-type:inline-size}
1540
1542
  .x1ab7gxt:has(~ * > [data-astryx-submenu-regions="view"]:not([hidden])):not(#\#):not(#\#):not(#\#){display:none}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @file disabledInteraction.ts
3
+ * @input An optional caller keydown handler
4
+ * @output Event props that keep a focusable, aria-disabled control inert
5
+ * @position Shared by controls that replace native `disabled` with
6
+ * `aria-disabled` under spec:AST-085 (FR1, FR2)
7
+ */
8
+ import type { KeyboardEvent, KeyboardEventHandler, MouseEvent } from 'react';
9
+ /**
10
+ * Event props for a disabled control that stays focusable. Native `disabled`
11
+ * dispatched no click at all; without it, Enter and Space still synthesize a
12
+ * click that native listeners on the element (a wrapping Popover's trigger)
13
+ * receive. Cancelling those keys keeps the click from existing, and the click
14
+ * handler cancels pointer clicks and keeps them from reaching ancestors. Other
15
+ * keys still reach the caller's handler.
16
+ */
17
+ export declare function disabledInteractionProps<T extends HTMLElement>(onKeyDown?: KeyboardEventHandler<T>): {
18
+ onClick: (event: MouseEvent<T>) => void;
19
+ onKeyDown: (event: KeyboardEvent<T>) => void;
20
+ };
21
+ //# sourceMappingURL=disabledInteraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabledInteraction.d.ts","sourceRoot":"","sources":["../../src/utils/disabledInteraction.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAE,oBAAoB,EAAE,UAAU,EAAC,MAAM,OAAO,CAAC;AAE3E;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,WAAW,EAC5D,SAAS,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAClC;IACD,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACxC,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CAC9C,CAcA"}
@@ -0,0 +1,33 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file disabledInteraction.ts
5
+ * @input An optional caller keydown handler
6
+ * @output Event props that keep a focusable, aria-disabled control inert
7
+ * @position Shared by controls that replace native `disabled` with
8
+ * `aria-disabled` under spec:AST-085 (FR1, FR2)
9
+ */
10
+
11
+ /**
12
+ * Event props for a disabled control that stays focusable. Native `disabled`
13
+ * dispatched no click at all; without it, Enter and Space still synthesize a
14
+ * click that native listeners on the element (a wrapping Popover's trigger)
15
+ * receive. Cancelling those keys keeps the click from existing, and the click
16
+ * handler cancels pointer clicks and keeps them from reaching ancestors. Other
17
+ * keys still reach the caller's handler.
18
+ */
19
+ export function disabledInteractionProps(onKeyDown) {
20
+ return {
21
+ onClick: event => {
22
+ event.preventDefault();
23
+ event.stopPropagation();
24
+ },
25
+ onKeyDown: event => {
26
+ if (event.key === 'Enter' || event.key === ' ') {
27
+ event.preventDefault();
28
+ } else {
29
+ onKeyDown?.(event);
30
+ }
31
+ }
32
+ };
33
+ }