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] New recipe of a read-only field #14606

Merged
merged 40 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ffda378
[docs] New recipe of a read-only field
flaviendelangle Sep 13, 2024
81099d2
Fix
flaviendelangle Sep 13, 2024
95075dd
Fix
flaviendelangle Sep 13, 2024
92da0c7
Fix
flaviendelangle Sep 13, 2024
b79b5f4
Add onOpen prop
flaviendelangle Sep 13, 2024
c7a1032
Fix types
flaviendelangle Sep 13, 2024
66574c3
Fix types
flaviendelangle Sep 13, 2024
00c6329
Fix
flaviendelangle Sep 13, 2024
cb32485
Merge branch 'master' into readonly-field
flaviendelangle Sep 17, 2024
15fbfec
Improve doc
flaviendelangle Sep 17, 2024
5768e56
Merge branch 'master' into readonly-field
flaviendelangle Sep 20, 2024
26a2135
Try to move onOpen to a context
flaviendelangle Sep 24, 2024
676aa65
Remove TS changes
flaviendelangle Sep 24, 2024
9f5f302
Fix
flaviendelangle Sep 24, 2024
9837ebf
Fix
flaviendelangle Sep 24, 2024
c9b0906
Work
flaviendelangle Sep 24, 2024
9ca0721
Move logic to usePicker
flaviendelangle Sep 24, 2024
1f185cf
Improve typing
flaviendelangle Sep 24, 2024
5f7f8e5
Work
flaviendelangle Sep 24, 2024
7bd2d32
Review Arthur
flaviendelangle Sep 30, 2024
f345cba
Merge branch 'master' into readonly-field
flaviendelangle Sep 30, 2024
299a96c
Work
flaviendelangle Sep 30, 2024
164a1de
Work
flaviendelangle Oct 1, 2024
7adf029
Fix
flaviendelangle Oct 1, 2024
77ef242
Review Lukas
flaviendelangle Oct 4, 2024
a1bc87f
[pickers] Move the DateFieldInPickerProps interface to the picker fol…
flaviendelangle Oct 4, 2024
3642e3c
Fix
flaviendelangle Oct 7, 2024
e6ea1a5
Merge branch 'master' into readonly-field
flaviendelangle Oct 7, 2024
cb91ec7
Merge
flaviendelangle Oct 7, 2024
2365f69
Merge
flaviendelangle Oct 7, 2024
07a0285
Review Lukas + JSDoc for useParsedFormat
flaviendelangle Oct 7, 2024
9d5e300
Replace toggling method with onClose and onOpen
flaviendelangle Oct 7, 2024
065dbfc
Merge branch 'master' into readonly-field
flaviendelangle Oct 7, 2024
3e976f8
Update packages/x-date-pickers/src/internals/components/PickersProvid…
flaviendelangle Oct 7, 2024
f5b950e
Update packages/x-date-pickers/src/internals/components/PickersProvid…
flaviendelangle Oct 7, 2024
80e16b4
Update packages/x-date-pickers/src/internals/hooks/usePicker/usePicke…
flaviendelangle Oct 7, 2024
2fd6a5a
Update packages/x-date-pickers/src/hooks/useParsedFormat.ts
flaviendelangle Oct 7, 2024
9443b65
Update packages/x-date-pickers/src/hooks/usePickersContext.ts
flaviendelangle Oct 7, 2024
018158d
Improve demo
flaviendelangle Oct 7, 2024
70b1bef
Fix
flaviendelangle Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from 'react';

import TextField from '@mui/material/TextField';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { useValidation, validateDate } from '@mui/x-date-pickers/validation';
import {
useSplitFieldProps,
useParsedFormat,
usePickersContext,
} from '@mui/x-date-pickers/hooks';
import { CalendarIcon } from '@mui/x-date-pickers/icons';

function ReadOnlyDateField(props) {
const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date');
const { value, timezone, format } = internalProps;
const { InputProps, slotProps, slots, ...other } = forwardedProps;

const pickersContext = usePickersContext();

const parsedFormat = useParsedFormat(internalProps);
const { hasValidationError } = useValidation({
validator: validateDate,
value,
timezone,
props: internalProps,
});

const handleTogglePicker = (event) => {
if (pickersContext.open) {
pickersContext.onClose(event);
} else {
pickersContext.onOpen(event);
}
};

return (
<TextField
{...other}
value={value == null ? '' : value.format(format)}
placeholder={parsedFormat}
InputProps={{
...InputProps,
readOnly: true,
endAdornment: <CalendarIcon color="action" />,
sx: { cursor: 'pointer', '& *': { cursor: 'inherit' } },
}}
error={hasValidationError}
onClick={handleTogglePicker}
/>
);
}

function ReadOnlyFieldDatePicker(props) {
return (
<DatePicker {...props} slots={{ ...props.slots, field: ReadOnlyDateField }} />
);
}

export default function ReadOnlyMaterialTextField() {
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<ReadOnlyFieldDatePicker />
</LocalizationProvider>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as React from 'react';
import { Dayjs } from 'dayjs';
import TextField from '@mui/material/TextField';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import {
DatePicker,
DatePickerProps,
DatePickerFieldProps,
} from '@mui/x-date-pickers/DatePicker';
import { useValidation, validateDate } from '@mui/x-date-pickers/validation';
import {
useSplitFieldProps,
useParsedFormat,
usePickersContext,
} from '@mui/x-date-pickers/hooks';
import { CalendarIcon } from '@mui/x-date-pickers/icons';

function ReadOnlyDateField(props: DatePickerFieldProps<Dayjs, false>) {
const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date');
const { value, timezone, format } = internalProps;
const { InputProps, slotProps, slots, ...other } = forwardedProps;

const pickersContext = usePickersContext();

const parsedFormat = useParsedFormat(internalProps);
const { hasValidationError } = useValidation({
validator: validateDate,
value,
timezone,
props: internalProps,
});

const handleTogglePicker = (event: React.UIEvent) => {
if (pickersContext.open) {
pickersContext.onClose(event);
} else {
pickersContext.onOpen(event);
}
};

return (
<TextField
{...other}
value={value == null ? '' : value.format(format)}
placeholder={parsedFormat}
InputProps={{
...InputProps,
readOnly: true,
endAdornment: <CalendarIcon color="action" />,
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure we should have done this. 🙈
Now the keyboard navigation and a11y is borked. 🤷

Copy link
Member Author

Choose a reason for hiding this comment

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

The Tab sequence looks good to me, it does not focus the adornment anymore

I don't have the aria label on the TextField though, should probably add that (could be a nice addition in the context)

sx: { cursor: 'pointer', '& *': { cursor: 'inherit' } },
}}
error={hasValidationError}
onClick={handleTogglePicker}
/>
);
}

function ReadOnlyFieldDatePicker(props: DatePickerProps<Dayjs>) {
return (
<DatePicker {...props} slots={{ ...props.slots, field: ReadOnlyDateField }} />
);
}

export default function ReadOnlyMaterialTextField() {
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<ReadOnlyFieldDatePicker />
</LocalizationProvider>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ReadOnlyFieldDatePicker />
11 changes: 9 additions & 2 deletions docs/data/date-pickers/custom-field/custom-field.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,17 @@ you can replace the field with an `Autocomplete` listing those dates:

{{"demo": "PickerWithAutocompleteField.js", "defaultCodeOpen": false}}

### Using a read-only `TextField`

If you want users to select a value exclusively through the views
but you still want the UI to look like a `TextField`, you can replace the field with a read-only `TextField`:

{{"demo": "custom-behavior/ReadOnlyMaterialTextField.js", "defaultCodeOpen": false}}

### Using a `Button`

If you only want to allow the user to pick a value through the views,
you can replace the field with a `Button`:
If you want users to select a value exclusively through the views
and you don't want the UI to look like a `TextField`, you can replace the field with a `Button`:

{{"demo": "PickerWithButtonField.js", "defaultCodeOpen": false}}

Expand Down
47 changes: 0 additions & 47 deletions docs/data/date-pickers/experimentation/CustomField.js

This file was deleted.

47 changes: 0 additions & 47 deletions docs/data/date-pickers/experimentation/CustomField.tsx

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions docs/data/date-pickers/experimentation/experimentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,3 @@ productId: x-date-pickers
# Date and Time Pickers experimentation

<p class="description">Demos not accessible through the navbar of the doc</p>

## Custom field

{{"demo": "CustomField.js"}}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react';
import useSlotProps from '@mui/utils/useSlotProps';
import { useLicenseVerifier } from '@mui/x-license';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { PickersLayout, PickersLayoutSlotProps } from '@mui/x-date-pickers/PickersLayout';
import {
executeInTheNextEventLoopTick,
Expand All @@ -11,6 +10,7 @@ import {
ExportedBaseToolbarProps,
DateOrTimeViewWithMeridiem,
ExportedBaseTabsProps,
PickersProvider,
} from '@mui/x-date-pickers/internals';
import { PickerValidDate, FieldRef, InferError } from '@mui/x-date-pickers/models';
import {
Expand Down Expand Up @@ -93,6 +93,7 @@ export const useDesktopRangePicker = <
renderCurrentView,
shouldRestoreFocus,
fieldProps: pickerFieldProps,
contextValue,
} = usePicker<
DateRange<TDate>,
TDate,
Expand Down Expand Up @@ -209,7 +210,7 @@ export const useDesktopRangePicker = <
const Layout = slots?.layout ?? PickersLayout;

const renderPicker = () => (
<LocalizationProvider localeText={localeText}>
<PickersProvider contextValue={contextValue} localeText={localeText}>
<Field {...enrichedFieldProps} />
<PickersPopper
role="tooltip"
Expand All @@ -233,7 +234,7 @@ export const useDesktopRangePicker = <
{renderCurrentView()}
</Layout>
</PickersPopper>
</LocalizationProvider>
</PickersProvider>
);

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as React from 'react';
import useSlotProps from '@mui/utils/useSlotProps';
import { useLicenseVerifier } from '@mui/x-license';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { PickersLayout, PickersLayoutSlotProps } from '@mui/x-date-pickers/PickersLayout';
import {
usePicker,
PickersModalDialog,
ExportedBaseToolbarProps,
DateOrTimeViewWithMeridiem,
ExportedBaseTabsProps,
PickersProvider,
} from '@mui/x-date-pickers/internals';
import { usePickersTranslations } from '@mui/x-date-pickers/hooks';
import { PickerValidDate, FieldRef, InferError } from '@mui/x-date-pickers/models';
Expand Down Expand Up @@ -88,6 +88,7 @@ export const useMobileRangePicker = <
layoutProps,
renderCurrentView,
fieldProps: pickerFieldProps,
contextValue,
} = usePicker<
DateRange<TDate>,
TDate,
Expand Down Expand Up @@ -214,7 +215,7 @@ export const useMobileRangePicker = <
};

const renderPicker = () => (
<LocalizationProvider localeText={localeText}>
<PickersProvider contextValue={contextValue} localeText={localeText}>
<Field {...enrichedFieldProps} />
<PickersModalDialog {...actions} open={open} slots={slots} slotProps={slotProps}>
<Layout
Expand All @@ -226,7 +227,7 @@ export const useMobileRangePicker = <
{renderCurrentView()}
</Layout>
</PickersModalDialog>
</LocalizationProvider>
</PickersProvider>
);

return {
Expand Down
4 changes: 4 additions & 0 deletions packages/x-date-pickers/src/hooks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ export type {
export { usePickersTranslations } from './usePickersTranslations';

export { useSplitFieldProps } from './useSplitFieldProps';

export { useParsedFormat } from './useParsedFormat';

export { usePickersContext } from './usePickersContext';
Loading