[temporal] New DateField, TimeField and DateTimeField components#3666
[temporal] New DateField, TimeField and DateTimeField components#3666flaviendelangle wants to merge 57 commits intomui:masterfrom
DateField, TimeField and DateTimeField components#3666Conversation
commit: |
Bundle size report
Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
DateField component
DateField componentDateField and TimeField component
DateField and TimeField componentDateField and TimeField components
DateField and TimeField componentsDateField, TimeField and DateTimeField components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
813d7d4 to
72a30d7
Compare
I improved the JSDoc 👍 |
|
What makes you think that? |
|
Points 1, 2 and 3 applied |
GPT-5.4 Pro ReviewI like the direction overall. The shared temporal core looks strong, and the accessibility work is thoughtful. But I would still treat this as not merge-ready yet because the PR is very large — about +20,597 / -274 across 186 files — so any public-API ambiguity here will be expensive to unwind later. ([GitHub]1) What I would change before merge:
What looks especially good:
On AGENTS.md specifically: I’d say this is mostly conformant on the code side and not fully there on the docs side. The implementation shares logic well, uses the DOM-safe owner utilities AGENTS asks for, and clearly invested in tests/docs. The main miss is that some hand-written docs still overstate or contradict the actual API behavior, and AGENTS explicitly says public docs should be updated accurately when the API changes. ([GitHub]7) My net: promising implementation, but I would block on 1–4. The React Aria gap is not that Base UI lacks power; it’s that React Aria’s model is currently easier to understand and harder to misuse. |
Thank your GPT 🙏 😆 |
For that one, I really think it's a bad idea to remove the |
Fixed |
This is a real DX discussion we need to have. format?: string | TemporalFieldFormatConfig
interface TemporalFieldFormatConfig {
granularity: TemporalFieldGranularity;
ampm?: boolean
// ...
} |
I added a more detailed doc (+ strengthen the validation in the parsing) but we need to discuss where we should document that 👀 |
0b3b59b to
5fb59e0
Compare
There was a problem hiding this comment.
Considering this is only used in packages/react/src/date-field/utils/TemporalFieldStore.ts, could we keep this file in that local utils folder? It would avoid making it part of the public API.
There was a problem hiding this comment.
I'm using it in the Scheduler + Tree View (on MUI X) and on the Tree PR on Base UI.
I neeed an equivalent of useTimeout for components with large stores out of React.
What problem do you see putting it in @base-ui/utils?
There was a problem hiding this comment.
It's fine if it's used in many places, just want to make sure we don't increase the API size for no reason.
Btw, why use a manager class rather than individual timeouts? The way I do it when I need multiple timeouts somewhere is something like this:
class X {
constructor() {
this.mouseDownTimeout = new Timeout()
this.mouseUpTimeout = new Timeout()
// etc
}
}Admittedly, declaring multiple timeouts upfront may have a performance impact that a manager doesn't have, and the cleanup isn't as neat (currently, but we could implement the new Disposable protocol to ease it up). However, with a manager the type safety is currently not as good.
I also see that the timeout names use inconsistent casing (mix of dash-case and camelCase), and that the interval methods are never used (and also don't strictly match with the name of the class).
There was a problem hiding this comment.
The interval methods are only used on the Scheduler.
I can drop them in favor of an IntervalManager that I don't move to @base-ui/utils until it's used in 2-3 packages (why might never be the case).
The main downside I see with standalone timeouts is the cleanup, it's easy to miss one in the mountEffect cleanup function, especially with plugins.
But if you have a way to make them autoclean, I'm all in favor of removing the abstraction.
I'll fix the casing 👍
Follow-up observations1. PlaceholdersOn X Pickers we decided to have no Maybe you could add a 2. FormsEnter clicks inside of a field are probably prevented, as they do not seem to submit a form. 3. Label
4. Experiments
P.S. Sorry I delayed this one, forgot the draft wasn't posted. 🙈 |
|
Point 2, 3 and 4 solved. |
Makes sense. If the team is happy with the UX of the current state, then we are GtG on this one. 👌
The field does not seem to propagate a form submit as seen in this experiment. Screen.Recording.2026-03-27.at.17.37.42.mov
I meant this behavior. Screen.Recording.2026-03-27.at.17.32.55.mov
Are you sure? |
|
I just didn't push the code 🤷 |
| const defaultButton = form.querySelector<HTMLElement>( | ||
| 'input[type="submit"], button[type="submit"], button:not([type])', | ||
| ); | ||
| if (defaultButton) { | ||
| defaultButton.click(); | ||
| } |
There was a problem hiding this comment.
| const defaultButton = form.querySelector<HTMLElement>( | |
| 'input[type="submit"], button[type="submit"], button:not([type])', | |
| ); | |
| if (defaultButton) { | |
| defaultButton.click(); | |
| } | |
| form.requestSubmit(); |

Follow up on #1973
Part of #1709
I'm doing to tests to see if the Calendar internals as suitable for the next steps.
To read before reviewing
TValuegeneric is always equal toTemporalFieldSupportedObject. I kept it because it will be needed for the range fields if we keep the MUI X approach.