From bc6bc12b935b66c5ad5da14f177c24f85e3d5f77 Mon Sep 17 00:00:00 2001 From: Cindy Zhang Date: Mon, 12 Oct 2026 04:38:01 -0700 Subject: [PATCH 1/4] docs(DateInput): list the part styling props and record FR10 in the contract List containerClassName, containerStyle, controlClassName, and controlStyle in the English, Chinese, and dense API references, and update the draft contract for the family FR10 base-prop and part-styling adoption and the shared clear glyph target. --- .../date-input-part-style-props-docs.md | 7 +++ packages/core/src/DateInput/DateInput.doc.mjs | 52 ++++++++++++++++ packages/core/src/DateInput/DateInput.spec.md | 62 ++++++++++--------- 3 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 .changeset/date-input-part-style-props-docs.md diff --git a/.changeset/date-input-part-style-props-docs.md b/.changeset/date-input-part-style-props-docs.md new file mode 100644 index 0000000000000..bdd8e4fa3c710 --- /dev/null +++ b/.changeset/date-input-part-style-props-docs.md @@ -0,0 +1,7 @@ +--- +'@astryxdesign/core': patch +--- + +[docs] List `DateInput`'s `containerClassName`, `containerStyle`, `controlClassName`, and `controlStyle` props in its API reference, alongside `containerXstyle` and `controlXstyle`. + +@cixzhang diff --git a/packages/core/src/DateInput/DateInput.doc.mjs b/packages/core/src/DateInput/DateInput.doc.mjs index 7618bd598c1c9..a7689d49316a6 100644 --- a/packages/core/src/DateInput/DateInput.doc.mjs +++ b/packages/core/src/DateInput/DateInput.doc.mjs @@ -182,12 +182,36 @@ export const docs = { description: 'StyleX styles for the Field box around the label, control, and status. containerClassName and containerStyle take a class name and inline styles for the same box. No effect (development warning) where no Field box renders: inside InputGroup (style the group) and in a horizontal-labels FormLayout.', }, + { + name: 'containerClassName', + type: 'string', + description: + 'Class name for the Field box. Same targeting as containerXstyle.', + }, + { + name: 'containerStyle', + type: 'CSSProperties', + description: + 'Inline styles for the Field box. Same targeting as containerXstyle.', + }, { name: 'controlXstyle', type: 'StyleXStyles', description: 'StyleX styles for the visual control box: the bordered element that holds the text, icons, and end controls, never the native input. controlClassName and controlStyle take a class name and inline styles for the same box. Replaces root xstyle, className, and style, which this component does not accept.', }, + { + name: 'controlClassName', + type: 'string', + description: + 'Class name for the visual control box. Same targeting as controlXstyle.', + }, + { + name: 'controlStyle', + type: 'CSSProperties', + description: + 'Inline styles for the visual control box. Same targeting as controlXstyle.', + }, ], theming: { targets: [ @@ -503,12 +527,32 @@ export const docsZh = { description: '作用于包含标签、控件和状态的 Field 容器的 StyleX 样式;containerClassName 与 containerStyle 以类名和内联样式作用于同一容器。没有 Field 容器时(InputGroup 内或 horizontal-labels FormLayout 中)不生效,并在开发环境发出警告。', }, + { + name: 'containerClassName', + type: 'string', + description: 'Field 容器的类名,作用目标同 containerXstyle。', + }, + { + name: 'containerStyle', + type: 'CSSProperties', + description: 'Field 容器的内联样式,作用目标同 containerXstyle。', + }, { name: 'controlXstyle', type: 'StyleXStyles', description: '作用于可见控件框(带边框、包含文本、图标和末端控件的元素,而非原生 input)的 StyleX 样式;controlClassName 与 controlStyle 以类名和内联样式作用于同一元素。本组件不接受根级 xstyle、className 和 style。', }, + { + name: 'controlClassName', + type: 'string', + description: '可见控件框的类名,作用目标同 controlXstyle。', + }, + { + name: 'controlStyle', + type: 'CSSProperties', + description: '可见控件框的内联样式,作用目标同 controlXstyle。', + }, ], theming: { targets: [ @@ -615,7 +659,15 @@ export const docsDense = { "deprecated, use presentation: 'touch'='adaptive-native', 'always'='native', 'never'='adaptive-bottom-sheet'. still works as released; presentation wins if both set.", containerXstyle: 'Field box (label+control+status); also containerClassName/containerStyle. no effect in InputGroup or horizontal-labels FormLayout', + containerClassName: + 'class name for the Field box; same target as containerXstyle', + containerStyle: + 'inline styles for the Field box; same target as containerXstyle', controlXstyle: 'visual control box (border/bg/icons), never the native input; also controlClassName/controlStyle. no root xstyle/className/style', + controlClassName: + 'class name for the visual control box; same target as controlXstyle', + controlStyle: + 'inline styles for the visual control box; same target as controlXstyle', }, }; diff --git a/packages/core/src/DateInput/DateInput.spec.md b/packages/core/src/DateInput/DateInput.spec.md index d9479dcd1a9c8..fe1f78d84fd47 100644 --- a/packages/core/src/DateInput/DateInput.spec.md +++ b/packages/core/src/DateInput/DateInput.spec.md @@ -13,6 +13,7 @@ review_triggers: [public-api, behavior, layout, theming, accessibility] verified_by: [ packages/core/src/DateInput/DateInput.test.tsx, + packages/core/src/DateInput/DateInput.fr10.test.tsx, packages/core/src/DateInput/DateInputTouch.test.tsx, packages/core/src/DateInput/NativeDateField.test.tsx, packages/core/src/DateInput/Presentation.test.tsx, @@ -48,7 +49,7 @@ compatibility promise, ownership boundary, or visual direction. | Builder impact | Existing native DateInput `changeAction` handlers now run after `onChange` and receive optimistic busy feedback. No API or migration work is required. | | Compatibility/readiness | Compatible patch correction under the current input-field family rule. Released defaults and controlled ownership are preserved; exact-head browser evidence remains audit evidence rather than product authority. | | Review checks | Reject a surface-mapping change, lost constraint, callback-order change, unlabeled field, unreachable disabled reason, changed close behavior, or a theming target placed on the wrong owner. | -| Governing rules | `spec:AST-043/FR1–FR5`; `family:input-fields/FR1–FR6, FR8–FR9`; `family:overlay-dismissal/FR1–FR7`, including its recorded BottomSheet adoption gap; the three architecture records linked above. | +| Governing rules | `spec:AST-043/FR1–FR5`; `family:input-fields/FR1–FR6, FR8–FR10`; `family:overlay-dismissal/FR1–FR7`, including its recorded BottomSheet adoption gap; the three architecture records linked above. | This table is a review projection; the body below is authoritative only after this record becomes `current`. @@ -120,20 +121,21 @@ Consumer migration instructions belong in consumer docs and release notes. Draft requirements identify their evidence basis; they do not turn observation into approved policy. -| ID | Candidate invariant | Basis | Draft review state | -| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------- | -| FR1 | DateInput MUST present the controlled ISO `value` and emit `onChange` with the next ISO date or `undefined` without maintaining a competing committed value. | Current source, docs, and focused tests | Verified shipped behavior | -| FR2 | The five `presentation` values MUST resolve to the fine/coarse surfaces in `spec:AST-043/FR1`; omitting both presentation props MUST preserve `adaptive-native`. | `spec:AST-043/FR1–FR3`; Presentation tests | Settled by current system authority | -| FR3 | Explicit `presentation` MUST outrank deprecated `nativePicker`; the legacy values MUST retain their mappings and development-only warning from `spec:AST-043/FR3–FR4`. | Current source, docs, and Presentation tests | Settled by current system authority | -| FR4 | Adaptive resolution MUST use the primary pointer rather than viewport width or any-pointer availability, so tablets receive a touch surface and touchscreen laptops retain the typable field. | Current source, consumer docs, and surface-selection tests | Verified shipped behavior | -| FR5 | Text, Calendar, bottom-sheet, and native commit paths MUST enforce `min`, `max`, and `dateConstraints`; a rejected value MUST NOT replace the controlled value. | Current source and all four focused suites | Verified shipped behavior | -| FR6 | Named committed formats MUST follow the InternationalizationProvider locale and shared Timestamp vocabulary; formatting MUST NOT rewrite in-progress typed text. | Current source, docs, locale tests, `spec:AST-043/FR5` | Verified shipped behavior | -| FR7 | Every value-change path MUST call `onChange` before `changeAction`, present the proposed value optimistically, and expose one busy state while the Action is pending. | `family:input-fields/FR6`; current source and focused tests | Settled shared rule and verified adoption | -| FR8 | The pointer field MUST open its Calendar from the input, calendar toggle, ArrowDown, or Alt+ArrowDown; Popover dismissal and focus return MUST remain owned by the shared Popover path. | Current source, Popover composition, keyboard/focus tests | Verified shipped behavior | -| FR9 | A pointer-surface Calendar selection MUST commit and close its Popover; a bottom-sheet Calendar selection MUST remain editable in the open sheet until Save closes the surface. | Current source and pointer/touch tests | Verified shipped behavior | -| FR10 | Standalone mode MUST compose Field; admitted InputGroup mode MUST remove competing Field chrome while preserving name, description, value, keyboard, focus, and editing semantics. | `family:input-fields/FR3`; current source and InputGroup tests | Settled shared rule and verified adoption | -| FR11 | Clear MUST emit `undefined` through the ordinary change pipeline. The pointer and bottom-sheet surfaces restore field focus using their shipped timing; the native surface MUST NOT reclaim focus because doing so reopens the OS picker. | Current source and focused clear tests | Verified shipped behavior | -| FR12 | Disabled-with-reason MUST remain focusable enough to expose its explanation while blocking mutation. Ordinary disabled and explicit-loading states remain inactive. During a pending Action, pointer and bottom-sheet surfaces remain inactive; the native surface stays focusable so the OS picker remains attached but rejects additional commits until the Action settles. | `family:input-fields/FR4–FR6`; current source and focused tests | Settled shared rule and verified adoption | +| ID | Candidate invariant | Basis | Draft review state | +| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------- | +| FR1 | DateInput MUST present the controlled ISO `value` and emit `onChange` with the next ISO date or `undefined` without maintaining a competing committed value. | Current source, docs, and focused tests | Verified shipped behavior | +| FR2 | The five `presentation` values MUST resolve to the fine/coarse surfaces in `spec:AST-043/FR1`; omitting both presentation props MUST preserve `adaptive-native`. | `spec:AST-043/FR1–FR3`; Presentation tests | Settled by current system authority | +| FR3 | Explicit `presentation` MUST outrank deprecated `nativePicker`; the legacy values MUST retain their mappings and development-only warning from `spec:AST-043/FR3–FR4`. | Current source, docs, and Presentation tests | Settled by current system authority | +| FR4 | Adaptive resolution MUST use the primary pointer rather than viewport width or any-pointer availability, so tablets receive a touch surface and touchscreen laptops retain the typable field. | Current source, consumer docs, and surface-selection tests | Verified shipped behavior | +| FR5 | Text, Calendar, bottom-sheet, and native commit paths MUST enforce `min`, `max`, and `dateConstraints`; a rejected value MUST NOT replace the controlled value. | Current source and all four focused suites | Verified shipped behavior | +| FR6 | Named committed formats MUST follow the InternationalizationProvider locale and shared Timestamp vocabulary; formatting MUST NOT rewrite in-progress typed text. | Current source, docs, locale tests, `spec:AST-043/FR5` | Verified shipped behavior | +| FR7 | Every value-change path MUST call `onChange` before `changeAction`, present the proposed value optimistically, and expose one busy state while the Action is pending. | `family:input-fields/FR6`; current source and focused tests | Settled shared rule and verified adoption | +| FR8 | The pointer field MUST open its Calendar from the input, calendar toggle, ArrowDown, or Alt+ArrowDown; Popover dismissal and focus return MUST remain owned by the shared Popover path. | Current source, Popover composition, keyboard/focus tests | Verified shipped behavior | +| FR9 | A pointer-surface Calendar selection MUST commit and close its Popover; a bottom-sheet Calendar selection MUST remain editable in the open sheet until Save closes the surface. | Current source and pointer/touch tests | Verified shipped behavior | +| FR10 | Standalone mode MUST compose Field; admitted InputGroup mode MUST remove competing Field chrome while preserving name, description, value, keyboard, focus, and editing semantics. | `family:input-fields/FR3`; current source and InputGroup tests | Settled shared rule and verified adoption | +| FR11 | Clear MUST emit `undefined` through the ordinary change pipeline. The pointer and bottom-sheet surfaces restore field focus using their shipped timing; the native surface MUST NOT reclaim focus because doing so reopens the OS picker. | Current source and focused clear tests | Verified shipped behavior | +| FR12 | Disabled-with-reason MUST remain focusable enough to expose its explanation while blocking mutation. Ordinary disabled and explicit-loading states remain inactive. During a pending Action, pointer and bottom-sheet surfaces remain inactive; the native surface stays focusable so the OS picker remains attached but rejects additional commits until the Action settles. | `family:input-fields/FR4–FR6`; current source and focused tests | Settled shared rule and verified adoption | +| FR13 | Base props (`ref`, `id`, `data-*`, `aria-*`, and DOM event handlers) MUST reach the date input on every surface; root `xstyle`, `className`, and `style` are not accepted; `container*` MUST style the Field box where one renders and `control*` the visual control box, never the native input. A caller DOM handler runs after DateInput's own handler and cannot cancel built-in behavior. | `family:input-fields/FR10`; current source and FR10 tests | Settled shared rule and verified adoption | ### Allowed variation @@ -249,14 +251,15 @@ approved policy. The `date-input` target owns the composite field surface. The `date-input-toggle-icon` target reflects collapsed and expanded states on the icon -itself. The deprecated `date-input-clear-icon` alias remains compatibility metadata; -the shared `input-clear-icon` target owns current clear-glyph theming. +itself. The shared `input-clear-icon` target owns clear-glyph theming; DateInput adds no +clear-glyph target of its own. ## Family and system relationships - `family:input-fields` owns stable field sizing, end-control space, grouped - adaptation, disabled reasons, loading, Transition Actions, status placement, and - the iOS-only focus-zoom floor; DateInput adopts every listed concept. + adaptation, disabled reasons, loading, Transition Actions, status placement, + base-prop and part-styling targets, and the iOS-only focus-zoom floor; DateInput + adopts every listed concept. - `family:overlay-dismissal` owns topmost Popover and BottomSheet dismissal. DateInput's Popover path uses the shared owner; its bottom-sheet path inherits BottomSheet's recorded adoption gap. DateInput owns only selection, open-state requests, and focus @@ -271,16 +274,17 @@ the shared `input-clear-icon` target owns current clear-glyph theming. ## Verification map -| Contract | Verification | Representative states | Mutation or failure expectation | Audit section | -| ---------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------- | -| FR1, FR5–FR8, FR10–FR12; AR1–AR4 | `DateInput.test.tsx` | empty, valued, typing, invalid, constrained, open, disabled, busy, clear, status, grouped | Value, callbacks, ARIA, disabled guard, focus, or shared-field composition drifts | `audit:DateInput/pointer-field` | -| FR2–FR4 | `Presentation.test.tsx`, `NativeDateField.test.tsx`, `DateInputTouch.test.tsx` | every presentation, omitted props, every deprecated mapping, dual props, fine/coarse, touchscreen laptop | A value resolves to the wrong surface, width affects modality, or legacy behavior wins incorrectly | `audit:DateInput/presentation` | -| FR5–FR7; AR1, AR3–AR5 | `NativeDateField.test.tsx` | empty, valued, focused, constrained, disabled, clear, formatted, locale | Native commit, overlay, label, constraint, or focus reconciliation drifts | `audit:DateInput/native` | -| FR1, FR4–FR7, FR9, FR11–FR12; AR1, AR4, AR6; PR1–PR2 | `DateInputTouch.test.tsx` | closed/open, month grid, selection correction, wheels, bounds, keyboard, swipe, mouse drag, clear, busy | Touch value parity, bounded rendering, focus, semantics, or gesture ownership drifts | `audit:DateInput/touch` | -| FR2–FR3, FR6 | `DateInput.doc.mjs`, Storybook controls, `scripts/check-knowledge.mjs` | five presentation values, deprecated prop, named formats, English and Chinese docs | Source, docs, types, or default mappings disagree | `audit:DateInput/docs-api` | -| Theming anatomy | `DateInput.test.tsx`, `themingTargets.test.ts`, generated probe theme | root size/status/disabled, toggle state, shared clear target | Target class or state is missing, undocumented, or placed on the wrong element | `audit:DateInput/theming` | -| FR8; AR2 | `apps/storybook/stories/DateInput.stories.tsx`, component-scoped axe | open Calendar dialog plus closed field states | Important popup semantics stay unreachable to the browser audit | `audit:DateInput/a11y` | -| AR7 | `apps/storybook/rtl-audit/targets.json`, component RTL audit | calendar and clear controls in LTR and RTL | DateInput-owned controls fail to exchange logical inline order | `audit:DateInput/rtl` | +| Contract | Verification | Representative states | Mutation or failure expectation | Audit section | +| ---------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | +| FR1, FR5–FR8, FR10–FR12; AR1–AR4 | `DateInput.test.tsx` | empty, valued, typing, invalid, constrained, open, disabled, busy, clear, status, grouped | Value, callbacks, ARIA, disabled guard, focus, or shared-field composition drifts | `audit:DateInput/pointer-field` | +| FR2–FR4 | `Presentation.test.tsx`, `NativeDateField.test.tsx`, `DateInputTouch.test.tsx` | every presentation, omitted props, every deprecated mapping, dual props, fine/coarse, touchscreen laptop | A value resolves to the wrong surface, width affects modality, or legacy behavior wins incorrectly | `audit:DateInput/presentation` | +| FR5–FR7; AR1, AR3–AR5 | `NativeDateField.test.tsx` | empty, valued, focused, constrained, disabled, clear, formatted, locale | Native commit, overlay, label, constraint, or focus reconciliation drifts | `audit:DateInput/native` | +| FR1, FR4–FR7, FR9, FR11–FR12; AR1, AR4, AR6; PR1–PR2 | `DateInputTouch.test.tsx` | closed/open, month grid, selection correction, wheels, bounds, keyboard, swipe, mouse drag, clear, busy | Touch value parity, bounded rendering, focus, semantics, or gesture ownership drifts | `audit:DateInput/touch` | +| FR2–FR3, FR6 | `DateInput.doc.mjs`, Storybook controls, `scripts/check-knowledge.mjs` | five presentation values, deprecated prop, named formats, English and Chinese docs | Source, docs, types, or default mappings disagree | `audit:DateInput/docs-api` | +| Theming anatomy | `DateInput.test.tsx`, `themingTargets.test.ts`, generated probe theme | root size/status/disabled, toggle state, shared clear target | Target class or state is missing, undocumented, or placed on the wrong element | `audit:DateInput/theming` | +| FR8; AR2 | `apps/storybook/stories/DateInput.stories.tsx`, component-scoped axe | open Calendar dialog plus closed field states | Important popup semantics stay unreachable to the browser audit | `audit:DateInput/a11y` | +| AR7 | `apps/storybook/rtl-audit/targets.json`, component RTL audit | calendar and clear controls in LTR and RTL | DateInput-owned controls fail to exchange logical inline order | `audit:DateInput/rtl` | +| FR13 | `DateInput.fr10.test.tsx` | pointer, native, and touch surfaces; standalone, InputGroup, and horizontal-labels FormLayout | Base props land off the control, root styling is accepted, part styling reroutes, or a caller handler runs first or cancels built-in behavior | `audit:DateInput/api` | ## Decision log From 5e4d37c3f7addb2f7ec53c3794bf2394f83ceb38 Mon Sep 17 00:00:00 2001 From: Cindy Zhang Date: Mon, 12 Oct 2026 05:10:41 -0700 Subject: [PATCH 2/4] docs(DateInput): link the family FR10 rule instead of restating part of it --- packages/core/src/DateInput/DateInput.spec.md | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/core/src/DateInput/DateInput.spec.md b/packages/core/src/DateInput/DateInput.spec.md index fe1f78d84fd47..a0cbde9f5a12c 100644 --- a/packages/core/src/DateInput/DateInput.spec.md +++ b/packages/core/src/DateInput/DateInput.spec.md @@ -121,21 +121,21 @@ Consumer migration instructions belong in consumer docs and release notes. Draft requirements identify their evidence basis; they do not turn observation into approved policy. -| ID | Candidate invariant | Basis | Draft review state | -| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------- | -| FR1 | DateInput MUST present the controlled ISO `value` and emit `onChange` with the next ISO date or `undefined` without maintaining a competing committed value. | Current source, docs, and focused tests | Verified shipped behavior | -| FR2 | The five `presentation` values MUST resolve to the fine/coarse surfaces in `spec:AST-043/FR1`; omitting both presentation props MUST preserve `adaptive-native`. | `spec:AST-043/FR1–FR3`; Presentation tests | Settled by current system authority | -| FR3 | Explicit `presentation` MUST outrank deprecated `nativePicker`; the legacy values MUST retain their mappings and development-only warning from `spec:AST-043/FR3–FR4`. | Current source, docs, and Presentation tests | Settled by current system authority | -| FR4 | Adaptive resolution MUST use the primary pointer rather than viewport width or any-pointer availability, so tablets receive a touch surface and touchscreen laptops retain the typable field. | Current source, consumer docs, and surface-selection tests | Verified shipped behavior | -| FR5 | Text, Calendar, bottom-sheet, and native commit paths MUST enforce `min`, `max`, and `dateConstraints`; a rejected value MUST NOT replace the controlled value. | Current source and all four focused suites | Verified shipped behavior | -| FR6 | Named committed formats MUST follow the InternationalizationProvider locale and shared Timestamp vocabulary; formatting MUST NOT rewrite in-progress typed text. | Current source, docs, locale tests, `spec:AST-043/FR5` | Verified shipped behavior | -| FR7 | Every value-change path MUST call `onChange` before `changeAction`, present the proposed value optimistically, and expose one busy state while the Action is pending. | `family:input-fields/FR6`; current source and focused tests | Settled shared rule and verified adoption | -| FR8 | The pointer field MUST open its Calendar from the input, calendar toggle, ArrowDown, or Alt+ArrowDown; Popover dismissal and focus return MUST remain owned by the shared Popover path. | Current source, Popover composition, keyboard/focus tests | Verified shipped behavior | -| FR9 | A pointer-surface Calendar selection MUST commit and close its Popover; a bottom-sheet Calendar selection MUST remain editable in the open sheet until Save closes the surface. | Current source and pointer/touch tests | Verified shipped behavior | -| FR10 | Standalone mode MUST compose Field; admitted InputGroup mode MUST remove competing Field chrome while preserving name, description, value, keyboard, focus, and editing semantics. | `family:input-fields/FR3`; current source and InputGroup tests | Settled shared rule and verified adoption | -| FR11 | Clear MUST emit `undefined` through the ordinary change pipeline. The pointer and bottom-sheet surfaces restore field focus using their shipped timing; the native surface MUST NOT reclaim focus because doing so reopens the OS picker. | Current source and focused clear tests | Verified shipped behavior | -| FR12 | Disabled-with-reason MUST remain focusable enough to expose its explanation while blocking mutation. Ordinary disabled and explicit-loading states remain inactive. During a pending Action, pointer and bottom-sheet surfaces remain inactive; the native surface stays focusable so the OS picker remains attached but rejects additional commits until the Action settles. | `family:input-fields/FR4–FR6`; current source and focused tests | Settled shared rule and verified adoption | -| FR13 | Base props (`ref`, `id`, `data-*`, `aria-*`, and DOM event handlers) MUST reach the date input on every surface; root `xstyle`, `className`, and `style` are not accepted; `container*` MUST style the Field box where one renders and `control*` the visual control box, never the native input. A caller DOM handler runs after DateInput's own handler and cannot cancel built-in behavior. | `family:input-fields/FR10`; current source and FR10 tests | Settled shared rule and verified adoption | +| ID | Candidate invariant | Basis | Draft review state | +| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------- | +| FR1 | DateInput MUST present the controlled ISO `value` and emit `onChange` with the next ISO date or `undefined` without maintaining a competing committed value. | Current source, docs, and focused tests | Verified shipped behavior | +| FR2 | The five `presentation` values MUST resolve to the fine/coarse surfaces in `spec:AST-043/FR1`; omitting both presentation props MUST preserve `adaptive-native`. | `spec:AST-043/FR1–FR3`; Presentation tests | Settled by current system authority | +| FR3 | Explicit `presentation` MUST outrank deprecated `nativePicker`; the legacy values MUST retain their mappings and development-only warning from `spec:AST-043/FR3–FR4`. | Current source, docs, and Presentation tests | Settled by current system authority | +| FR4 | Adaptive resolution MUST use the primary pointer rather than viewport width or any-pointer availability, so tablets receive a touch surface and touchscreen laptops retain the typable field. | Current source, consumer docs, and surface-selection tests | Verified shipped behavior | +| FR5 | Text, Calendar, bottom-sheet, and native commit paths MUST enforce `min`, `max`, and `dateConstraints`; a rejected value MUST NOT replace the controlled value. | Current source and all four focused suites | Verified shipped behavior | +| FR6 | Named committed formats MUST follow the InternationalizationProvider locale and shared Timestamp vocabulary; formatting MUST NOT rewrite in-progress typed text. | Current source, docs, locale tests, `spec:AST-043/FR5` | Verified shipped behavior | +| FR7 | Every value-change path MUST call `onChange` before `changeAction`, present the proposed value optimistically, and expose one busy state while the Action is pending. | `family:input-fields/FR6`; current source and focused tests | Settled shared rule and verified adoption | +| FR8 | The pointer field MUST open its Calendar from the input, calendar toggle, ArrowDown, or Alt+ArrowDown; Popover dismissal and focus return MUST remain owned by the shared Popover path. | Current source, Popover composition, keyboard/focus tests | Verified shipped behavior | +| FR9 | A pointer-surface Calendar selection MUST commit and close its Popover; a bottom-sheet Calendar selection MUST remain editable in the open sheet until Save closes the surface. | Current source and pointer/touch tests | Verified shipped behavior | +| FR10 | Standalone mode MUST compose Field; admitted InputGroup mode MUST remove competing Field chrome while preserving name, description, value, keyboard, focus, and editing semantics. | `family:input-fields/FR3`; current source and InputGroup tests | Settled shared rule and verified adoption | +| FR11 | Clear MUST emit `undefined` through the ordinary change pipeline. The pointer and bottom-sheet surfaces restore field focus using their shipped timing; the native surface MUST NOT reclaim focus because doing so reopens the OS picker. | Current source and focused clear tests | Verified shipped behavior | +| FR12 | Disabled-with-reason MUST remain focusable enough to expose its explanation while blocking mutation. Ordinary disabled and explicit-loading states remain inactive. During a pending Action, pointer and bottom-sheet surfaces remain inactive; the native surface stays focusable so the OS picker remains attached but rejects additional commits until the Action settles. | `family:input-fields/FR4–FR6`; current source and focused tests | Settled shared rule and verified adoption | +| FR13 | DateInput MUST adopt `family:input-fields/FR10` on every surface. Its primary semantic control is the text input with `role=combobox` on the pointer and bottom-sheet surfaces and the `` on the native surface. | `family:input-fields/FR10`; current source and FR10 tests | Settled shared rule and verified adoption | ### Allowed variation @@ -274,17 +274,17 @@ clear-glyph target of its own. ## Verification map -| Contract | Verification | Representative states | Mutation or failure expectation | Audit section | -| ---------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | -| FR1, FR5–FR8, FR10–FR12; AR1–AR4 | `DateInput.test.tsx` | empty, valued, typing, invalid, constrained, open, disabled, busy, clear, status, grouped | Value, callbacks, ARIA, disabled guard, focus, or shared-field composition drifts | `audit:DateInput/pointer-field` | -| FR2–FR4 | `Presentation.test.tsx`, `NativeDateField.test.tsx`, `DateInputTouch.test.tsx` | every presentation, omitted props, every deprecated mapping, dual props, fine/coarse, touchscreen laptop | A value resolves to the wrong surface, width affects modality, or legacy behavior wins incorrectly | `audit:DateInput/presentation` | -| FR5–FR7; AR1, AR3–AR5 | `NativeDateField.test.tsx` | empty, valued, focused, constrained, disabled, clear, formatted, locale | Native commit, overlay, label, constraint, or focus reconciliation drifts | `audit:DateInput/native` | -| FR1, FR4–FR7, FR9, FR11–FR12; AR1, AR4, AR6; PR1–PR2 | `DateInputTouch.test.tsx` | closed/open, month grid, selection correction, wheels, bounds, keyboard, swipe, mouse drag, clear, busy | Touch value parity, bounded rendering, focus, semantics, or gesture ownership drifts | `audit:DateInput/touch` | -| FR2–FR3, FR6 | `DateInput.doc.mjs`, Storybook controls, `scripts/check-knowledge.mjs` | five presentation values, deprecated prop, named formats, English and Chinese docs | Source, docs, types, or default mappings disagree | `audit:DateInput/docs-api` | -| Theming anatomy | `DateInput.test.tsx`, `themingTargets.test.ts`, generated probe theme | root size/status/disabled, toggle state, shared clear target | Target class or state is missing, undocumented, or placed on the wrong element | `audit:DateInput/theming` | -| FR8; AR2 | `apps/storybook/stories/DateInput.stories.tsx`, component-scoped axe | open Calendar dialog plus closed field states | Important popup semantics stay unreachable to the browser audit | `audit:DateInput/a11y` | -| AR7 | `apps/storybook/rtl-audit/targets.json`, component RTL audit | calendar and clear controls in LTR and RTL | DateInput-owned controls fail to exchange logical inline order | `audit:DateInput/rtl` | -| FR13 | `DateInput.fr10.test.tsx` | pointer, native, and touch surfaces; standalone, InputGroup, and horizontal-labels FormLayout | Base props land off the control, root styling is accepted, part styling reroutes, or a caller handler runs first or cancels built-in behavior | `audit:DateInput/api` | +| Contract | Verification | Representative states | Mutation or failure expectation | Audit section | +| ---------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | +| FR1, FR5–FR8, FR10–FR12; AR1–AR4 | `DateInput.test.tsx` | empty, valued, typing, invalid, constrained, open, disabled, busy, clear, status, grouped | Value, callbacks, ARIA, disabled guard, focus, or shared-field composition drifts | `audit:DateInput/pointer-field` | +| FR2–FR4 | `Presentation.test.tsx`, `NativeDateField.test.tsx`, `DateInputTouch.test.tsx` | every presentation, omitted props, every deprecated mapping, dual props, fine/coarse, touchscreen laptop | A value resolves to the wrong surface, width affects modality, or legacy behavior wins incorrectly | `audit:DateInput/presentation` | +| FR5–FR7; AR1, AR3–AR5 | `NativeDateField.test.tsx` | empty, valued, focused, constrained, disabled, clear, formatted, locale | Native commit, overlay, label, constraint, or focus reconciliation drifts | `audit:DateInput/native` | +| FR1, FR4–FR7, FR9, FR11–FR12; AR1, AR4, AR6; PR1–PR2 | `DateInputTouch.test.tsx` | closed/open, month grid, selection correction, wheels, bounds, keyboard, swipe, mouse drag, clear, busy | Touch value parity, bounded rendering, focus, semantics, or gesture ownership drifts | `audit:DateInput/touch` | +| FR2–FR3, FR6 | `DateInput.doc.mjs`, Storybook controls, `scripts/check-knowledge.mjs` | five presentation values, deprecated prop, named formats, English and Chinese docs | Source, docs, types, or default mappings disagree | `audit:DateInput/docs-api` | +| Theming anatomy | `DateInput.test.tsx`, `themingTargets.test.ts`, generated probe theme | root size/status/disabled, toggle state, shared clear target | Target class or state is missing, undocumented, or placed on the wrong element | `audit:DateInput/theming` | +| FR8; AR2 | `apps/storybook/stories/DateInput.stories.tsx`, component-scoped axe | open Calendar dialog plus closed field states | Important popup semantics stay unreachable to the browser audit | `audit:DateInput/a11y` | +| AR7 | `apps/storybook/rtl-audit/targets.json`, component RTL audit | calendar and clear controls in LTR and RTL | DateInput-owned controls fail to exchange logical inline order | `audit:DateInput/rtl` | +| FR13 | `DateInput.fr10.test.tsx` | pointer, native, and touch surfaces; standalone, InputGroup, and horizontal-labels FormLayout | A surface stops meeting `family:input-fields/FR10` or routes base props to an element other than its primary semantic control | `audit:DateInput/api` | ## Decision log From 8dcb60563613166fdfd243593b2b848c3f1fe9a3 Mon Sep 17 00:00:00 2001 From: Cindy Zhang Date: Mon, 12 Oct 2026 05:41:12 -0700 Subject: [PATCH 3/4] chore: retrigger the preview deployment From 4faee79d299c5f4661bfecbb01a7aade966440ee Mon Sep 17 00:00:00 2001 From: Cindy Zhang Date: Mon, 12 Oct 2026 06:36:30 -0700 Subject: [PATCH 4/4] docs(DateInput): cite the family FR10 rule without a new component requirement --- packages/core/src/DateInput/DateInput.spec.md | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/core/src/DateInput/DateInput.spec.md b/packages/core/src/DateInput/DateInput.spec.md index a0cbde9f5a12c..162387f7604ac 100644 --- a/packages/core/src/DateInput/DateInput.spec.md +++ b/packages/core/src/DateInput/DateInput.spec.md @@ -135,7 +135,6 @@ approved policy. | FR10 | Standalone mode MUST compose Field; admitted InputGroup mode MUST remove competing Field chrome while preserving name, description, value, keyboard, focus, and editing semantics. | `family:input-fields/FR3`; current source and InputGroup tests | Settled shared rule and verified adoption | | FR11 | Clear MUST emit `undefined` through the ordinary change pipeline. The pointer and bottom-sheet surfaces restore field focus using their shipped timing; the native surface MUST NOT reclaim focus because doing so reopens the OS picker. | Current source and focused clear tests | Verified shipped behavior | | FR12 | Disabled-with-reason MUST remain focusable enough to expose its explanation while blocking mutation. Ordinary disabled and explicit-loading states remain inactive. During a pending Action, pointer and bottom-sheet surfaces remain inactive; the native surface stays focusable so the OS picker remains attached but rejects additional commits until the Action settles. | `family:input-fields/FR4–FR6`; current source and focused tests | Settled shared rule and verified adoption | -| FR13 | DateInput MUST adopt `family:input-fields/FR10` on every surface. Its primary semantic control is the text input with `role=combobox` on the pointer and bottom-sheet surfaces and the `` on the native surface. | `family:input-fields/FR10`; current source and FR10 tests | Settled shared rule and verified adoption | ### Allowed variation @@ -274,17 +273,16 @@ clear-glyph target of its own. ## Verification map -| Contract | Verification | Representative states | Mutation or failure expectation | Audit section | -| ---------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | -| FR1, FR5–FR8, FR10–FR12; AR1–AR4 | `DateInput.test.tsx` | empty, valued, typing, invalid, constrained, open, disabled, busy, clear, status, grouped | Value, callbacks, ARIA, disabled guard, focus, or shared-field composition drifts | `audit:DateInput/pointer-field` | -| FR2–FR4 | `Presentation.test.tsx`, `NativeDateField.test.tsx`, `DateInputTouch.test.tsx` | every presentation, omitted props, every deprecated mapping, dual props, fine/coarse, touchscreen laptop | A value resolves to the wrong surface, width affects modality, or legacy behavior wins incorrectly | `audit:DateInput/presentation` | -| FR5–FR7; AR1, AR3–AR5 | `NativeDateField.test.tsx` | empty, valued, focused, constrained, disabled, clear, formatted, locale | Native commit, overlay, label, constraint, or focus reconciliation drifts | `audit:DateInput/native` | -| FR1, FR4–FR7, FR9, FR11–FR12; AR1, AR4, AR6; PR1–PR2 | `DateInputTouch.test.tsx` | closed/open, month grid, selection correction, wheels, bounds, keyboard, swipe, mouse drag, clear, busy | Touch value parity, bounded rendering, focus, semantics, or gesture ownership drifts | `audit:DateInput/touch` | -| FR2–FR3, FR6 | `DateInput.doc.mjs`, Storybook controls, `scripts/check-knowledge.mjs` | five presentation values, deprecated prop, named formats, English and Chinese docs | Source, docs, types, or default mappings disagree | `audit:DateInput/docs-api` | -| Theming anatomy | `DateInput.test.tsx`, `themingTargets.test.ts`, generated probe theme | root size/status/disabled, toggle state, shared clear target | Target class or state is missing, undocumented, or placed on the wrong element | `audit:DateInput/theming` | -| FR8; AR2 | `apps/storybook/stories/DateInput.stories.tsx`, component-scoped axe | open Calendar dialog plus closed field states | Important popup semantics stay unreachable to the browser audit | `audit:DateInput/a11y` | -| AR7 | `apps/storybook/rtl-audit/targets.json`, component RTL audit | calendar and clear controls in LTR and RTL | DateInput-owned controls fail to exchange logical inline order | `audit:DateInput/rtl` | -| FR13 | `DateInput.fr10.test.tsx` | pointer, native, and touch surfaces; standalone, InputGroup, and horizontal-labels FormLayout | A surface stops meeting `family:input-fields/FR10` or routes base props to an element other than its primary semantic control | `audit:DateInput/api` | +| Contract | Verification | Representative states | Mutation or failure expectation | Audit section | +| ---------------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------- | +| FR1, FR5–FR8, FR10–FR12; AR1–AR4 | `DateInput.test.tsx` | empty, valued, typing, invalid, constrained, open, disabled, busy, clear, status, grouped | Value, callbacks, ARIA, disabled guard, focus, or shared-field composition drifts | `audit:DateInput/pointer-field` | +| FR2–FR4 | `Presentation.test.tsx`, `NativeDateField.test.tsx`, `DateInputTouch.test.tsx` | every presentation, omitted props, every deprecated mapping, dual props, fine/coarse, touchscreen laptop | A value resolves to the wrong surface, width affects modality, or legacy behavior wins incorrectly | `audit:DateInput/presentation` | +| FR5–FR7; AR1, AR3–AR5 | `NativeDateField.test.tsx` | empty, valued, focused, constrained, disabled, clear, formatted, locale | Native commit, overlay, label, constraint, or focus reconciliation drifts | `audit:DateInput/native` | +| FR1, FR4–FR7, FR9, FR11–FR12; AR1, AR4, AR6; PR1–PR2 | `DateInputTouch.test.tsx` | closed/open, month grid, selection correction, wheels, bounds, keyboard, swipe, mouse drag, clear, busy | Touch value parity, bounded rendering, focus, semantics, or gesture ownership drifts | `audit:DateInput/touch` | +| FR2–FR3, FR6 | `DateInput.doc.mjs`, Storybook controls, `scripts/check-knowledge.mjs` | five presentation values, deprecated prop, named formats, English and Chinese docs | Source, docs, types, or default mappings disagree | `audit:DateInput/docs-api` | +| Theming anatomy | `DateInput.test.tsx`, `themingTargets.test.ts`, generated probe theme | root size/status/disabled, toggle state, shared clear target | Target class or state is missing, undocumented, or placed on the wrong element | `audit:DateInput/theming` | +| FR8; AR2 | `apps/storybook/stories/DateInput.stories.tsx`, component-scoped axe | open Calendar dialog plus closed field states | Important popup semantics stay unreachable to the browser audit | `audit:DateInput/a11y` | +| AR7 | `apps/storybook/rtl-audit/targets.json`, component RTL audit | calendar and clear controls in LTR and RTL | DateInput-owned controls fail to exchange logical inline order | `audit:DateInput/rtl` | ## Decision log