-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[pickers] New unstable field components #5504
Changes from all commits
a27e983
bfbc627
f65cfe5
8333afd
85e5af2
51ab705
03ffed4
7afab04
dc58f12
7d2a453
24b1a6c
d9994a0
5e025e7
be952ae
d1a1ebc
d93acf0
bc2c9cf
db5c78e
2a2e865
599bdc1
9d3a723
ffcb865
12b3cd1
8e4d719
c03591b
848c857
589da3c
663ab1b
66012cb
99e53b9
aae69cf
2784dcb
701bbfd
37b08ba
10d11b9
a305285
0b01e4b
99c649d
aa77af9
58de7f6
6259b53
622c826
f0d35c7
21216fc
b59fa00
9a52389
c302aea
c11d662
b4ab68c
8a27cc4
d27ffb4
bdb30ef
c0c8fc2
9d71ed9
6c7fb7e
7a62420
e9ed42f
7b7cc0a
209409f
436d3aa
f288a3f
37614b8
842cf5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import * as React from 'react'; | ||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||
import { Unstable_DateField as DateField } from '@mui/x-date-pickers/DateField'; | ||
|
||
export default function BasicDateField() { | ||
return ( | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<DateField label="Basic date field" /> | ||
</LocalizationProvider> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,12 @@ | ||||||||||
import * as React from 'react'; | ||||||||||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||||||||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||||||||||
import { Unstable_DateField as DateField } from '@mui/x-date-pickers/DateField'; | ||||||||||
|
||||||||||
export default function BasicDateField() { | ||||||||||
return ( | ||||||||||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||||||||||
<DateField label="Basic date field" /> | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. End-users need to click twice to be able to select the year. Compare: Screen.Recording.2022-08-24.at.22.33.21.movhttps://deploy-preview-5504--material-ui-x.netlify.app/x/react-date-pickers/date-field/#basic-usage With (better): Screen.Recording.2022-08-24.at.22.35.41.movhttps://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is a known issue The problem is that I select all sections on focus. And on a fully selected input, I can't find the cursor position of the click, the cursor just moves to the beginning of the input. One solution would be to delay the selection caused by the focus and to skip it if a click selection has been done in the meanwhile. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I would dive into this. I think it's where the problem starts: mui-x/packages/x-date-pickers/src/internals/hooks/useField/useField.ts Lines 319 to 322 in 8db0bfa
Maybe instead of a "select all" on focus, the browser does it automatically when focusing an input with a Tab, we could look at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a PR to improve this behavior #5901 |
||||||||||
</LocalizationProvider> | ||||||||||
); | ||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<DateField label="Basic date field" /> | ||
</LocalizationProvider> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<DateField | ||
value={value} | ||
onChange={(newValue) => { | ||
setValue(newValue); | ||
}} | ||
variant="standard" | ||
/> | ||
</LocalizationProvider> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import * as React from 'react'; | ||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||
import { Unstable_DateField as DateField } from '@mui/x-date-pickers/DateField'; | ||
import Stack from '@mui/material/Stack'; | ||
|
||
export default function CustomDateFormat() { | ||
const [value, setValue] = React.useState(new Date()); | ||
|
||
return ( | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<Stack spacing={2} sx={(theme) => ({ width: theme.spacing(48) })}> | ||
<DateField | ||
label="Dash separator" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
format="dd-MM-yyyy" | ||
/> | ||
<DateField | ||
label="Dash and white space separator" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
format="dd / MM / yyyy" | ||
/> | ||
<DateField | ||
label="Full letter month" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
format="dd MMMM yyyy" | ||
/> | ||
<DateField | ||
label="Date and time format" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
format="Pp" | ||
/> | ||
<DateField | ||
label="Time format" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
format="p" | ||
/> | ||
</Stack> | ||
</LocalizationProvider> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,46 @@ | ||||||
import * as React from 'react'; | ||||||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||||||
import { Unstable_DateField as DateField } from '@mui/x-date-pickers/DateField'; | ||||||
import Stack from '@mui/material/Stack'; | ||||||
|
||||||
export default function CustomDateFormat() { | ||||||
const [value, setValue] = React.useState<Date | null>(new Date()); | ||||||
|
||||||
return ( | ||||||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||||||
<Stack spacing={2} sx={(theme) => ({ width: theme.spacing(48) })}> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might make the demo easier to scan:
Suggested change
|
||||||
<DateField | ||||||
label="Dash separator" | ||||||
value={value} | ||||||
onChange={(newValue) => setValue(newValue)} | ||||||
format="dd-MM-yyyy" | ||||||
/> | ||||||
<DateField | ||||||
label="Dash and white space separator" | ||||||
value={value} | ||||||
onChange={(newValue) => setValue(newValue)} | ||||||
format="dd / MM / yyyy" | ||||||
/> | ||||||
<DateField | ||||||
label="Full letter month" | ||||||
value={value} | ||||||
onChange={(newValue) => setValue(newValue)} | ||||||
format="dd MMMM yyyy" | ||||||
/> | ||||||
<DateField | ||||||
label="Date and time format" | ||||||
value={value} | ||||||
onChange={(newValue) => setValue(newValue)} | ||||||
format="Pp" | ||||||
/> | ||||||
<DateField | ||||||
label="Time format" | ||||||
value={value} | ||||||
onChange={(newValue) => setValue(newValue)} | ||||||
format="p" | ||||||
/> | ||||||
</Stack> | ||||||
</LocalizationProvider> | ||||||
); | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import * as React from 'react'; | ||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||
import { Unstable_DateField as DateField } from '@mui/x-date-pickers/DateField'; | ||
import Stack from '@mui/material/Stack'; | ||
import IconButton from '@mui/material/IconButton'; | ||
import CancelIcon from '@mui/icons-material/Close'; | ||
|
||
export default function CustomInputProps() { | ||
const [value, setValue] = React.useState(new Date()); | ||
|
||
return ( | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<Stack spacing={2} sx={(theme) => ({ width: theme.spacing(48) })}> | ||
<DateField | ||
label="Custom variant" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
variant="filled" | ||
/> | ||
<DateField | ||
label="Disabled" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
disabled | ||
/> | ||
<DateField | ||
label="Read only" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
readOnly | ||
/> | ||
<DateField | ||
label="Clearable" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
InputProps={{ | ||
endAdornment: ( | ||
<IconButton size="small" onClick={() => setValue(null)}> | ||
<CancelIcon /> | ||
</IconButton> | ||
), | ||
}} | ||
/> | ||
</Stack> | ||
</LocalizationProvider> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import * as React from 'react'; | ||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||
import { Unstable_DateField as DateField } from '@mui/x-date-pickers/DateField'; | ||
import Stack from '@mui/material/Stack'; | ||
import IconButton from '@mui/material/IconButton'; | ||
import CancelIcon from '@mui/icons-material/Close'; | ||
|
||
export default function CustomInputProps() { | ||
const [value, setValue] = React.useState<Date | null>(new Date()); | ||
|
||
return ( | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<Stack spacing={2} sx={(theme) => ({ width: theme.spacing(48) })}> | ||
<DateField | ||
label="Custom variant" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
variant="filled" | ||
/> | ||
<DateField | ||
label="Disabled" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
disabled | ||
/> | ||
<DateField | ||
label="Read only" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
readOnly | ||
/> | ||
<DateField | ||
label="Clearable" | ||
value={value} | ||
onChange={(newValue) => setValue(newValue)} | ||
InputProps={{ | ||
endAdornment: ( | ||
<IconButton size="small" onClick={() => setValue(null)}> | ||
<CancelIcon /> | ||
</IconButton> | ||
), | ||
}} | ||
/> | ||
</Stack> | ||
</LocalizationProvider> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as React from 'react'; | ||
import { CssVarsProvider } from '@mui/joy/styles'; | ||
import Stack from '@mui/material/Stack'; | ||
import FormControlLabel from '@mui/material/FormControlLabel'; | ||
import FormLabel from '@mui/joy/FormLabel'; | ||
import JoyTextField from '@mui/joy/TextField'; | ||
import InputUnstyled from '@mui/base/InputUnstyled'; | ||
import { LocalizationProvider } from '@mui/x-date-pickers'; | ||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; | ||
import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField'; | ||
|
||
const JoyDateField = (props) => { | ||
const { inputRef, inputProps } = useDateField(props); | ||
|
||
return ( | ||
<JoyTextField | ||
{...inputProps} | ||
componentsProps={{ input: { componentsProps: { input: { ref: inputRef } } } }} | ||
/> | ||
); | ||
}; | ||
|
||
const UnstyledDateField = (props) => { | ||
const { inputRef, inputProps } = useDateField(props); | ||
|
||
return ( | ||
<InputUnstyled | ||
{...inputProps} | ||
componentsProps={{ input: { ref: inputRef, style: { width: '100%' } } }} | ||
/> | ||
); | ||
}; | ||
|
||
const BrowserInputDateField = (props) => { | ||
const { inputRef, inputProps } = useDateField(props); | ||
|
||
return <input {...inputProps} ref={inputRef} />; | ||
}; | ||
|
||
export default function CustomUIDateField() { | ||
const [value, setValue] = React.useState(new Date()); | ||
|
||
const handleChange = (newValue) => setValue(newValue); | ||
|
||
return ( | ||
<CssVarsProvider> | ||
<LocalizationProvider dateAdapter={AdapterDateFns}> | ||
<Stack spacing={2}> | ||
<JoyDateField | ||
label="Using @mui/joy TextField" | ||
value={value} | ||
onChange={handleChange} | ||
/> | ||
<FormControlLabel | ||
label={<FormLabel>Using unstyled input</FormLabel>} | ||
control={<UnstyledDateField value={value} onChange={handleChange} />} | ||
labelPlacement="top" | ||
sx={{ alignItems: 'stretch' }} | ||
/> | ||
<FormControlLabel | ||
label={<FormLabel>Using browser input</FormLabel>} | ||
control={<BrowserInputDateField value={value} onChange={handleChange} />} | ||
labelPlacement="top" | ||
sx={{ alignItems: 'stretch' }} | ||
/> | ||
</Stack> | ||
</LocalizationProvider> | ||
</CssVarsProvider> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we allow 00?
Maybe we should reset the field when this happens
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know for this one
In Spectrum, if I press
0
it does not write anything, even if the end format will be01
Press
0
=> still render the placeholder (totally ignores the event I think)Press
1
=> renders01
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be more precise, I was thinking of what would happen when leaving the selection. A native browser seems to turn 00 to 01 when unselecting.