Skip to content

refactor(DateInput, DateTimeInput): share typed entry in useTypedDateField - #9837

Closed
nynexman4464 wants to merge 41 commits into
mainfrom
nynexman4464/refactor/typed-entry-shared-hook
Closed

nynexman4464 wants to merge 41 commits into
mainfrom
nynexman4464/refactor/typed-entry-shared-hook

Conversation

@nynexman4464

@nynexman4464 nynexman4464 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Stack: #9643 → #10031 → #9794 → #9653 → #9837 → #9842

Declared stack: each pull request targets main and contains the one below it, so review only its own commits (the ones above #9653). The stack lands together.

Maintainer impact

DateInput and DateTimeInput each kept a copy of the same typed-entry logic: the typed text, the committed rejection, the date that typing last reported, the commit on Enter or blur, and the rejection status and alert. A fix to typed entry had to land twice, and the two copies could drift.

Intended invariant

No behavior change. Typing, commits, onChange reports, rejection messages, the field status, the alert, and the format hint stay as they are in both components.

Change

  • useTypedDateField in packages/core/src/DateInput/useTypedDate.ts now owns the typed text, the committed rejection, the last reported date, the commit on Enter or blur, the reset when a value comes from outside, the shown text and format hint, the shown status, and the alert message. It builds on useTypedDate.
  • DateInput and DateTimeInput call the hook and keep only what differs between them: how a date is reported (DateTimeInput combines it with the time), how emptied text clears the value, whether the shown status announces itself (an InputGroup DateInput does not), and the existing difference on commit in a disabled or busy field (DateInput drops the typed text; DateTimeInput reads it).
  • The hook is internal. It is not exported from the package entry point.
  • component:DateInput now links spec:AST-085 FR1 and FR2 in system_specs, because the source comments that cited them moved out of DateInput.tsx. No requirement text changes.
  • Two comments that restated the code are removed: the one above DateInput's fireChange, and the narration in DateTimeInput's status-icon comment, which keeps only its reason.
  • A [chore] changeset records the internal change.

Evidence

  • Failure before the change: not applicable; no behavior changes.
  • Success after the change: the existing tests pass with no test edits.
  • Product/runtime behavior verified unchanged: every DateInput and DateTimeInput test passes (932 tests; see Testing).
  • CI impact: none; no workflow or CI script changes.

Scope

  • No intended public API, product behavior, visual direction, or policy change.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

  • pnpm exec vitest run --maxWorkers=2 over every Vitest file in packages/core/src/DateInput and packages/core/src/DateTimeInput, plus docPropLiterals.test.ts: 22 files, 932 tests passed.
  • pnpm exec tsc --noEmit -p packages/core: passes.
  • eslint and prettier --check on the changed files: clean.
  • pnpm check:knowledge and pnpm check:changesets: pass.
  • node scripts/pre-review.mjs --base nynexman4464/feat/calendar-presentations: 724 authored lines.

Writing rubric results

Record: component:DateInput (two system_specs entries, spec:AST-085/FR1 and spec:AST-085/FR2).

  • R1 narration: none; no prose changes.
  • R2 research: none.
  • R3 evidence: none added.
  • R4 rejected alternatives: none.
  • R5 change references: none added.
  • R6 open questions: none.

@vercel

vercel Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 5, 2026 4:00am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 3, 2026
@astracat-bot

astracat-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Nov 5, 2026, 4:03 AM UTC

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested. The refactor preserves behavior: the existing DateInput, DateTimeInput and DateRangeInput suites pass unchanged, and every moved condition matches the code it replaces. One repository rule needs a small follow-up before approval.

Blocking

  • Removing the comments that cited spec:AST-085 FR1 and FR2 in packages/core/src/DateInput/DateInput.tsx drops those cited claims from pnpm specs:for packages/core/src/DateInput/DateInput.tsx, which architecture:knowledge-contracts INV29 allows only after a record links them, so add spec:AST-085/FR1 and spec:AST-085/FR2 to system_specs in docs/specs/components/DateInput/DateInput.spec.md, which makes the before and after output match.

Two non-blocking comment-wording suggestions are inline.

[Automated review]

if (pendingInput === null) {
return;
}
// Disabled or busy: keep the value, drop the draft (spec:AST-085 FR2).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment and the one at old line 835 were this file's only spec:AST-085 FR2 and FR1 citations, so pnpm specs:for packages/core/src/DateInput/DateInput.tsx no longer lists those claims (architecture:knowledge-contracts INV29). Add spec:AST-085/FR1 and spec:AST-085/FR2 to system_specs in docs/specs/components/DateInput/DateInput.spec.md to restore them.

if (pendingInput === null) {
return;
}
// A disabled or busy field keeps its value and drops the draft.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (INV29): this reads as a rule for every field, but it holds only when dropsDraftWhenDisabled is true. DateTimeInput still parses its draft. The option's JSDoc already says this, so the comment can go.

{/*
Live region announcing rejected typed input to assistive technology,
with one message for each kind of rejection (WCAG 3.3.1).
Announces a typed rejection that no shown status carries, with one

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (INV29): inside an InputGroup the field shows the typed status and this alert still announces it, so "no shown status carries" is not quite accurate. Suggested wording: "Announces a typed rejection that the field status does not announce. The field status announces the rest." The DateTimeInput comment and the alertMessage JSDoc in useTypedDate.ts need the same change.

@nynexman4464
nynexman4464 force-pushed the nynexman4464/feat/calendar-presentations branch from cb8dd2f to 3cef6a3 Compare November 4, 2026 00:19
@nynexman4464
nynexman4464 force-pushed the nynexman4464/refactor/typed-entry-shared-hook branch from be8e6e7 to 961c512 Compare November 4, 2026 00:19

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested. The refactor preserves behavior: the existing DateInput, DateTimeInput and DateRangeInput suites pass unchanged, and every moved condition matches the code it replaces. One repository rule needs a small follow-up before approval.

Blocking

  • Removing the comments that cited spec:AST-085 FR1 and FR2 in packages/core/src/DateInput/DateInput.tsx drops those cited claims from pnpm specs:for packages/core/src/DateInput/DateInput.tsx, which architecture:knowledge-contracts INV29 allows only after a record links them, so add spec:AST-085/FR1 and spec:AST-085/FR2 to system_specs in docs/specs/components/DateInput/DateInput.spec.md, which makes the before and after output match.

Two non-blocking comment-wording suggestions are inline.

[Automated review]

if (pendingInput === null) {
return;
}
// Disabled or busy: keep the value, drop the draft (spec:AST-085 FR2).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment and the one at old line 835 were this file's only spec:AST-085 FR2 and FR1 citations, so pnpm specs:for packages/core/src/DateInput/DateInput.tsx no longer lists those claims (architecture:knowledge-contracts INV29). Add spec:AST-085/FR1 and spec:AST-085/FR2 to system_specs in docs/specs/components/DateInput/DateInput.spec.md to restore them.

if (pendingInput === null) {
return;
}
// A disabled or busy field keeps its value and drops the draft.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (INV29): this reads as a rule for every field, but it holds only when dropsDraftWhenDisabled is true. DateTimeInput still parses its draft. The option's JSDoc already says this, so the comment can go.

{/*
Live region announcing rejected typed input to assistive technology,
with one message for each kind of rejection (WCAG 3.3.1).
Announces a typed rejection that no shown status carries, with one

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (INV29): inside an InputGroup the field shows the typed status and this alert still announces it, so "no shown status carries" is not quite accurate. Suggested wording: "Announces a typed rejection that the field status does not announce. The field status announces the rest." The DateTimeInput comment and the alertMessage JSDoc in useTypedDate.ts need the same change.

@nynexman4464
nynexman4464 force-pushed the nynexman4464/feat/calendar-presentations branch from 3cef6a3 to a26bf47 Compare November 4, 2026 18:42
@nynexman4464
nynexman4464 force-pushed the nynexman4464/refactor/typed-entry-shared-hook branch from 961c512 to d05ad0c Compare November 4, 2026 18:42

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. It runs once the pull request is ready for review and targets main.

The refactor keeps typing, commits, rejection messages, the field status and the alert unchanged in both fields. The existing DateInput, DateTimeInput and DateRangeInput suites pass with no test edits, and each moved condition matches the code it replaces. The earlier blocking item is resolved: component:DateInput now links spec:AST-085/FR1 and /FR2, so pnpm specs:for packages/core/src/DateInput/DateInput.tsx lists the same records and cited claims as before.

[Automated review]

@nynexman4464
nynexman4464 force-pushed the nynexman4464/feat/calendar-presentations branch from a26bf47 to 37c9150 Compare November 4, 2026 19:47
@nynexman4464
nynexman4464 force-pushed the nynexman4464/refactor/typed-entry-shared-hook branch from d05ad0c to d5dc7bb Compare November 4, 2026 19:47

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet, and it runs once the pull request is ready for review and targets main.

Typing, commits, rejection messages, the field status and the alert stay unchanged in both fields: the existing DateInput, DateTimeInput, DateRangeInput and Calendar suites pass with no test edits, and the same typed-entry states read identically before and after the move. Two optional comment cleanups are noted inline.

[Automated review]

const {isDateDisabled} = useCalendarConstraints({min, max, dateConstraints});
const typedDate = useTypedDate({

// Unified change handler that fires both onChange and changeAction

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (architecture:knowledge-contracts INV29): this comment restates what fireChange does, so it can go; the name and the body already say it.

Comment on lines +1036 to +1039
// DateTimeInput fixes its status presentation to the detached message box,
// so the shared helper suppresses the on-field icon (the message box carries
// its own leading glyph). Routed through the helper for consistency with the
// rest of the bordered input family.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (architecture:knowledge-contracts INV29): the last sentence narrates the call. Suggested, keeping only the reason:

// The detached message box carries its own glyph, so the helper shows no on-field icon.

@nynexman4464

Copy link
Copy Markdown
Contributor Author

/approve-spec e1cc948

@nynexman4464
nynexman4464 force-pushed the nynexman4464/feat/calendar-presentations branch from 02527f4 to 6db495e Compare November 4, 2026 22:55
@nynexman4464
nynexman4464 force-pushed the nynexman4464/refactor/typed-entry-shared-hook branch from e1cc948 to 1766698 Compare November 4, 2026 22:55
…he lost native warning as a failure

DateInput FR21 states that a pane's grid name keeps the era of its month's
middle day. The DateTimeInput FR12 verification row again fails a missing
warning for an explicit native.
DateRangeInput takes a calendar prop and otherwise follows the provider's calendar. Its trigger text and popover calendar use the calendar; values stay Gregorian ISO dates.
…d the -u-ca- request

The provider's calendar prop docs and record list DateRangeInput. The DateRangeInput record and changeset state that an explicit -u-ca- locale is the application's request, and the record's intent paragraph is rewrapped.
…regorian dates

The DateRangeInput record and the changeset say that a provider locale
with a -u-ca- keyword keeps Gregorian dates; set calendar to choose one.
A test asserts that the trigger's accessible name writes the range in the calendar. INV10 names DateRangeInput among the displays that follow the calendar.
…onthOf

calendarYearMonthOf now takes a calendar month, so the trigger's same-year
check passes the month of each date.
…Field

DateInput and DateTimeInput kept two copies of the same typed-entry logic: the typed text, the committed rejection, the date that typing last reported, and the commit on Enter or blur. useTypedDateField in useTypedDate.ts now owns that state and the rejection status and alert for both fields. Each field keeps its own clear and disabled rules: DateInput drops typed text when a disabled or busy field commits, and DateTimeInput reads it. Behavior is unchanged.
… DateInput record

The comments that cited these claims left DateInput.tsx in the shared-hook
move, so the DateInput record now links them. The live-region comments and
the alertMessage doc say which rejections the alert announces.
@nynexman4464 nynexman4464 reopened this Nov 5, 2026
@nynexman4464
nynexman4464 changed the base branch from nynexman4464/feat/calendar-presentations to main November 5, 2026 03:54
@nynexman4464
nynexman4464 force-pushed the nynexman4464/refactor/typed-entry-shared-hook branch from e56a372 to 669e1b2 Compare November 5, 2026 03:54
@github-actions github-actions Bot added the needs:design-review Affects visuals — Design should review label Nov 5, 2026
@nynexman4464

Copy link
Copy Markdown
Contributor Author

/approve-spec 669e1b2

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request is reviewed as part of its stack; see the review on #9842.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 669e1b2

Storybook · Sandbox · built from this PR's head

Modified components

Component Size LoC Visual · A11y · RTL
Calendar · Storybook 57.7 kB (+214 B) · 9.3 kB CSS (0) 1,714 (0) ✗ · ✓ · ✓
PowerSearch · Storybook 🔴 258.1 kB (+8.4 kB) · 22.3 kB CSS (0) 7,201 (0) ✓ · ✓ · ✓
DateInput · Storybook 🔴 163.0 kB (+8.0 kB) · 15.5 kB CSS (0) 5,610 (+507) ✓ · ✓ · ✓
6 more components
Component Size LoC Visual · A11y · RTL
DateTimeInput · Storybook 🔴 184.8 kB (+7.7 kB) · 17.2 kB CSS (0) 3,554 (−11) ✓ · ✓ · ✓
TimeInput 140.4 kB (0) · 14.5 kB CSS (0) — — · — · —
Timestamp 22.9 kB (−8 B) · 8.9 kB CSS (0) — — · — · —
DateRangeInput · Storybook 75.7 kB (−103 B) · 11.2 kB CSS (0) 684 (+17) ✓ · ✓ · ✓
lab/Comments 271.5 kB (new) · 2.5 kB CSS (new) — — · — · —
lab/CommentThread 266.4 kB (new) · 2.4 kB CSS (new) — — · — · —
Visual changes: 2 snapshots in 1 component

A change is a question for the reviewer, not a failure.

Component · story Before After Diff
Calendar · Default (neutral, light) before frame after frame diff frame
Calendar · Default (neutral, dark) before frame after frame diff frame

Package size: measured; main has no measurement of the merge base to compare yet.

API changes: cli +8 · ~1 · −0 (against the merge base's committed report); core +3 · ~0 · −0

Committed API report behind this build: cli 9 rows, core 3 rows; run pnpm api:report.

12 API changes (advisory)
Package Where Signature Usage
+ cli ./api · Types · type SearchResultEntry deprecated?: ComponentDeprecation | undefined import type {SearchResultEntry} from '@astryxdesign/cli/api'; const x: SearchResultEntry = {deprecated: …}
+ cli ./authoring · Types · interface ComponentDeprecation interface ComponentDeprecation import type {ComponentDeprecation} from '@astryxdesign/cli/authoring'
+ cli ./authoring · Types · interface MultiComponentDoc deprecated?: ComponentDeprecation import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {deprecated: …}
+ cli ./authoring · Types · interface SingleComponentDoc deprecated?: ComponentDeprecation import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {deprecated: …}
+ cli ./doc · Types · interface ComponentBaseDoc deprecated?: ComponentDeprecation import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {deprecated: …}
+ cli ./doc · Types · interface SubComponentDoc deprecated?: ComponentDeprecation import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {deprecated: …}
+ cli ./doc · Also exported from an earlier entry point · ComponentDeprecation ComponentDeprecation (./authoring) import {ComponentDeprecation} from '@astryxdesign/cli/doc'
+ cli ./template · Also exported from an earlier entry point · ComponentDeprecation ComponentDeprecation (./authoring) import {ComponentDeprecation} from '@astryxdesign/cli/template'
~ cli ./api · Functions · function search function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "hook" | "theme" | "doc" | undefined; limit?: number | undefined }) => Promise<SearchResponse> → function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "doc" | "theme" | "hook" | undefined; limit?: number | undefined }) => Promise<SearchResponse> import {search} from '@astryxdesign/cli/api'; search(…)
+ core . · Components · component DateInput prop calendar?: CalendarSystem = the InternationalizationProvider's calendar, else `'gregory'` <DateInput calendar="s calendar, else `" />
+ core . · Components · component DateRangeInput prop calendar?: CalendarSystem = the InternationalizationProvider's calendar, else `'gregory'` <DateRangeInput calendar="s calendar, else `" />
+ core . · Components · component DateTimeInput prop calendar?: CalendarSystem = the InternationalizationProvider's calendar, else `'gregory'` <DateTimeInput calendar="s calendar, else `" />

Touched components checked; add ci:run-visual, ci:run-a11y or ci:run-rtl to run the full suites.


Generated by PR Enrichment workflow | View full report

@nynexman4464

Copy link
Copy Markdown
Contributor Author

Folded into #9643: the review asked for the shared typed-entry hook (#9837) in the same change as the typed entry (#9643), so #9643 now carries this part unchanged, with this description reproduced as its own part. The declared stack is #9643 → #9842.

nynexman4464 added a commit that referenced this pull request Nov 5, 2026
…ates in the active calendar (#9643, #9842)

Lands the declared stack #9643 → #9842; each part was reviewed on its own pull request.

- #9643 (with #10031, #9794, #9653 and #9837 folded in): DateInput and DateTimeInput read and write typed dates in the active calendar; a non-Gregorian calendar uses the Astryx picker instead of the native control; the bottom sheet shows months of the calendar; DateRangeInput shows the range in the calendar; one shared typed-entry hook serves both fields.
- #9842: while DateInput or DateTimeInput is disabled or busy, typed text stays without a rejection, and commits or gives way once the field is editable.

Fixes #8958.
@github-actions
github-actions Bot deleted the nynexman4464/refactor/typed-entry-shared-hook branch November 5, 2026 06:03

This branch was successfully deployed

1 active deployment
Preview — 669e1b22 Deployed Nov 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. needs:design-review Affects visuals — Design should review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant