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] Improving DX of masked input #4759

Closed alexfauquette closed 2 years ago

alexfauquette commented 2 years ago

The Month and Year picker

Current behavior

For now, the masked input is managed by 4 props:

This feature is important for keyboard interaction because, without a mask, it's easy to miss a space or use a / instead of a - which will lead to an invalid date, so we discourage using disableMaskedInput={true}

Those parameters are strongly linked together. Modifying inputFormat without mask does not make sens, and disableMaskedInput should be used only if it's impossible to provide a mask for the wanted inputFormat

This leads to the following weird behavior for developers: The default props for the date picker depend on the views provided:

// Only Year
mask: '____'
inputFormat: utils.formats.year

// Only Year and Month
disableMaskedInput: true
inputFormat: utils.formats.monthAndYear

// default
mask: '__/__/____'
inputFormat: utils.formats.keyboardDate

The main problem here is the "Year and Month" case, because it set by default disableMaskedInput to true

Proposed Solution

(A) Modify the format

Set a format MM/YYYY such as proposed in #4664

(B) Drop month and year

This feature set magically the inputFormat when developers only care about the month and the year. But it seems to do more damage than it helps, so we could remove the special case of month and years

(C) Group related variables

We could regroup all the variables in one object:

inputFormatManager={{ 
    mask: '____ __', 
    format: 'yyyy MMM',
    disableMask: false,
    acceptRegex: /\dap/gi, 
}}

The defaultized value would be as follow. The idea is to keep default acceptRegex because it's rare to have to change it, and add ap for AM/PM is easy to forget.

const defaultizedInputFormatManager = props.inputFormatManager ? {
  acceptRegex: defaultInputFormatManager.acceptRegexp,
  ...props.inputFormatManager
} : defaultInputFormatManager

(D) Have a special behavior when mask/format is provided

Same as option (C) but without grouping everything in a JS object. The default value would be computed as follow:

// Only Year and Month
disableMaskedInput: (mask || inputFormat) ? false : true
inputFormat:  inputFormat ?? utils.formats.monthAndYear

I put other pain points below because they can have an influence on how we resolve the one above

The locale management #4756

Current behavior

The mask is set by default, lives in Europe or America with __/__/____ date mask. Spoiler: it's not the case, some locales set the year first leading to a mask ____/__/__

Proposed modification

remove the mask and use the inputFormat to compute it.

Managing more masks

Current behavior

The masked input support format with fix length and only digits. This excludes formats such as 1/2/2025 (because the number of digits can be 1 or 2 for months and days) or Jun 2012 because it uses letters (even if number of letters is fix).

Objective

Support mask for those, with mask such as [1or2digitsDay]/[1or2digitsMonth]/[year] Not sure if it is possible

alexfauquette commented 2 years ago

What is done by others

alexfauquette commented 2 years ago
alexfauquette commented 2 years ago

Move to #5504