mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.52k stars 1.31k forks source link

[RFC] Nomenclature of the components exported by `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` #4484

Closed eps1lon closed 1 year ago

eps1lon commented 3 years ago

TL;DR: Changes to the public API are

  1. Static*Picker will become *PickerView (naming open).
  2. DayPicker will become CalendarPicker
  3. DayPicker view date will become day
  4. Drop allowKeyboardControl
  5. components implementing <input type={...} /> will end in Input instead of Picker e.g. TimePicker will become TimeInput

For a short summary of the terminology used see https://gist.github.com/eps1lon/97cbf619cffd30f12deece8d72b0c941

variants

Right now we ship every picker in 4 different variants:

  1. static e.g. StaticDatePicker
  2. mobile e.g. MobileDatePicker
  3. desktop e.g. DesktopDatePicker
  4. responsive e.g. DatePicker

Static variants are the underyling picker without the textbox(s). It isn't static at all since it takes user input, validates it etc. Mobile and desktop are for their respective environment and "responsive" just switches dynamically between "mobile" and "desktop" based on a media query.

None of these components share a common entry point in their implementation (anymore). However, it seems to me that all of these compose naturally into:

  1. Responsive
    1. Desktop
      1. desktop textbox
      2. desktop popup
        1. popup content
    2. Mobile
      1. mobile textbox
      2. mobile popup
        1. popup content

The "popup content" is what will become the *PickerView component (or *PickerGrid, *PickerDialogContainer). The naming is still open since it's somewhat arbitrary what we consider the "view". It's just as arbitrary as "static" but it seems to me that "static" is even more misleading.

The "responsive" component will then just be a thin wrapper around the desktop and tooltip variants that doesn't need much customization. Instead, we should encourage custom wrappers especially for lazy loading etc.

timing related naming

cursive formatting refers to natural language which isn't clearly defined (especially considering different languages which differ in what is a date or time). monospace formatting refers to technical terms that are well defined.

What we call a date is not the same as a JavaScript Date. Instead we follow the naming of HTML input types where we split a point in time (a moment) into date and time (ISO 8601 equally applies). date is further split into year, month and day. time is split into hour, minute and second.

allowKeyboardControl

Dropping allowKeyboardControl is more of a drive-by improvement. This is effectively a prop that makes the component strictly worse (since it excludes people relying on keyboard input). I suspect the prop was motivated by the fact that the original implementation registered all keyboard handlers globally when we can use keydown handlers on the specific components instead.

Picker vs Input

This change is unlikely to land in the public interface. But it might make sense to use that terminology internally.

Right now we use picker as a generic term for all components that were part of @material-ui/pickers. But it's unclear what this term means considering we have ClockPicker and TimePicker (which is just ClockPicker + textbox).

Let's entertain the idea of renaming DatePicker to DateInput and CalendarPicker to DatePicker. DateInput composes a textbox + DatePicker . *Picker referring to the UI that you choose from pre-defined values (like the listbox in a combobox). Seems like the best solution for cleaning up the terminology. But I'm afraid causing more confusion for people being used to DatePicker.

I would propose

-TimePicker
+TimeInput
-DatePicker
+DateInput
-DateTimePicker
+DateTimeInput
-DateRangePicker
+DateRangeInput

/cc @mui-org/maintainers

oliviertassinari commented 3 years ago

@eps1lon Great issue and an interesting topic! A couple of thoughts that I have maturing since I started diving into the pickers with @dmtrKovalenko last year.

Based on the above, one option we could consider (and that seems compatible with the first proposal) is:

  1. Responsive *Picker
    1. Desktop first (mobile too with a few CSS tweaks) *PickerDesktop
      1. textbox
      2. desktop popup
        1. desktop popup content *PickerDesktopView
    2. Mobile *PickerMobile
      1. readonly textbox
      2. mobile dialog
        1. mobile dialog content *PickerMobileView
eps1lon commented 3 years ago

I think that the solution we come up with should take this constraint into account. I think that developers should be able to cherry-pick mobile-only or desktop-only tradeoffs.

This issue is not about creating a single component for mobile/desktop nor that we should reduce the difference. Aside from allowKeyboardControl no public API/behavior is supposed to change with these changes.

Third. The signals I have seen so far would suggest that "Static" components have a non-negligible market share. They are important.

Sure. This issue is not trying to dispute that.

Based on the above, one option we could consider (and that seems compatible with the first proposal) is:

Apart from the textbox I don't see any difference. I forgot to mention different textboxes which I encorporated in the initial proposal.

oliviertassinari commented 3 years ago

@eps1lon Agree with you. I was trying to take a step back and try to present the context in which the RFC happens (how I understand it). The intent was to explore how much the proposal fits with the other constraints. It seems all good.

Regarding the difference, I have only tried to further precise it. 1. I have made a proposal for the name at each level. 2. I have clarified that the mobile view and desktop view (popup container) are different components.

eps1lon commented 3 years ago

Update the issue with notes about the terminology we use. Came to the realization that we should rename DayPicker to CalendarPicker.

I'm also leaning towards replacing the Picker in DatePicker, TimePicker, DateTimePicker and DateRangePicker with Input. This would distinguish them from e.g. ClockPicker, emphasize that you don't just "pick" but also have an "input" (i.e. textbox) and match the existing HTML terms.

I have clarified that the mobile view and desktop view (popup container) are different components.

That was already part of the original issue.

oliviertassinari commented 3 years ago

@eps1lon Looks great.

eps1lon commented 3 years ago

Some more thoughts about DatePicker -> DateInput renaming:

What about we rename the current DatePicker to DateInput and CalendarPicker to DatePicker. DateInput composes a textbox + DatePicker . *Picker referring to the UI that you choose from pre-defined values (like the listbox in a combobox). Seems like the best solution for cleaning up the terminology. But I'm afraid causing more confusion for people being used to DatePicker.

oliviertassinari commented 3 years ago

I personally find DateInput more accurate. It also seems that the developer intent is to search for "date picker" and expect a date input in a very large proportion. I would personally +1 for not doing it, saving us time in a renaming that isn't an obvious net improvement for developers.

From a benchmark perspective, it just discovered a tradeoff that I didn't even consider before. Kendo UI has a date input component that is only a textbox https://www.telerik.com/kendo-react-ui/dateinput/

dimitropoulos commented 3 years ago

for whatever it's worth: I added DatePicker to the react-ui-roundup if you wanna see a bunch side by side. https://github.com/dimitropoulos/react-ui-roundup#DatePicker

Only one of them uses DateInput, but I gotta say I agree that DateInput is a better name. The picker itself can still be DatePicker, but I don't love how so many frameworks conflate input vs. picker.

dimitropoulos commented 3 years ago

Although, I will mention, that some of these libraries have both DatePicker and DateInput, e.g. blueprint https://blueprintjs.com/docs/#datetime/dateinput, and some really only have the picker https://quasar.dev/vue-components/date and the input part is not really baked in.

You can see them all if you click "OPEN ALL IN NEW TABS" on https://react-ui-roundup.dimitrimitropoulos.com/#DatePicker

TrejGun commented 3 years ago

Hi guys! any plans to implement DateTimeRangeInput ?

oliviertassinari commented 3 years ago

Regarding the topic on "Picker vs. Input", in hindsight, I think that:

Screenshot 2021-04-17 at 14 14 54
alippai commented 3 years ago

Does this issue cover https://github.com/mui-org/material-ui-pickers/issues/1526 ?

eps1lon commented 3 years ago

Does this issue cover mui-org/material-ui-pickers#1526 ?

I'm afraid not. This issue is mainly about terminology and composition not about component behavior.

While we're at it: Just wanted to leave the suggestion of @m4theushw in yesterdays meeting about naming the components DateField. Personally, I find this the best candidate but I don't think it's realistic to move away from the current terminology.

flaviendelangle commented 2 years ago

@alexfauquette @joserodolfofreitas that one will be interesting to keep track off

flaviendelangle commented 2 years ago

I am restarting this discussion to be able to have something concrete in the coming week and to implement the new nomenclature before the end of the alpha.

Current behavior

Side note: I am using the term view as all the panels that focuses on a single date section. For most date section, 1 view = 1 panel visible on screen (we list all the months of the year in a single panel, we show all the hours of the day in a single panel etc...). But for the DayPicker (to be renamed) component, we have a small inconsistency because sometime we say the DayPicker is a single view and sometime we say each month in the DayPicker is a view.

My understanding is that we have 4 families of components

  1. The components with only an HTML input (current DateField and DateRangeField)

  2. The components with an HTML input and a view displayed in a modal or a tooltip (current DatePicker, MobileDatePicker, DesktopDatePicker, DateRangePicker, ...)

  3. The components with only ONE view rendered directly on the page (current DayPicker, MonthPicker, YearPicker)

  4. The components with several views rendered directly on the page (current StaticDatePicker, StaticTimePicker, ...)

Proposal

The list below covers more than just the components exposed by our package. It also covers some slots naming because we can't decide how to name our components without deciding which names are already taken for another concept in the slots.

Input

Component used to render an HTML input component

Examples:

// Set the input rendered in the `DateField` component
// Only one `OutlinedInput` will be rendered
<DateField components={{ input: OutlinedInput }} />

// Set the input rendered in the `MultiInputDateRangeField` component
// Two `FilledInput` will be rendered, one for the start date and one for the end date
<MultiInputDateRangeField components={{ input: FilledInput }} />

// Set the input rendered in the field of the `DatePicker` component
// Only one `OutlinedInput` will be rendered
<DatePicker components={{ input: OutlinedInput }} />

Field

Component used to edit a date with the keyboard

Examples:

// Standalone usage of a field component
<DateField />

// Set the field rendered in the `DateRangePicker` component
<DateRangePicker components={{ field: MultiInputDateRangeField }} />
<DateRangePicker components={{ field: SingleInputDateRangeField }} />

// Set both the field and the input rendered in the `DateRangePicker` component
<DateRangePicker
  components={{
    field: MultiInputDateRangeField,
    input: OutlinedInput,
  }}
 />

Competitors naming for the same concept:

View

Component used to edit one or several date section (day, month, year, hour, minutes, seconds) with the mouse

Examples:

// Standalone usage of views
<MonthView /> // current `MonthPicker`, to edit month
<YearView /> // current `YearPicker`, to edit year
<DayView /> // current `DayPicker`, to edit day
<CalendarView /> // current `CalendarPicker`, to edit day / month / year

// Set the list of views rendered in a `DatePicker` component
<DatePicker views={['month', 'day']} />

Competitors naming for the same concept:

Picker

Component used to edit a date with both the keyboard and the mouse Is the combination of a field and one or several views

Examples:

// Standalone usage of responsive picker components
<DatePicker />
<DateRangePicker />
<DateTimePicker />
<DateRangeTimePicker />

// Standalone usage of mobile / desktop picker components
<MobileDateRangeTimePicker />
<DesktopDatePicker />

Competitors naming for the same concept:

Conclusion

One things that is clear is that no nomenclature is being used by all of our competitors. We are all using the same terms for various things. My main goal here is to be consistent across our components (MonthPicker should clearly not have the same suffix as DatePicker for instance)

oliviertassinari commented 2 years ago

@flaviendelangle sounds great.

One note, on this demo

<DateField components={{ input: OutlinedInput }} />

I think that for many teams they will want to use:

<DateField components={{ input: TextField }} />

Which I think is still coherent if we argue that a DateField is a specialized version of a TextField.

LukasTy commented 2 years ago

My main goal here is to be consistent across our components (MonthPicker should clearly not have the same suffix as DatePicker for instance)

Could you elaborate more on this point? 🤔 IMHO, I'd argue that the current naming of those components represents their intent more correctly than View. MonthView - I might expect to see a visual representation of months in a year or days in a month given such name. MonthPicker - I would expect a component with ability to pick/choose a particular month

flaviendelangle commented 2 years ago

I think that for many teams they will want to use:

<DateField components={{ input: TextField }} />

The exact behavior of the input slot is something I would like to discuss, but maybe in a standalone issue. Should it have a default value ? If so maybe not the TextField due to the bundle size but it should clearly be compatible with the TextField out of the box. Should it remain a render prop like today ? Etc...


My main goal here is to be consistent across our components (MonthPicker should clearly not have the same suffix as DatePicker for instance)

Could you elaborate more on this point?

Currently, the Picker term refers to either:

For me there is an inconsistency there. And by reading the name of the component, we should know if there is an input and a modal, or if the content is directly on your screen.

We can of course discuss this naming, the most important part for me being the differentiation between the two.

For example, we could add the Static prefix to all of them (StaticMonthPicker). But I don't have the feeling the Static describes the actual behavior either.

LukasTy commented 2 years ago

For example, we could add the Static prefix to all of them (StaticMonthPicker).

Oh, I see your point. That is a problem we could solve by tweaking the naming and you did give a very good example of using Static as we already use it for other pickers without input.

But I don't have the feeling the Static describes the actual behavior either.

Indeed, there are a few of ways we could go:

  1. come up with a better substitute for Static as per @eps1lon suggestion (also adding this name to the components in question)
  2. add Static to YearPicker, MonthPicker, CalendarPicker to align with existing Static<Type>Picker
  3. suffix all static components with View (i.e.: YearPicker -> YearPickerView, StaticDatePicker -> DatePickerView)
  4. rename the components, which work with input (DatePicker -> DateInput) as per @eps1lon suggestion

I've listed the options in my personal preference order. I'm not a fan of the last option just because of the possible confusion caused to developers. One possible alternatives to Static I could think of is Fixed. 🤔

flaviendelangle commented 2 years ago

I was thinking about the Inline prefix. @alexfauquette if you have some idea.

alexfauquette commented 2 years ago

About the current renaming

From What I understood from the previous discussion, the current modification proposal is the next one.

Some naming do not change. The components with an input are ending with Field

v5 name v6 name
DateTimePicker same
TimePicker same
DateRangePicker same
DatePicker same
DesktopDatePicker same
DesktopDateRangePicker same
DesktopDateTimePicker same
DesktopTimePicker same
MobileDatePicker same
MobileDateRangePicker same
MobileDateTimePicker same
MobileTimePicker same

The components that are referring to a views=['day', 'year'] end with View for consistency

v5 name v6 name
MonthPicker MonthView
YearPicker YearView
DateRangePickerDay MultiMonthDayView (tricky one)
PickersDay DayView

For Clock and Calendar I have a doubt. Should we emphasize that it's an aggregation of different views. Interface si conflicting with the notion of interface of typescript

v5 name v6 name
ClockPicker ClockView or ClockInterface
CalendarPicker CalendarView or CalendarInterface

Same question for statics

v5 name v6 name
StaticTimePicker TimePickerView or TimePickerInterface
StaticDateRangePicker DateRangePickerView or DateRangePickerInterface
StaticDateTimePicker DateTimePickerView or DateTimePickerInterface
StaticDatePicker DatePickerView or DatePickerInterface

We also export CalendarPickerSkeleton and PickerStaticWrapper be nobody care and they are not a problem

The new components

From a developer point of view (I'm not sure about how complex it's to implement) I would expect DateField to behave like TextField. So you no not pass TextField to its slots, but the subcomponents

// Simple customization
<DateField label="..." placeholder="..." components={{ 
    Input: OutlinedInput,
    InputLabel: ..
    FormHelperText: ... 
}} />

@flaviendelangle I don't get for wichi component do you want to pass Inline For components without views?

flaviendelangle commented 2 years ago

@flaviendelangle I don't get for wichi component do you want to pass Inline For components without views?

The debate is about those components:

The components that are referring to a views=['day', 'year'] end with View for consistency

@LukasTy is not a fan of the View suffix, and I agree that it's worth taking some time to think about it.


We also export CalendarPickerSkeleton and PickerStaticWrapper be nobody care and they are not a problem

Yes for those two I don't really understand the use case yet.


From a developer point of view (I'm not sure about how complex it's to implement) I would expect DateField to behave like TextField.

The problem being that on a date range field, we can have 2 TextField rendered. In a perfect world, I would have a suffix for DateField & co that is not Field but something never used.

joserodolfofreitas commented 2 years ago

In a perfect world, I would have a suffix for DateField & co that is not Field but something never used.

I think "Field" makes sense, although, as you said is the closest but not ideal.

Personally, I see everything as an input, you can input the date with a mouse (using a picker) or with a keyboard (using a field). But I agree that input is usually related to the most basic component of the hierarchy.

The naming that would make the most sense to me would be:

Example: <DateRange pickers: {['month', 'year']} components:{{ field: MultiInputDateRangeField, monthPicker: MyMonthPicker }} />

flaviendelangle commented 2 years ago

So in your nomenclature, if I understand correctly we would have:

joserodolfofreitas commented 2 years ago

Yes, that would be the most intuitive for me, and we wouldn't need to use the generic "View".

The DatePicker => Date (that one is problematic because Date is also the name of the JS interface)

I was inspired by retool. But I see your point, thought when it's written as a component doesn't seem that bad.

<Date pickers: {['month', 'year']} components:{{ monthPicker: MyMonthPicker }} />

flaviendelangle commented 2 years ago

https://codesandbox.io/s/throbbing-forest-n7skkj?file=/src/App.js

The problem is name collision

flaviendelangle commented 2 years ago

Follow yesterday's meeting, we decided to wait before applying the changes in order to gather more information about how these Static / View components would be used.

My latest proposal was to use the "Calendar" prefix and to remove any prefix from Clock

This leaves us with the naming of the Static, but I feel that once we will have a headless version ready, those wrappers will loose a lot of there interest.