Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Create the doc of the new date pickers #6902

Merged
merged 6 commits into from
Nov 22, 2022

Conversation

flaviendelangle
Copy link
Member

@flaviendelangle flaviendelangle commented Nov 17, 2022

  • Copy the current state of docs/date/date-pickers/date-picker in docs/date/date-pickers/legacy-date-picker as make this new page accessible
  • Adapt the examples of docs/date/date-pickers/date-picker to use the new pickers
  • Create a new Controlled vs uncontrolled value demo for the new date picker (to match the approach of the other input-like component both on X and on the Core)
  • Remove useless props in the demos to keep them as focused as possible (do not control when not needed, don't set custom views if it has nothing to do with the feature demonstrated etc...)

I will do a follow up with all the other pickers.
You can ignore all the /legacy-pickers files, it's just a copy paste.
The /pickers files are interesting to see the actual diff between the old and the new pickers.

@flaviendelangle flaviendelangle marked this pull request as draft November 17, 2022 16:59
@flaviendelangle flaviendelangle added the docs Improvements or additions to the documentation label Nov 17, 2022
@flaviendelangle flaviendelangle self-assigned this Nov 17, 2022
@mui-bot
Copy link

mui-bot commented Nov 17, 2022

Messages
📖 Netlify deploy preview: https://deploy-preview-6902--material-ui-x.netlify.app/

These are the results for the performance tests:

Test case Unit Min Max Median Mean σ
Filter 100k rows ms 684.2 1,036.1 735.4 839.04 125.543
Sort 100k rows ms 689.1 1,275.2 689.1 954.06 210.362
Select 100k rows ms 163.7 343.1 282.3 270.08 58.671
Deselect 100k rows ms 146.2 298.2 196.5 218.38 54.697

Generated by 🚫 dangerJS against 44e45b0

setValue(newValue);
componentsProps={{
input: {
helperText: 'MM / DD / YYYY',
Copy link
Member Author

Choose a reason for hiding this comment

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

Here we have a small problem

The format is determined inside useDateField
But useDateField is called with the props resolved from the slots.

The only solution I see to keep this feature possible is to duplicate the format logic (extract https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/DateField/useDateField.ts#L25 inside a tiny hook) and call it on DateField as well)
Same for the other fields

If you have another solution, I am interested.

Copy link
Member

Choose a reason for hiding this comment

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

The original example sounds more like a hack than a feature.

Another solution could be to let dev compute the format helper themself:

adapter.getFormatHelperText(adapter.formats.keyboardDate)

Copy link
Member

Choose a reason for hiding this comment

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

What about having both ways of overriding slot props as we have for styleOverrides?

// static
input: {
  helperText: 'MM / DD / YYYY',
}
// function
input: (inputProps) => ({
  helperText: inputProps?.placeholder,
})

Copy link
Member Author

Choose a reason for hiding this comment

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

We already callbacks on the slot (when they are built using useSlotProps).
But in the params of your function, you don't have the format yet, because the function is called before useDateField which computes the format.

Copy link
Member

Choose a reason for hiding this comment

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

Thinking about this case a bit more—I don't think that we have any sort of problem here.
Static props can be used to pass static props, but in case something more advanced is needed with access to real/current props—the custom component can be passed down. 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

I feel like being able to put the format in the helper test is something quite a lot of people want.
And not being able to easily do it (without loosing the automatic format of the pickers / field) is not great.

But we can see if people complain about it, we have solutions if needed

Copy link
Member Author

Choose a reason for hiding this comment

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

olution could be to let dev compute the format helper themself:

adapter.getFormatHelperText(adapter.formats.keyboardDate)

Sorry @alexfauquette I missed your answer
Sure the way it was done was hacky, and if we want to support it, I'm in favor of passing the format in a format property, not a placeholder property.

The only issue with your proposal is that the user need to know the format.
He would loose the ability to have the picker decide the format based on the locale / the views / the meridiem etc...

Maybe that's not that big of a deal, we can wait for feedbacks.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe that's not that big of a deal, we can wait for feedbacks.

I'd say that having the option to access current localized format in one way or another for different use cases might be the expectation by users—especially ones used to using previously available placeholder prop.
Based on this assumption—it would be worthwhile to think of the easiest way to expose it.
Maybe it could be initialized in the components format props? 🤔 Now it seems to be empty if user did not provide any format...

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe it could be initialized in the components format props?

Right now the format is initialized in useDateField (or the equivalent for other fields)
Which is called after the resolution of the slots because it needs the result from this resolution
But we could either

  1. Make the format param mandatory in useDateField and apply its default value inside the component instead of the hook

  2. Apply the default value both in the component and in the hook (more duplication but people using the hook directly could still benefit from it)

ownerState?: any;
};

const BrowserInput = (props: BrowserInputProps) => {
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm in favor of removing this demo in the future, in favor of detailed sections in the Custom sub-components page.

@flaviendelangle flaviendelangle marked this pull request as ready for review November 18, 2022 12:01
@flaviendelangle flaviendelangle changed the title [docs] Create the doc of the new pickers [docs] Create the doc of the new date pickers Nov 18, 2022
@flaviendelangle flaviendelangle added the component: pickers This is the name of the generic UI component, not the React module! label Nov 18, 2022
Copy link
Member

@LukasTy LukasTy left a comment

Choose a reason for hiding this comment

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

Looks great overall. 👍
I've left a few minor comments.

One question stopping from approving it: How are we planning to approach API pages?
To me it would seem that we should basically do the same thing—keep adding new api pages with every component swap PR and possibly try to adopt similar naming strategy to them 🤔

docs/data/date-pickers/date-picker/CustomDay.tsx Outdated Show resolved Hide resolved
docs/data/date-pickers/date-picker/CustomField.tsx.preview Outdated Show resolved Hide resolved
<NextDatePicker
label="Controlled picker"
value={value}
onChange={(newValue) => setValue(newValue)}
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated question: Have we considered shortening such simple onChange handlers?

-onChange={(newValue) => setValue(newValue)}
+onChange={setValue}

Copy link
Member Author

Choose a reason for hiding this comment

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

To be honest, we very often recreate a method (same on the grid model setters) and I don't know why
Maybe we are just doing it because we always did it 😆

No problem using the shorter version for me

Copy link
Member

Choose a reason for hiding this comment

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

Maybe for pedagogical reasons. The long version explicitly says to newbies that the onChange is expecting a function which has the new value in argument. Moreover not sure every one is super familiar with setter accepting a function

Copy link
Member Author

Choose a reason for hiding this comment

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

Moreover not sure every one is super familiar with setter accepting a function

But we are not using this feature here right ?

Copy link
Member

@LukasTy LukasTy Nov 22, 2022

Choose a reason for hiding this comment

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

I do agree that longer form of creating an intermediate arrow function is a bit more explicit.
I was thinking of maybe using this way in case the function has only one argument.
Anyways, maybe we are not the ones who should promote nit-pick optimisations. It's not those arrow function are hard to re-create on every render. 🙈

setValue(newValue);
componentsProps={{
input: {
helperText: 'MM / DD / YYYY',
Copy link
Member

Choose a reason for hiding this comment

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

What about having both ways of overriding slot props as we have for styleOverrides?

// static
input: {
  helperText: 'MM / DD / YYYY',
}
// function
input: (inputProps) => ({
  helperText: inputProps?.placeholder,
})

maxDate={maxDate}
onChange={(newValue) => setValue(newValue)}
/>
<YearCalendar defaultValue={dayjs('2022-04-07')} />
Copy link
Member

Choose a reason for hiding this comment

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

Hm... This one is interesting...
By going the simplicity route we not only loose that sort of nice behaviour of any changes being reflected in the other calendars, but also not having the min and max dates on this calendar causes the calendar to render A LOT of years and also shows a bug—the view is not scrolled into the selected year. 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

but also not having the min and max dates on this calendar causes the calendar to render A LOT of years and also shows a bug—the view is not scrolled into the selected year

For me the minDate / maxDate were defined here because in the past they were mandatory (see #4814)
But if we think that they are useful in the demo, I can of course add them back.

For the bug, I thought @alexfauquette fixed it some time ago, but maybe not in this situation.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it sounds like a bug in the computation of the scroll, because the scroll is done (scrollbar is not at the top) but a bit bellow the expected time (2022) Need to investigate in another PR

image

docs/data/date-pickers/date-picker/date-picker.md Outdated Show resolved Hide resolved
@flaviendelangle
Copy link
Member Author

@LukasTy

One question stopping from approving it: How are we planning to approach API pages?

We just have to turn the includeUnstableComponents flag to true on getTypescriptProject
I created it to have the proptypes working but I wait for the doc to be ready before generating those pages 👍

@flaviendelangle
Copy link
Member Author

To me it would seem that we should basically do the same thing—keep adding new api pages with every component swap PR and possibly try to adopt similar naming strategy to them thinking

Just, those pages being generated, they will always have the name of their component.
So it will be NextDatePicker etc... for the new and DatePicker etc... for the legacy.
And then when we rename the components they will change.

But we should make sure that the demos (see #6909) are sent to the right page.

@LukasTy
Copy link
Member

LukasTy commented Nov 21, 2022

So it will be NextDatePicker etc... for the new and DatePicker etc... for the legacy.
And then when we rename the components they will change.

Yeah, I think that in the alpha/beta phase such naming inconsistency shouldn't be too much of a trouble. 👌

docs/data/date-pickers/date-picker/date-picker.md Outdated Show resolved Hide resolved
setValue(newValue);
componentsProps={{
input: {
helperText: 'MM / DD / YYYY',
Copy link
Member

Choose a reason for hiding this comment

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

Thinking about this case a bit more—I don't think that we have any sort of problem here.
Static props can be used to pass static props, but in case something more advanced is needed with access to real/current props—the custom component can be passed down. 👍

Copy link
Member

@alexfauquette alexfauquette left a comment

Choose a reason for hiding this comment

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

That's a solid starting point 👍

setValue(newValue);
componentsProps={{
input: {
helperText: 'MM / DD / YYYY',
Copy link
Member

Choose a reason for hiding this comment

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

The original example sounds more like a hack than a feature.

Another solution could be to let dev compute the format helper themself:

adapter.getFormatHelperText(adapter.formats.keyboardDate)

renderInput={(params) => <TextField {...params} />}
/>
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
<NextDatePicker defaultValue={new Date(2022, 3, 7)} />
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it will make sens to make this demo RTL when the support will be merged

Copy link
Member Author

Choose a reason for hiding this comment

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

I would be in favor of removing it once we merge #6869 (and improve the demos their with RTL of course)

<NextDatePicker
label="Controlled picker"
value={value}
onChange={(newValue) => setValue(newValue)}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe for pedagogical reasons. The long version explicitly says to newbies that the onChange is expecting a function which has the new value in argument. Moreover not sure every one is super familiar with setter accepting a function

maxDate={maxDate}
onChange={(newValue) => setValue(newValue)}
/>
<YearCalendar defaultValue={dayjs('2022-04-07')} />
Copy link
Member

Choose a reason for hiding this comment

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

Yes, it sounds like a bug in the computation of the scroll, because the scroll is done (scrollbar is not at the top) but a bit bellow the expected time (2022) Need to investigate in another PR

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: pickers This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants