From b303694f2626de095352c21121dc88ca76f85899 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 26 Nov 2024 14:39:26 +0100 Subject: [PATCH 01/46] [RFC] WIP - Proposal for the future DX of the Date and Time Pickers --- docs/data/date-pickers/rfc/calendar.md | 28 +++ docs/data/date-pickers/rfc/field.md | 171 ++++++++++++++++++ docs/data/date-pickers/rfc/picker.md | 28 +++ docs/data/pages.ts | 9 + .../x/react-date-pickers/rfc/calendar.js | 7 + docs/pages/x/react-date-pickers/rfc/field.js | 7 + docs/pages/x/react-date-pickers/rfc/picker.js | 7 + 7 files changed, 257 insertions(+) create mode 100644 docs/data/date-pickers/rfc/calendar.md create mode 100644 docs/data/date-pickers/rfc/field.md create mode 100644 docs/data/date-pickers/rfc/picker.md create mode 100644 docs/pages/x/react-date-pickers/rfc/calendar.js create mode 100644 docs/pages/x/react-date-pickers/rfc/field.js create mode 100644 docs/pages/x/react-date-pickers/rfc/picker.js diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md new file mode 100644 index 0000000000000..ac4cfa1aa5ab7 --- /dev/null +++ b/docs/data/date-pickers/rfc/calendar.md @@ -0,0 +1,28 @@ +--- +productId: x-date-pickers +title: DX - Calendar +--- + +# Fields + +

This page describes how people can use date views with Material UI and how they can build custom date views.

+ +:::success +This page extends the initial proposal made in [#15598](https://github.com/mui/mui-x/issues/15598) +::: + +## With Material UI + +### Basic usage + +TODO + +### Override part of the UI + +TODO + +## Without Material UI + +### Basic usage + +TODO diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md new file mode 100644 index 0000000000000..7dbe01fd1cc0a --- /dev/null +++ b/docs/data/date-pickers/rfc/field.md @@ -0,0 +1,171 @@ +--- +productId: x-date-pickers +title: DX - Fields +--- + +# Fields + +

This page describes how people can use field with Material UI and how they can build custom fields while keeping the built-in editing behavior.

+ +:::success +This page extends the initial proposal made in [this Github comment](https://github.com/mui/mui-x/issues/14496#issuecomment-2348917294) +::: + +## With Material UI + +### Basic usage + +The `@mui/x-date-pickers` package exposes one field per value type. +Those fields are self-contained components (meaning they don't use composition). + +Here is a basic example of a ``: + +```tsx +import { DateField } from '@mui/x-date-pickers/DateField'; + +; +``` + +The behavior is the same for all the other fields: + +```tsx +; + +; + +; + +; + +; +``` + +:::success +I'm proposing to rename `` into `` for concision when the single input range fields will become the default and when the multi input range fields will be gathered into a single component. +::: + +### Multi input range field + +The `@mui/x-date-pickers` package also exposes a component to create multi input range fields as follow: + +```tsx +import { useDateRangeManager } from '@mui/x-date-pickers/managers'; +import { MultiInputRangeField } from '@mui/x-date-pickers/MultiInputRangeField'; + +function MultiInputDateTimeRangeField(props: MultiInputDateTimeRangeFieldProps) { + const manager = useDateTimeRangeManager(props); + + return ; +} +``` + +:::success +I have a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505) +::: + +## Without Material UI + +### Basic usage + +```tsx +import { useDateManager } from '@base-ui/x-date-pickers/managers'; +import { PickerField } from '@base-ui/x-date-pickers/PickerField'; + +// Misses some parts like the clear button for now +function CustomDateField(props) { + const manager = useDateManager(); + + return ( + + + {(section) => ( + + + + + + )} + + + ); +} +``` + +The field can then either be: + +1. Used as standalone: + + ```tsx + + ``` + +2. Used inside a self-contained `` component from `@mui/x-date-pickers/DatePicker`: + + ```tsx + import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + + ; + ``` + + :::success + The concept of slots does not fit this use-case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so I'm using the tools we currently have. + ::: + +3. Used inside a composable `Picker.*` component from `@base-ui/x-date-pickers/Picker` + + ```tsx + import { useDateManager } from '@base-ui/x-date-pickers/managers'; + import { Picker } from '@base-ui/x-date-pickers/Picker'; + + function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + + + {/** See the pickers documentation for more details */} + + + ); + } + ``` + + People could of course also inline their field if they want: + + ```tsx + import { useDateManager } from '@base-ui/x-date-pickers/managers'; + import { Picker } from '@base-ui/x-date-pickers/Picker'; + + function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + + {/** See demo above */} + + + {/** See the pickers documentation for more details */} + + + ); + } + ``` + + :::warning + I'm wondering if we could make `manager` optional on `` and by default use the one exposed by the `` component in a React context. + That way people could create a single field component for all their pickers, as long as they don't want to use them as standalone. + + If we go that way, then the `` component would no longer receive the `manager` prop in the component above: + + ```tsx + + {/** See demo above */} + + {/** See the pickers documentation for more details */} + + + ``` + + ::: diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md new file mode 100644 index 0000000000000..e78b13123f36b --- /dev/null +++ b/docs/data/date-pickers/rfc/picker.md @@ -0,0 +1,28 @@ +--- +productId: x-date-pickers +title: DX - Pickers +--- + +# Fields + +

This page describes how people can use picker with Material UI and how they can build custom pickers.

+ +:::success +This page extends the initial proposal made in [#14718](https://github.com/mui/mui-x/issues/14718) +::: + +## With Material UI + +### Basic usage + +TODO + +### Override part of the UI + +TODO + +## Without Material UI + +### Basic usage + +TODO diff --git a/docs/data/pages.ts b/docs/data/pages.ts index 7da1e4479c8e0..e5b6cee1194df 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -265,6 +265,15 @@ const pages: MuiPage[] = [ { pathname: '/x/react-date-pickers/getting-started' }, { pathname: '/x/react-date-pickers/base-concepts' }, { pathname: '/x/react-date-pickers/faq', title: 'FAQs' }, + { + pathname: '/x/react-date-pickers/rfc', + title: 'Composition and unstyled DX', + children: [ + { pathname: '/x/react-date-pickers/rfc/field', title: 'Field' }, + { pathname: '/x/react-date-pickers/rfc/calendar', title: 'Calendar' }, + { pathname: '/x/react-date-pickers/rfc/picker', title: 'Picker' }, + ], + }, { pathname: '/x/react-date-pickers-components', subheader: 'Components', diff --git a/docs/pages/x/react-date-pickers/rfc/calendar.js b/docs/pages/x/react-date-pickers/rfc/calendar.js new file mode 100644 index 0000000000000..79ffed51ba95a --- /dev/null +++ b/docs/pages/x/react-date-pickers/rfc/calendar.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/rfc/calendar.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/x/react-date-pickers/rfc/field.js b/docs/pages/x/react-date-pickers/rfc/field.js new file mode 100644 index 0000000000000..c305b80976aa6 --- /dev/null +++ b/docs/pages/x/react-date-pickers/rfc/field.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/rfc/field.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/x/react-date-pickers/rfc/picker.js b/docs/pages/x/react-date-pickers/rfc/picker.js new file mode 100644 index 0000000000000..4e937b03b8b75 --- /dev/null +++ b/docs/pages/x/react-date-pickers/rfc/picker.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/rfc/picker.md?muiMarkdown'; + +export default function Page() { + return ; +} From 014bcfb20267030bef5d2bc60eaabc4800292192 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 26 Nov 2024 15:18:58 +0100 Subject: [PATCH 02/46] Work --- docs/data/date-pickers/rfc/calendar.md | 169 +++++++++++- docs/data/date-pickers/rfc/field.md | 346 +++++++++++++++++++------ docs/data/date-pickers/rfc/picker.md | 6 +- 3 files changed, 434 insertions(+), 87 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index ac4cfa1aa5ab7..a5ec1a977ca3c 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -5,23 +5,182 @@ title: DX - Calendar # Fields -

This page describes how people can use date views with Material UI and how they can build custom date views.

+

This page describes how people can use date views with Material UI and how they can build custom date views.

:::success This page extends the initial proposal made in [#15598](https://github.com/mui/mui-x/issues/15598) ::: -## With Material UI +## With Material UI ### Basic usage -TODO +The `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` packages expose four calendar components: +Those components are self-contained components (meaning they don't use composition). + +- `` + + Allows users to edit a date (its day in the month, its month and its year). + + ```tsx + import { DateCalendar } from '@mui/x-date-pickers/DateCalendar />'; + + ; + ``` + +- `` + + Allows users to edit the month of a date. + + ```tsx + import { MonthCalendar } from '@mui/x-date-pickers/MonthCalendar />'; + + ; + ``` + +- `` + + Allows users to edit the year of a date. + + ```tsx + import { YearCalendar } from '@mui/x-date-pickers/YearCalendar />'; + + ; + ``` + +- `` + + Allows users to edit a range of dates (for now it only handles the day in the month, but could handle the month and the year in the future). + + ```tsx + import { DateRangeCalendar } from '@mui/x-date-pickers/DateRangeCalendar />'; + + ; + ``` ### Override part of the UI -TODO +You can use slots to override part of the UI in self-contained components: + +```tsx + +``` + +:::success +The concept of slots does not fit this use case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so this RFC uses the tools currently available. +::: + +The `` component can be built in a few different ways: + +1. From scratch: + + This is mostly viable for components that don't interact a lot with the picker state. For example, if someone wants to build a custom header for their calendar that just displays the current month, they could do it from scratch: + + ```tsx + import { useCalendarContext } from '@base-ui/x-date-pickers/Calendar'; + + function CustomCalendarHeader() { + const { currentMonth } = useCalendarContext(); + + return
{currentMonth.format('MMMM YYYY')}
; + } + ``` + + This is not the recommended way, but nothing prevents it. + + :::success + The `calendarHeader` slot does not receive `currentMonth` as a prop but instead access it using `useCalendarContext()`. + That way, this components can be composed more freely, it now only has to be mounted inside ``. + ::: + +2. Using the `Calendar.*` primitives exposed by `@base-ui/x-date-pickers/Calendar`: + + If the user wants to totally own the styling of this part of the UI (because he wants to build something really different from Material UI), he can use `Calendar.*` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: + + ```tsx + import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + + function CustomCalendarHeader() { + return ( + + + + ); + } + ``` + +3. Using the `PickerCalendarHeader*` components exposed by `@mui/x-date-pickers/PickerCalendarHeader`: + + ```tsx + import { + PickersCalendarHeaderRoot, + PickersCalendarHeaderLabel, + } from '@mui/x-date-pickers/PickersCalendarHeader'; + + function CustomCalendarHeader() { + return ( + + + + + + ); + } + ``` + + :::success + The components like `` would be built on top of their `@base-ui/x-date-pickers/Calendar` counterparts and would be used to build ``. The packages expose several version but they don't have logic duplication. + Internally, the code would look something like that: + + ```tsx + import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + + export const PickerCalendarHeaderRoot = styled(Calendar.Header.Root)({ + display: 'flex', + alignItems: 'center', + marginTop: 12, + marginBottom: 4, + paddingLeft: 24, + paddingRight: 12, + }); + + export const PickerCalendarHeaderLabel = styled(Calendar.Header.Label)({ + /** ... */ + }); + + // This component is purely presentational and not present in `@base-ui/x-date-pickers/Calendar'. + export const PickerCalendarHeaderLabelContainer = styled('div')({ + /** ... */ + }); + + export const PickerCalendarHeader = (props) => { + const { format, ...other } = props; + return ( + + + + + + ); + }; + ``` + + ::: + + :::success + This one is unclear. + Maybe those composable but styled components should only be exposed for parts of the UI where the Material UI implementation has some complexity and people want to be able to use composition to customize it without going fully unstyled for this part of the UI. + + And if those composable but styled components are something worth doing, then they need to have a coherent export strategy. + Should it be: + + 1. `` like it would be today + 2. `` to match the exports from `@base-ui/x-date-pickers` + 3. Something else? + + ::: -## Without Material UI +## Without Material UI ### Basic usage diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index 7dbe01fd1cc0a..fead81acff475 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -5,18 +5,18 @@ title: DX - Fields # Fields -

This page describes how people can use field with Material UI and how they can build custom fields while keeping the built-in editing behavior.

+

This page describes how people can use field with Material UI and how they can build custom fields while keeping the built-in editing behavior.

:::success This page extends the initial proposal made in [this Github comment](https://github.com/mui/mui-x/issues/14496#issuecomment-2348917294) ::: -## With Material UI +## Basic standalone usage -### Basic usage +### With Material UI The `@mui/x-date-pickers` package exposes one field per value type. -Those fields are self-contained components (meaning they don't use composition). +Those components are self-contained components (meaning they don't use composition). Here is a basic example of a ``: @@ -41,10 +41,129 @@ The behavior is the same for all the other fields: ``` :::success -I'm proposing to rename `` into `` for concision when the single input range fields will become the default and when the multi input range fields will be gathered into a single component. +This RFC proposes to rename `` into `` for concision when the single input range fields become the default and when the multi input range fields are gathered into a single component. ::: -### Multi input range field +:::success +All these self-contained components are built on top of `PickerField`. +An intermediary internal component is needed to only create the component once and then have each field pass its `manager` to it. +::: + +### Without Material UI + +```tsx +import { useDateManager } from '@base-ui/x-date-pickers/managers'; +import { PickerField } from '@base-ui/x-date-pickers/PickerField'; + +function CustomDateField(props) { + const manager = useDateManager(); + + return ( + + + {(section) => ( + + + + + + )} + + + ); +} +``` + +The field can then be rendered just like the Material UI fields: + +```tsx + +``` + +## Basic usage inside a picker + +### With Material UI + +:::success +No DX change here compared to today +::: + +```tsx +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +; +``` + +:::success +The concept of slots does not fit this use case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so this RFC uses the tools currently available. +::: + +### Without Material UI + +#### Inside a picker from `@mui/x-date-pickers` + +Even if most applications with a custom field probably want to remove `@mui/material` entirely, using these custom fields inside a self contained picker component from `@mui/x-date-pickers/DatePicker` is totally doable. +This can be useful for application using Material UI but with some specific needs for the fields or to allow for a gradual migration away from Material UI. + +```tsx +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +; +``` + +:::success +The concept of slots does not fit this use case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so this RFC uses the tools currently available. +::: + +#### Inside an unstyled picker + +The custom field can also be used inside a picker built with the composable `Picker.*` component from `@base-ui/x-date-pickers/Picker`: + +```tsx +import { useDateManager } from '@base-ui/x-date-pickers/managers'; +import { Picker } from '@base-ui/x-date-pickers/Picker'; + +function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + + + {/** See picker documentation */} + + + ); +} +``` + +People could of course also inline their field if they want: + +```tsx +import { useDateManager } from '@base-ui/x-date-pickers/managers'; +import { Picker } from '@base-ui/x-date-pickers/Picker'; + +function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + {/** See demo above */} + + {/** See picker documentation */} + + + ); +} +``` + +:::success +When doing that, the `Picker.Field.Root` doesn't have to receive props like `minDate` because they are accessed using `usePickerContext` (or maybe a dedicated `usePickerValidationContext`). This makes composition viable between the picker and the field (same for the views). +::: + +## Basic usage (multi input picker) + +### With Material UI The `@mui/x-date-pickers` package also exposes a component to create multi input range fields as follow: @@ -59,113 +178,182 @@ function MultiInputDateTimeRangeField(props: MultiInputDateTimeRangeFieldProps) } ``` +When used inside a picker, `` can be passed directly and uses the `manager` exposed by `usePickerContext`: + +```tsx + +``` + :::success -I have a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505) +I have a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505). ::: -## Without Material UI +### Without Material UI -### Basic usage +:::warning +This is not planned for now. +`Picker.*` could contain some additional components that would be the building blocks for `` but it does not seem to be the priority for now. +::: + +## Clearable field + +### With Material UI + +:::success +No DX change here compared to today +::: + +```tsx + + + +``` + +### Without Material UI + +People can use the `` component to add a button to clear the value: ```tsx import { useDateManager } from '@base-ui/x-date-pickers/managers'; import { PickerField } from '@base-ui/x-date-pickers/PickerField'; -// Misses some parts like the clear button for now function CustomDateField(props) { const manager = useDateManager(); return ( - - {(section) => ( - - - - - - )} - + {/** See demo above */} + + + ); } ``` -The field can then either be: +## Anatomy of `Picker.*` + +### `` + +Top level component that wraps the other components. +It would expend `Field.Root` from `@base-ui-components/react/Field`. + +#### Props + +- `manager`: `PickerManager` - **required for standalone fields** + + See [#15395](https://github.com/mui/mui-x/issues/15395) for context. + +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. + + Same typing and behavior as today. + +- **Validation props**: list based on the `manager` prop + + For `useDateManager()` it would be `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. + + Same typing and behavior as today. + +- **Form props**: `disabled`, `readOnly`. + + Same typing and behavior as today. + +- `format`: `string` (default value applied by the `manager`). + +- `formatDensity`: `'dense' | 'spacious'`, default: `'dense'`. + +- `shouldRespectLeadingZeros`: `boolean`, default: `false`. + +- `selectedSections`: `FieldSelectedSections` + +- `onSelectedSectionsChange`: `(newValue: FieldSelectedSections) => void` + +- `unstableFieldRef`: `React.Ref>` + + This one may not be needed. If its only used for internal purpose, it can probably be made internal (the picker would pass a ref using a private context instead of a prop). + + Keeping it unstable makes removing it easy. + +- `autoFocus`: `boolean` + +:::success +All the props that the picker can pass to the field (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that it can be used inside a picker built with composition. + +That way, users only have to pass the props specific to the field to ``: + +```tsx + + + {/** See demo above */} + + + {/** See picker documentation */} + + +``` + +::: + +### `` + +It would expend `Field.Control` from `@base-ui-components/react/Field`. + +It expects a function as it's children, which is called for every section to render: + +```tsx +{(section) =>
{section.value}
}
+``` + +It also renders a hidden input which contains the stringified value and can be used for form submission and testing. + +#### Props + +- `children`: `(section: InferFieldSection) => React.ReactNode` + +### `` -1. Used as standalone: +Renders a single section (for instance the year of the hour of the current value). - ```tsx - - ``` +#### Props -2. Used inside a self-contained `` component from `@mui/x-date-pickers/DatePicker`: +- `children`: `React.ReactNode` +- `section`: `InferFieldSection` (can be `FieldSection` or `FieldRangeSection`) - **required**. - ```tsx - import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +### `` - ; - ``` +Renders the content of a single section. - :::success - The concept of slots does not fit this use-case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so I'm using the tools we currently have. - ::: +#### Props -3. Used inside a composable `Picker.*` component from `@base-ui/x-date-pickers/Picker` +- nothing? - ```tsx - import { useDateManager } from '@base-ui/x-date-pickers/managers'; - import { Picker } from '@base-ui/x-date-pickers/Picker'; +### `` + +Renders the separator to display before or after the current section. + +```tsx + +``` - function CustomDatePicker(props) { - const manager = useDateManager(); +#### Props - return ( - - - - {/** See the pickers documentation for more details */} - - - ); - } - ``` +- `position`: `'before' | 'after'` - **required**. - People could of course also inline their field if they want: +### `` - ```tsx - import { useDateManager } from '@base-ui/x-date-pickers/managers'; - import { Picker } from '@base-ui/x-date-pickers/Picker'; +Renders the button to clear the value of the field. - function CustomDatePicker(props) { - const manager = useDateManager(); +#### Props - return ( - - - {/** See demo above */} - - - {/** See the pickers documentation for more details */} - - - ); - } - ``` +- `children`: `React.ReactNode` - :::warning - I'm wondering if we could make `manager` optional on `` and by default use the one exposed by the `` component in a React context. - That way people could create a single field component for all their pickers, as long as they don't want to use them as standalone. +- `onClear`: `React.MouseEventHandler` - If we go that way, then the `` component would no longer receive the `manager` prop in the component above: + :::success + The new DX is a good opportunity to discuss the behavior of this prop. + The behavior should either be: - ```tsx - - {/** See demo above */} - - {/** See the pickers documentation for more details */} - - - ``` + 1. `onClear` is defined on ``. It is also fired when doing Ctrl + A and then Backspace. + 2. `onClear` is defined on `` (or not defined at all and people just use `onClick`). It is only fired when clicking on this button. - ::: + ::: diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index e78b13123f36b..69f86d473e9e7 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -5,13 +5,13 @@ title: DX - Pickers # Fields -

This page describes how people can use picker with Material UI and how they can build custom pickers.

+

This page describes how people can use picker with Material UI and how they can build custom pickers.

:::success This page extends the initial proposal made in [#14718](https://github.com/mui/mui-x/issues/14718) ::: -## With Material UI +## With Material UI ### Basic usage @@ -21,7 +21,7 @@ TODO TODO -## Without Material UI +## Without Material UI ### Basic usage From e0a5abd3f7d066c4386b793bfd13003e72ebbf98 Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 12:41:02 +0100 Subject: [PATCH 03/46] Work on Calendar doc page --- docs/data/date-pickers/rfc/calendar.md | 510 +++++++++++++++++++++++-- docs/data/date-pickers/rfc/field.md | 18 +- 2 files changed, 487 insertions(+), 41 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index a5ec1a977ca3c..9e4d1f9526f29 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -3,7 +3,7 @@ productId: x-date-pickers title: DX - Calendar --- -# Fields +# Calendar

This page describes how people can use date views with Material UI and how they can build custom date views.

@@ -11,54 +11,299 @@ title: DX - Calendar This page extends the initial proposal made in [#15598](https://github.com/mui/mui-x/issues/15598) ::: -## With Material UI +## Usage with only days -### Basic usage +### With Material UI -The `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` packages expose four calendar components: -Those components are self-contained components (meaning they don't use composition). +:::success +No DX change here compared to today +::: + +The user can use the `` and limit the views: -- `` +```tsx +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; - Allows users to edit a date (its day in the month, its month and its year). +; +``` - ```tsx - import { DateCalendar } from '@mui/x-date-pickers/DateCalendar />'; +### Without Material UI - ; - ``` +The user can use the `Calendar.Days.*` components to create a grid of days and the `Calendar.Header.*` to create a header to navigate across the months: -- `` +```tsx +import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + + + + + ◀ + + + + + + + {({ days }) => days.map((day) => )} + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => days.map((day) => )} + + )) + } + + +; +``` + +## Usage with only months + +### With Material UI + +:::success +No DX change here compared to today +::: - Allows users to edit the month of a date. +The user can use the `` component: - ```tsx - import { MonthCalendar } from '@mui/x-date-pickers/MonthCalendar />'; +```tsx +import { MonthCalendar } from '@mui/x-date-pickers/MonthCalendar'; - ; - ``` + +``` -- `` +:::success +The big limitation here is that the `` component does not have a header to navigate through the years. +Once the `Calendar.*` unstyled component is ready, the `` should probably be reworked to improve this (or removed in favor of always using ``). +::: - Allows users to edit the year of a date. +### Without Material UI - ```tsx - import { YearCalendar } from '@mui/x-date-pickers/YearCalendar />'; +The user can use the `Calendar.Months.*` components to create a grid of months and the `Calendar.Header.*` to create a header to navigate across the years: - ; - ``` +```tsx +import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + + + + + + + + + {(monthValue) => } + +; +``` -- `` +## Usage with only years - Allows users to edit a range of dates (for now it only handles the day in the month, but could handle the month and the year in the future). +### With Material UI - ```tsx - import { DateRangeCalendar } from '@mui/x-date-pickers/DateRangeCalendar />'; +:::success +No DX change here compared to today +::: - ; - ``` +The user can use the `` component: -### Override part of the UI +```tsx +import { YearCalendar } from '@mui/x-date-pickers/YearCalendar'; + + +``` + +:::success +The big limitation here is that the `` component does not have a header to navigate through the years. +Once the `Calendar.*` unstyled component is ready, the `` should probably be reworked to improve this (or removed in favor of always using ``). +::: + +### Without Material UI + +The user can use the `Calendar.Years.*` components to create a grid of years: + +```tsx +import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + + + + {(yearValue) => } + +; +``` + +## Day + month + years + +### With Material UI + +:::success +No DX change here compared to today +::: + +The user can use the `` component and add the month view: + +```tsx +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; + + +``` + +:::success +When MD3 is supported, the default views of `` should probably be `['year', 'month', 'day']` +::: + +### Without Material UI + +```tsx + + + {({ view }) => ( + +
+ + ◀ + + + + + + ▶ + +
+
+ + ◀ + + + + + + ▶ + +
+
+ )} +
+ + + + {({ days }) => days.map((day) => )} + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => days.map((day) => )} + + )) + } + + + + + + {(monthValue) => } + + + + + {(yearValue) => } + + +
+``` + +:::success +The header above tries to replicate the behavior of a MD3 Date Picker. +Today's `` header would look as follow: + +```tsx + + {({ view }) => ( + + + {view === 'year' ? '▲' : '▼'} + + +
+ + ◀ + + + ▶ + +
+
+
+ )} +
+``` + +But the current behavior is not great, once you are on the `year` view, there is no way to go back to the `day` view without picking a value. +::: + +## Display week number + +### With Material UI + +:::success +No DX change here compared to today +::: + +The user can use the `` with the `displayWeekNumber` prop: + +```tsx +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; + +; +``` + +### Without Material UI + +The user can use the `` and `` components to add a column to the grid: + +```tsx + + + {({ days }) => ( + + # + {days.map((day) => ( + + ))} + + )} + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => ( + + + {days.map((day) => ( + + ))} + + )} + + )) + } + + +``` + +## Override part of the UI + +### With Material UI You can use slots to override part of the UI in self-contained components: @@ -180,8 +425,209 @@ The `` component can be built in a few different ways: ::: -## Without Material UI +## Anatomy of `Calendar.*` + +### `Calendar.Root` + +Top level component that wraps the other components. + +#### Props + +- Extends `React.HTMLAttributes` + +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. + + Same typing and behavior as today. + +- **Validation props**: `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. + + Same typing and behavior as today. + +- **Form props**: `disabled`, `readOnly`. + + Same typing and behavior as today. + +- `autoFocus`: `boolean` + +### `Calendar.MatchView` + +Utility component to conditionally render some components based on the current view. +Doesn't render a DOM node (it does not have a `render` prop either). + +```tsx + + Only rendered when the view is "day" + + + + Only rendered when the view is "day" or "month" + +``` + +#### Props + +- `match`: `TView | readonly TView[]` - **required**. +- `children`: `React.ReactNode` + +### `Calendar.Header.Root` + +Top level component for the `Calendar.Header.*` components. + +#### Props + +- Extends `React.HTMLAttributes` + +### `Calendar.Header.Label` + +Renders the header label for the current value based on the provided format. + +#### Props + +- Extends `React.HTMLAttributes` +- `format`: `string`, default: `${utils.formats.month} ${utils.formats.year}` + +### `Calendar.Navigation.GoToMonth` + +Renders a button to go to the previous or the next month. +It does not modify the value it only navigates to the target month. + +- Extends `React.HTMLAttributes` +- `target`: `'previous' | 'next'` +- `children`: `React.ReactNode` + +:::success +TODO: Clarify the behavior when multiple calendars are rendered at once. +::: + +### `Calendar.Navigation.GoToYear` + +Renders a button to go to the previous or the next month. +It does not modify the value it only navigates to the target year. + +- Extends `React.HTMLAttributes` +- `target`: `'previous' | 'next'` +- `children`: `React.ReactNode` + +:::success +TODO: Clarify the behavior when multiple calendars are rendered at once. +::: + +### `Calendar.Navigation.SetView` + +Renders a button to set the current visible view. + +- Extends `React.HTMLAttributes` +- `target`: `TView` +- `children`: `React.ReactNode` + +### `Calendar.Days.Root` + +Top level component for the `Calendar.Days.*` components + +#### Props + +- `fixedWeekNumber`: `number` + +### `Calendar.Days.Header` + +Renders the header of the day grid. + +It expects a function as its children, which has the list of days as a parameter: + +```tsx + + {({ days }) => days.map((day) => )} + +``` + +#### Props + +- Extends `React.HTMLAttributes` +- `children`: `(params: { days: PickerValidDate[] }) => React.ReactNode` + +### `Calendar.Days.HeaderCell` + +Renders the header of a day in the week. + +#### Props + +- Extends `React.HTMLAttributes` +- `value`: `PickerValidDate` - **required**. + +### `Calendar.Days.WeekNumberHeaderCell` + +Renders the header of the week number column. + +#### Props + +- Extends `React.HTMLAttributes` + +### `Calendar.Days.Content` + +Renders the content all the days in a month (it is the DOM element that should contain all the weeks). + +It expects a function as its children, which has the list of weeks to render as a parameter: + +```tsx + + {({ weeks }) => weeks.map((week) => )} + +``` + +:::success +Maybe it should be named ``. +::: + +#### Props + +- Extends `React.HTMLAttributes` +- `children`: `(params: { weeks: PickerValidDate[] }) => React.ReactNode` + +### `Calendar.Days.WeekLine` + +Renders the content all the days in a week. + +It expects a function as its children, which has the list of days to render and the week number as a parameter: + +```tsx + + {({ days }) => days.map((day) => )} + +``` + +#### Props + +- Extends `React.HTMLAttributes` +- `value`: `{ value: PickerValidDate }` - **required** +- `children`: `(params: { days: PickerValidDate[], week: PickerValidDate }) => React.ReactNode` + +### `Calendar.Days.Cell` + +Renders the cell for a single day. + +#### Props + +- Extends `React.HTMLAttributes` +- `value`: `PickerValidDate` - **required** + +### `Calendar.Days.WeekNumberCell` + +Renders the number of the current week. + +- Extends `React.HTMLAttributes` + +### `Calendar.Months.Root` + +TODO + +### `Calendar.Months.Cell` + +TODO + +### `Calendar.Years.Root` + +TODO -### Basic usage +### `Calendar.Years.Cell` TODO diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index fead81acff475..a4cc3a8594e13 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -1,9 +1,9 @@ --- productId: x-date-pickers -title: DX - Fields +title: DX - Field --- -# Fields +# Field

This page describes how people can use field with Material UI and how they can build custom fields while keeping the built-in editing behavior.

@@ -233,7 +233,7 @@ function CustomDateField(props) { ## Anatomy of `Picker.*` -### `` +### `PickerField.Root` Top level component that wraps the other components. It would expend `Field.Root` from `@base-ui-components/react/Field`. @@ -294,11 +294,11 @@ That way, users only have to pass the props specific to the field to `` +### `PickerField.Content` It would expend `Field.Control` from `@base-ui-components/react/Field`. -It expects a function as it's children, which is called for every section to render: +It expects a function as its children, which is called for every section to render: ```tsx {(section) =>
{section.value}
}
@@ -310,7 +310,7 @@ It also renders a hidden input which contains the stringified value and can be u - `children`: `(section: InferFieldSection) => React.ReactNode` -### `` +### `PickerField.Section` Renders a single section (for instance the year of the hour of the current value). @@ -319,7 +319,7 @@ Renders a single section (for instance the year of the hour of the current value - `children`: `React.ReactNode` - `section`: `InferFieldSection` (can be `FieldSection` or `FieldRangeSection`) - **required**. -### `` +### `PickerField.SectionContent` Renders the content of a single section. @@ -327,7 +327,7 @@ Renders the content of a single section. - nothing? -### `` +### `PickerField.SectionSeparator` Renders the separator to display before or after the current section. @@ -339,7 +339,7 @@ Renders the separator to display before or after the current section. - `position`: `'before' | 'after'` - **required**. -### `` +### `PickerField.Clear` Renders the button to clear the value of the field. From 57abe01fe31788f0b81e62ff02cfbacb4725914a Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 12:51:27 +0100 Subject: [PATCH 04/46] Work on Calendar doc page --- docs/data/date-pickers/rfc/calendar.md | 61 +++++++++++++++++++++----- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 9e4d1f9526f29..fd6d49e96464e 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -94,7 +94,9 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar';
- {(monthValue) => } + {({ months }) => + months.map((month) => ) + }
; ``` @@ -129,7 +131,7 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - {(yearValue) => } + {({ years }) => years.map((year) => )} ; ``` @@ -210,12 +212,14 @@ When MD3 is supported, the default views of `` should probably b - {(monthValue) => } + {({ months }) => + months.map((month) => ) + } - {(yearValue) => } + {({ years }) => years.map((year) => )} @@ -405,8 +409,7 @@ The `` component can be built in a few different ways: - - ); + WeekNumberCell }; ``` @@ -522,7 +525,7 @@ Renders a button to set the current visible view. ### `Calendar.Days.Root` -Top level component for the `Calendar.Days.*` components +Top level component for the `Calendar.Days.*` components. #### Props @@ -618,16 +621,52 @@ Renders the number of the current week. ### `Calendar.Months.Root` -TODO +Top level component for the `Calendar.Months.*` components. + +It expects a function as its children, which has the list of the months as a parameter: + +```tsx + + {({ months }) => months.map((month) => )} + +``` + +#### Props + +- Extends `React.HTMLAttributes` +- `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` ### `Calendar.Months.Cell` -TODO +Renders the cell for a single month. + +#### Props + +- Extends `React.HTMLAttributes` +- `value`: `PickerValidDate` - **required**. ### `Calendar.Years.Root` -TODO +Top level component for the `Calendar.Years.*` components. + +It expects a function as its children, which has the list of the years as a parameter: + +```tsx + + {({ years }) => years.map((year) => )} + +``` + +#### Props + +- Extends `React.HTMLAttributes` +- `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` ### `Calendar.Years.Cell` -TODO +Renders the cell for a single year. + +#### Props + +- Extends `React.HTMLAttributes` +- `value`: `PickerValidDate` - **required**. From 496f03d08ccb177e1f514bf00c827f0f773ff3be Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 13:34:20 +0100 Subject: [PATCH 05/46] Work on Calendar doc page --- docs/data/date-pickers/rfc/calendar.md | 50 ++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index fd6d49e96464e..e998e765b6fb1 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -49,9 +49,9 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => )} - + )) } @@ -202,9 +202,9 @@ When MD3 is supported, the default views of `` should probably b {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => )} - + )) } @@ -289,7 +289,7 @@ The user can use the `` and ` {({ weeks }) => weeks.map((week) => ( - + {({ days }) => ( @@ -298,7 +298,7 @@ The user can use the `` and ` )} - + )) } @@ -573,7 +573,7 @@ It expects a function as its children, which has the list of weeks to render as ```tsx - {({ weeks }) => weeks.map((week) => )} + {({ weeks }) => weeks.map((week) => )} ``` @@ -586,16 +586,16 @@ Maybe it should be named ``. - Extends `React.HTMLAttributes` - `children`: `(params: { weeks: PickerValidDate[] }) => React.ReactNode` -### `Calendar.Days.WeekLine` +### `Calendar.Days.WeekRow` Renders the content all the days in a week. It expects a function as its children, which has the list of days to render and the week number as a parameter: ```tsx - + {({ days }) => days.map((day) => )} - + ``` #### Props @@ -635,6 +635,30 @@ It expects a function as its children, which has the list of the months as a par - Extends `React.HTMLAttributes` - `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` +- `cellsPerRow`: `number`, default: `1` + + :::success + The `cellsPerRow` prop is needed to have a working keyboard navigation. + But it's not a great DX, especially if the user wants to vary the amount of items per row based on the viewport width. + + The navigation behavior should looks something like this: + + - if `cellsPerRow === 1`: + + - ArrowLeft do nothing + - ArrowRight do nothing + - ArrowTop go to the month rendered above (should handle `display: flex-reverse`) + - ArrowBottom go to month rendered below (should handle `display: flex-reverse`) + + - if `cellsPerRow > 1`: + - ArrowLeft go the month rendered on the left, and if none should go to the outer-right month of the line rendered above (should handle `display: flex-reverse`) + - ArrowRight go the month rendered on the right, and if none should go to the outer-left month of the line rendered below (should handle `display: flex-reverse`) + - ArrowTop go to the month rendered above (should handle `display: flex-reverse`) + - ArrowBottom go to month rendered below (should handle `display: flex-reverse`) + + And with no assumption on the layout, this seems to be a real challenge to achieve. + The MVP could probably not contain any keyboard navigation. + ::: ### `Calendar.Months.Cell` @@ -661,6 +685,12 @@ It expects a function as its children, which has the list of the years as a para - Extends `React.HTMLAttributes` - `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` +- `cellsPerRow`: `number`, default: `1` + + :::success + The `cellsPerRow` prop is needed to have a working keyboard navigation. + See the equivalent prop in `Calendar.Months.Root` for more details. + ::: ### `Calendar.Years.Cell` From b2836400f0a5f70069f3c641c919002693cc5009 Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 13:37:51 +0100 Subject: [PATCH 06/46] Work on Calendar doc page --- docs/data/date-pickers/rfc/calendar.md | 22 +++++++++++++++++++--- docs/data/date-pickers/rfc/field.md | 15 +++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index e998e765b6fb1..6768144f24b26 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -470,6 +470,7 @@ Doesn't render a DOM node (it does not have a `render` prop either). #### Props - `match`: `TView | readonly TView[]` - **required**. + - `children`: `React.ReactNode` ### `Calendar.Header.Root` @@ -487,6 +488,7 @@ Renders the header label for the current value based on the provided format. #### Props - Extends `React.HTMLAttributes` + - `format`: `string`, default: `${utils.formats.month} ${utils.formats.year}` ### `Calendar.Navigation.GoToMonth` @@ -495,8 +497,8 @@ Renders a button to go to the previous or the next month. It does not modify the value it only navigates to the target month. - Extends `React.HTMLAttributes` + - `target`: `'previous' | 'next'` -- `children`: `React.ReactNode` :::success TODO: Clarify the behavior when multiple calendars are rendered at once. @@ -508,8 +510,8 @@ Renders a button to go to the previous or the next month. It does not modify the value it only navigates to the target year. - Extends `React.HTMLAttributes` + - `target`: `'previous' | 'next'` -- `children`: `React.ReactNode` :::success TODO: Clarify the behavior when multiple calendars are rendered at once. @@ -520,8 +522,8 @@ TODO: Clarify the behavior when multiple calendars are rendered at once. Renders a button to set the current visible view. - Extends `React.HTMLAttributes` + - `target`: `TView` -- `children`: `React.ReactNode` ### `Calendar.Days.Root` @@ -529,6 +531,8 @@ Top level component for the `Calendar.Days.*` components. #### Props +- Extends `React.HTMLAttributes` + - `fixedWeekNumber`: `number` ### `Calendar.Days.Header` @@ -546,6 +550,7 @@ It expects a function as its children, which has the list of days as a parameter #### Props - Extends `React.HTMLAttributes` + - `children`: `(params: { days: PickerValidDate[] }) => React.ReactNode` ### `Calendar.Days.HeaderCell` @@ -555,6 +560,7 @@ Renders the header of a day in the week. #### Props - Extends `React.HTMLAttributes` + - `value`: `PickerValidDate` - **required**. ### `Calendar.Days.WeekNumberHeaderCell` @@ -584,6 +590,7 @@ Maybe it should be named ``. #### Props - Extends `React.HTMLAttributes` + - `children`: `(params: { weeks: PickerValidDate[] }) => React.ReactNode` ### `Calendar.Days.WeekRow` @@ -601,7 +608,9 @@ It expects a function as its children, which has the list of days to render and #### Props - Extends `React.HTMLAttributes` + - `value`: `{ value: PickerValidDate }` - **required** + - `children`: `(params: { days: PickerValidDate[], week: PickerValidDate }) => React.ReactNode` ### `Calendar.Days.Cell` @@ -611,6 +620,7 @@ Renders the cell for a single day. #### Props - Extends `React.HTMLAttributes` + - `value`: `PickerValidDate` - **required** ### `Calendar.Days.WeekNumberCell` @@ -634,7 +644,9 @@ It expects a function as its children, which has the list of the months as a par #### Props - Extends `React.HTMLAttributes` + - `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` + - `cellsPerRow`: `number`, default: `1` :::success @@ -667,6 +679,7 @@ Renders the cell for a single month. #### Props - Extends `React.HTMLAttributes` + - `value`: `PickerValidDate` - **required**. ### `Calendar.Years.Root` @@ -684,7 +697,9 @@ It expects a function as its children, which has the list of the years as a para #### Props - Extends `React.HTMLAttributes` + - `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` + - `cellsPerRow`: `number`, default: `1` :::success @@ -699,4 +714,5 @@ Renders the cell for a single year. #### Props - Extends `React.HTMLAttributes` + - `value`: `PickerValidDate` - **required**. diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index a4cc3a8594e13..30e29187f2fa1 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -137,7 +137,7 @@ function CustomDatePicker(props) { } ``` -People could of course also inline their field if they want: +The user can also inline their field if they want: ```tsx import { useDateManager } from '@base-ui/x-date-pickers/managers'; @@ -211,7 +211,7 @@ No DX change here compared to today ### Without Material UI -People can use the `` component to add a button to clear the value: +The user can use the `` component to add a button to clear the value: ```tsx import { useDateManager } from '@base-ui/x-date-pickers/managers'; @@ -240,6 +240,8 @@ It would expend `Field.Root` from `@base-ui-components/react/Field`. #### Props +- Extends `Field.Root.Props` + - `manager`: `PickerManager` - **required for standalone fields** See [#15395](https://github.com/mui/mui-x/issues/15395) for context. @@ -308,6 +310,8 @@ It also renders a hidden input which contains the stringified value and can be u #### Props +- Extends `Field.Control.Props` + - `children`: `(section: InferFieldSection) => React.ReactNode` ### `PickerField.Section` @@ -316,7 +320,7 @@ Renders a single section (for instance the year of the hour of the current value #### Props -- `children`: `React.ReactNode` +- Extends `React.HTMLAttributes` - `section`: `InferFieldSection` (can be `FieldSection` or `FieldRangeSection`) - **required**. ### `PickerField.SectionContent` @@ -325,7 +329,7 @@ Renders the content of a single section. #### Props -- nothing? +- Extends `React.HTMLAttributes` ### `PickerField.SectionSeparator` @@ -337,6 +341,7 @@ Renders the separator to display before or after the current section. #### Props +- Extends `React.HTMLAttributes` - `position`: `'before' | 'after'` - **required**. ### `PickerField.Clear` @@ -345,6 +350,8 @@ Renders the button to clear the value of the field. #### Props +- Extends `React.HTMLAttributes` + - `children`: `React.ReactNode` - `onClear`: `React.MouseEventHandler` From 87542d74ec0458e8922567fa24b4dcc4f848444f Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 13:49:43 +0100 Subject: [PATCH 07/46] Work on Calendar doc page --- docs/data/date-pickers/rfc/calendar.md | 126 ++++++++++++------------- docs/data/date-pickers/rfc/field.md | 24 +++-- 2 files changed, 76 insertions(+), 74 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 6768144f24b26..21833589dcd52 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -36,11 +36,9 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - - ◀ - + - + @@ -89,9 +87,9 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - + - + {({ months }) => @@ -164,32 +162,24 @@ When MD3 is supported, the default views of `` should probably b {({ view }) => (
- - ◀ - - ◀ + - - - ▶ - + +
- - ◀ - - ◀ + - - - ▶ - + +
)} @@ -233,17 +223,13 @@ Today's `` header would look as follow: {({ view }) => ( - + {view === 'year' ? '▲' : '▼'} - +
- - ◀ - - - ▶ - + +
@@ -251,7 +237,7 @@ Today's `` header would look as follow:
``` -But the current behavior is not great, once you are on the `year` view, there is no way to go back to the `day` view without picking a value. +But the current behavior is not great, once the user is on the `year` view, there is no way to go back to the `day` view without picking a value. ::: ## Display week number @@ -309,7 +295,7 @@ The user can use the `` and ` @@ -473,29 +459,13 @@ Doesn't render a DOM node (it does not have a `render` prop either). - `children`: `React.ReactNode` -### `Calendar.Header.Root` - -Top level component for the `Calendar.Header.*` components. - -#### Props - -- Extends `React.HTMLAttributes` - -### `Calendar.Header.Label` - -Renders the header label for the current value based on the provided format. - -#### Props - -- Extends `React.HTMLAttributes` - -- `format`: `string`, default: `${utils.formats.month} ${utils.formats.year}` - -### `Calendar.Navigation.GoToMonth` +### `Calendar.GoToMonth` Renders a button to go to the previous or the next month. It does not modify the value it only navigates to the target month. +#### Props + - Extends `React.HTMLAttributes` - `target`: `'previous' | 'next'` @@ -504,11 +474,13 @@ It does not modify the value it only navigates to the target month. TODO: Clarify the behavior when multiple calendars are rendered at once. ::: -### `Calendar.Navigation.GoToYear` +### `Calendar.GoToYear` Renders a button to go to the previous or the next month. It does not modify the value it only navigates to the target year. +#### Props + - Extends `React.HTMLAttributes` - `target`: `'previous' | 'next'` @@ -517,14 +489,34 @@ It does not modify the value it only navigates to the target year. TODO: Clarify the behavior when multiple calendars are rendered at once. ::: -### `Calendar.Navigation.SetView` +### `Calendar.SetView` Renders a button to set the current visible view. +#### Props + - Extends `React.HTMLAttributes` - `target`: `TView` +### `Calendar.Header.Root` + +Top level component for the `Calendar.Header.*` components. + +#### Props + +- Extends `React.HTMLAttributes` + +### `Calendar.Header.Label` + +Renders the header label for the current value based on the provided format. + +#### Props + +- Extends `React.HTMLAttributes` + +- `format`: `string`, default: `${utils.formats.month} ${utils.formats.year}` + ### `Calendar.Days.Root` Top level component for the `Calendar.Days.*` components. @@ -647,26 +639,28 @@ It expects a function as its children, which has the list of the months as a par - `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` -- `cellsPerRow`: `number`, default: `1` +- `monthsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `monthsPerRow`: `number`, default: `1` :::success - The `cellsPerRow` prop is needed to have a working keyboard navigation. + The `monthsOrder` and `monthsPerRow` prop is needed to have a working keyboard navigation. But it's not a great DX, especially if the user wants to vary the amount of items per row based on the viewport width. The navigation behavior should looks something like this: - - if `cellsPerRow === 1`: + - if `monthsPerRow === 1`: - ArrowLeft do nothing - ArrowRight do nothing - - ArrowTop go to the month rendered above (should handle `display: flex-reverse`) - - ArrowBottom go to month rendered below (should handle `display: flex-reverse`) + - ArrowTop go to the month rendered above + - ArrowBottom go to month rendered below - - if `cellsPerRow > 1`: - - ArrowLeft go the month rendered on the left, and if none should go to the outer-right month of the line rendered above (should handle `display: flex-reverse`) - - ArrowRight go the month rendered on the right, and if none should go to the outer-left month of the line rendered below (should handle `display: flex-reverse`) - - ArrowTop go to the month rendered above (should handle `display: flex-reverse`) - - ArrowBottom go to month rendered below (should handle `display: flex-reverse`) + - if `monthsPerRow > 1`: + - ArrowLeft go the month rendered on the left, and if none should go to the outer-right month of the line rendered above + - ArrowRight go the month rendered on the right, and if none should go to the outer-left month of the line rendered below + - ArrowTop go to the month rendered above + - ArrowBottom go to month rendered below And with no assumption on the layout, this seems to be a real challenge to achieve. The MVP could probably not contain any keyboard navigation. @@ -700,10 +694,12 @@ It expects a function as its children, which has the list of the years as a para - `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` -- `cellsPerRow`: `number`, default: `1` +- `yearsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `yearsPerRow`: `number`, default: `1` :::success - The `cellsPerRow` prop is needed to have a working keyboard navigation. + The `yearsPerRow` prop is needed to have a working keyboard navigation. See the equivalent prop in `Calendar.Months.Root` for more details. ::: diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index 30e29187f2fa1..5c54b870106cc 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -61,13 +61,15 @@ function CustomDateField(props) { return ( - {(section) => ( - - - - - - )} + {({ sections }) => + sections.map((section) => ( + + + + + + )) + } ); @@ -300,10 +302,14 @@ That way, users only have to pass the props specific to the field to `{(section) =>
{section.value}
} + + {({ sections }) => + sections.map((section) => ) + } + ``` It also renders a hidden input which contains the stringified value and can be used for form submission and testing. From 053cba23268a1efc874fb784f65f72e42d0a6104 Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 13:50:46 +0100 Subject: [PATCH 08/46] Work on Calendar doc page --- docs/data/date-pickers/rfc/calendar.md | 16 +-- docs/data/date-pickers/rfc/field.md | 18 +++- docs/data/date-pickers/rfc/picker.md | 138 +++++++++++++++++++++++-- 3 files changed, 154 insertions(+), 18 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 21833589dcd52..0976ec82ca018 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -37,7 +37,7 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - + @@ -88,7 +88,7 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - + @@ -167,7 +167,7 @@ When MD3 is supported, the default views of `` should probably b target={view === 'year' ? 'day' : 'year'} disabled={view === 'month'} > - + @@ -177,7 +177,7 @@ When MD3 is supported, the default views of `` should probably b target={view === 'month' ? 'day' : 'month'} disabled={view === 'year'} > - + @@ -224,7 +224,7 @@ Today's `` header would look as follow: {({ view }) => ( - {view === 'year' ? '▲' : '▼'} + {view === 'year' ? '▲' : '▼'}
@@ -338,7 +338,7 @@ The `` component can be built in a few different ways: function CustomCalendarHeader() { return ( - + ); } @@ -379,7 +379,7 @@ The `` component can be built in a few different ways: paddingRight: 12, }); - export const PickerCalendarHeaderLabel = styled(Calendar.Header.Label)({ + export const PickerCalendarHeaderLabel = styled(Calendar.Header.Title)({ /** ... */ }); @@ -507,7 +507,7 @@ Top level component for the `Calendar.Header.*` components. - Extends `React.HTMLAttributes` -### `Calendar.Header.Label` +### `Calendar.Header.Title` Renders the header label for the current value based on the provided format. diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index 5c54b870106cc..4691271ef1844 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -8,7 +8,7 @@ title: DX - Field

This page describes how people can use field with Material UI and how they can build custom fields while keeping the built-in editing behavior.

:::success -This page extends the initial proposal made in [this Github comment](https://github.com/mui/mui-x/issues/14496#issuecomment-2348917294) +This page extends the initial proposal made in [this GitHub comment](https://github.com/mui/mui-x/issues/14496#issuecomment-2348917294) ::: ## Basic standalone usage @@ -87,9 +87,12 @@ The field can then be rendered just like the Material UI fields: ### With Material UI :::success -No DX change here compared to today +No DX change here compared to today. +The only change is that the field component are detecting if there is a picker around them and adding an opening button if so (instead of having the picker pass a prop to define this opening button). ::: +The field exposed by `@mui/x-date-pickers` and `@mui/x-date-pickers` automatically + ```tsx import { DatePicker } from '@mui/x-date-pickers/DatePicker'; @@ -102,6 +105,15 @@ The concept of slots does not fit this use case very well, but the exploration o ### Without Material UI +To use the field inside a picker, it has to contain a way to open the picker. + +:::success +TODO: Find the DX to define a trigger button. + +- Should it a custom `Picker.Trigger` or directly the `Popover.Trigger` and `Dialog.Trigger`? +- If it uses the Base UI component, how should it handle the responsive version of the picker? + ::: + #### Inside a picker from `@mui/x-date-pickers` Even if most applications with a custom field probably want to remove `@mui/material` entirely, using these custom fields inside a self contained picker component from `@mui/x-date-pickers/DatePicker` is totally doable. @@ -187,7 +199,7 @@ When used inside a picker, `` can be passed directly and ``` :::success -I have a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505). +THere is a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505). ::: ### Without Material UI diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index 69f86d473e9e7..091efd2c44c27 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -1,9 +1,9 @@ --- productId: x-date-pickers -title: DX - Pickers +title: DX - Picker --- -# Fields +# Picker

This page describes how people can use picker with Material UI and how they can build custom pickers.

@@ -11,18 +11,142 @@ title: DX - Pickers This page extends the initial proposal made in [#14718](https://github.com/mui/mui-x/issues/14718) ::: -## With Material UI +## Basic usage -### Basic usage +### With Material UI TODO -### Override part of the UI +### Without Material UI + +```tsx +function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + + + + {/** See field documentation */} + 📅 + + + + + + + + + + + ); +} +``` + +## Add an action bar + +### With Material UI + +TODO + +### Without Material UI + +```tsx + + {/** See demo above */} +
+ Clear + Close +
+
+``` + +## Add a toolbar + +### With Material UI + +TODO + +### Without Material UI + +```tsx + + + + + {/** See demo above */} + +``` + +```tsx + + + + + + + + + + {/** See demo above */} + +``` + +## Add tabs + +### With Material UI + +TODO + +### Without Material UI TODO -## Without Material UI +## Add shortcuts + +### With Material UI + +TODO + +### Without Material UI + +TODO + +## Anatomy of `Picker.*` + +### `Picker.Root` + +TODO + +### `Picker.Clear` + +TODO + +### `Picker.SetValue` + +TODO + +### `Picker.SetView` + +TODO + +### `Picker.Layout` + +TODO + +### `Picker.Toolbar.Root` + +TODO + +### `Picker.Toolbar.Title` + +TODO + +### `Picker.Shortcuts.Root` + +TODO -### Basic usage +### `Picker.Shortcut.Item` TODO From d1558b3e530d18b9b118a6b588fbb24bd04d28b0 Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 17:53:29 +0100 Subject: [PATCH 09/46] Work on picker page --- docs/data/date-pickers/rfc/calendar.md | 70 +++++----- docs/data/date-pickers/rfc/picker.md | 171 +++++++++++++++++++++---- 2 files changed, 179 insertions(+), 62 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 0976ec82ca018..86a61d350e7de 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -35,11 +35,11 @@ The user can use the `Calendar.Days.*` components to create a grid of days and t import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - +
- + - +
{({ days }) => days.map((day) => )} @@ -86,11 +86,11 @@ The user can use the `Calendar.Months.*` components to create a grid of months a import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - +
- + - +
{({ months }) => months.map((month) => ) @@ -158,7 +158,7 @@ When MD3 is supported, the default views of `` should probably b ```tsx - +
{({ view }) => (
@@ -167,7 +167,7 @@ When MD3 is supported, the default views of `` should probably b target={view === 'year' ? 'day' : 'year'} disabled={view === 'month'} > - +
@@ -177,13 +177,13 @@ When MD3 is supported, the default views of `` should probably b target={view === 'month' ? 'day' : 'month'} disabled={view === 'year'} > - +
)} -
+
@@ -220,11 +220,11 @@ The header above tries to replicate the behavior of a MD3 Date Picker. Today's `` header would look as follow: ```tsx - +
{({ view }) => ( - {view === 'year' ? '▲' : '▼'} + {view === 'year' ? '▲' : '▼'}
@@ -234,7 +234,7 @@ Today's `` header would look as follow: )} - +
``` But the current behavior is not great, once the user is on the `year` view, there is no way to go back to the `day` view without picking a value. @@ -328,18 +328,18 @@ The `` component can be built in a few different ways: That way, this components can be composed more freely, it now only has to be mounted inside ``. ::: -2. Using the `Calendar.*` primitives exposed by `@base-ui/x-date-pickers/Calendar`: +2. Using the primitives exposed by `@base-ui/x-date-pickers/Calendar`: - If the user wants to totally own the styling of this part of the UI (because he wants to build something really different from Material UI), he can use `Calendar.*` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: + If the user wants to totally own the styling of this part of the UI (because he wants to build something really different from Material UI), he can use components like `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: ```tsx import { Calendar } from '@base-ui/x-date-pickers/Calendar'; function CustomCalendarHeader() { return ( - - - +
+ +
); } ``` @@ -370,7 +370,7 @@ The `` component can be built in a few different ways: ```tsx import { Calendar } from '@base-ui/x-date-pickers/Calendar'; - export const PickerCalendarHeaderRoot = styled(Calendar.Header.Root)({ + export const PickerCalendarHeaderRoot = styled('div')({ display: 'flex', alignItems: 'center', marginTop: 12, @@ -379,7 +379,7 @@ The `` component can be built in a few different ways: paddingRight: 12, }); - export const PickerCalendarHeaderLabel = styled(Calendar.Header.Title)({ + export const PickerCalendarHeaderLabel = styled(Calendar.FormattedValue)({ /** ... */ }); @@ -409,7 +409,7 @@ The `` component can be built in a few different ways: Should it be: 1. `` like it would be today - 2. `` to match the exports from `@base-ui/x-date-pickers` + 2. `` to match the exports from `@base-ui/x-date-pickers` 3. Something else? ::: @@ -459,6 +459,16 @@ Doesn't render a DOM node (it does not have a `render` prop either). - `children`: `React.ReactNode` +### `Calendar.FormattedValue` + +Formats the value based on the provided format. + +#### Props + +- Extends `React.HTMLAttributes` + +- `format`: `string` - **required** + ### `Calendar.GoToMonth` Renders a button to go to the previous or the next month. @@ -499,24 +509,6 @@ Renders a button to set the current visible view. - `target`: `TView` -### `Calendar.Header.Root` - -Top level component for the `Calendar.Header.*` components. - -#### Props - -- Extends `React.HTMLAttributes` - -### `Calendar.Header.Title` - -Renders the header label for the current value based on the provided format. - -#### Props - -- Extends `React.HTMLAttributes` - -- `format`: `string`, default: `${utils.formats.month} ${utils.formats.year}` - ### `Calendar.Days.Root` Top level component for the `Calendar.Days.*` components. diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index 091efd2c44c27..5881394500a48 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -11,7 +11,7 @@ title: DX - Picker This page extends the initial proposal made in [#14718](https://github.com/mui/mui-x/issues/14718) ::: -## Basic usage +## Basic usage in a Popover ### With Material UI @@ -44,6 +44,28 @@ function CustomDatePicker(props) { } ``` +## Basic usage in a Dialog + +### With Material UI + +TODO + +### Without Material UI + +TODO + +## Basic responsive usage + +### With Material UI + +TODO + +### Without Material UI + +TODO + +## Basic responsive usage + ## Add an action bar ### With Material UI @@ -52,11 +74,16 @@ TODO ### Without Material UI +The user can use the ``, `` and `` components to create an action bar and interact with the value: + ```tsx {/** See demo above */}
- Clear + Clear + Today + Accept + Cancel Close
@@ -70,25 +97,29 @@ TODO ### Without Material UI +The user can use the `Picker.ToolbarRoot` and `Picker.FormattedValue` components to create a toolbar for its picker: + ```tsx - - - + + + {/** See demo above */} ``` +The toolbar can also be used to switch between views thanks to the `` component: + ```tsx - + - + - + - + {/** See demo above */} ``` @@ -101,7 +132,38 @@ TODO ### Without Material UI -TODO +The user can use the `Picker.SetView` component in combination with any `Tabs` component. + +The example below uses the `Tabs` component from Base UI as an example: + +```tsx +import { Tabs } from '@base-ui-components/react/tabs'; +import { Picker } from '@base-ui/x-date-pickers/Picker'; + + + {({ view }) => ( + + + + } + > + Date + + } + > + Time + + + + {/** See demo above */} + + )} +; +``` ## Add shortcuts @@ -111,7 +173,52 @@ TODO ### Without Material UI -TODO +```tsx + +
+ + New Year's Day + + + Independence Day + +
+ {/** See demo above */} +
+``` + +:::success +To support the `isValid` param of the Material UI shortcut implement, a `useIsValidValue` hook could be added. +Without it, it's not trivial to use `useValidation` since it requires a value and params like the validation props or the timezone. + +```tsx +import { useIsValueValid } from '@base-ui/x-date-pickers/hooks'; + +const isValueValid = useIsValueValid(); + +const newAvailableSaturday = React.useMemo(() => { + const today = dayjs(); + const nextSaturday = + today.day() <= 6 + ? today.add(6 - today.day(), 'day') + : today.add(7 + 6 - today.day(), 'day'); + + let maxAttempts = 50; + let solution: Dayjs = nextSaturday; + while (maxAttempts > 0 && !isValueValid(solution)) { + solution = solution.add(7, 'day'); + maxAttempts -= 1; + } + + return solution; +}, [isValueValid]); + +return ( + Next available saturday +); +``` + +::: ## Anatomy of `Picker.*` @@ -119,34 +226,52 @@ TODO TODO -### `Picker.Clear` +### `Picker.FormattedValue` + +Formats the value based on the provided format. + +#### Props + +- Extends `React.HTMLAttributes` + +- `format`: `string` - **required** + +### `Picker.Views` TODO ### `Picker.SetValue` -TODO +#### Props -### `Picker.SetView` +- Extends `React.HTMLAttributes` -TODO +- `target`: `PickerValidDate` - **required** -### `Picker.Layout` +### `Picker.AcceptValue` -TODO +#### Props -### `Picker.Toolbar.Root` +- Extends `React.HTMLAttributes` -TODO +### `Picker.CancelValue` -### `Picker.Toolbar.Title` +#### Props -TODO +- Extends `React.HTMLAttributes` + +### `Picker.SetView` + +#### Props -### `Picker.Shortcuts.Root` +- Extends `React.HTMLAttributes` + +- `target`: `TView` - **required** + +### `Picker.Layout` TODO -### `Picker.Shortcut.Item` +### `Picker.ToolbarRoot` TODO From c905484a6c6eef561db1723717fcb414c1747e58 Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 27 Nov 2024 18:17:02 +0100 Subject: [PATCH 10/46] Work on picker page --- docs/data/date-pickers/rfc/calendar.md | 23 ++++ docs/data/date-pickers/rfc/field.md | 12 +- docs/data/date-pickers/rfc/picker.md | 150 ++++++++++++++++++------- 3 files changed, 140 insertions(+), 45 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 86a61d350e7de..dd6cef84368ec 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -438,6 +438,29 @@ Top level component that wraps the other components. - `autoFocus`: `boolean` +:::success +All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. + +That way, users only have to pass the props specific to the calendar to the `Calendar.*` components: + +```tsx + + {/** See the field documentation */} + + + + + + {/** See demo above */} + + + + + +``` + +::: + ### `Calendar.MatchView` Utility component to conditionally render some components based on the current view. diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index 4691271ef1844..bda1e1af2b1cc 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -258,7 +258,9 @@ It would expend `Field.Root` from `@base-ui-components/react/Field`. - `manager`: `PickerManager` - **required for standalone fields** + :::success See [#15395](https://github.com/mui/mui-x/issues/15395) for context. + ::: - **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. @@ -293,18 +295,16 @@ It would expend `Field.Root` from `@base-ui-components/react/Field`. - `autoFocus`: `boolean` :::success -All the props that the picker can pass to the field (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that it can be used inside a picker built with composition. +All the props that the picker can pass to the field (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the field can be used inside a picker built with composition. -That way, users only have to pass the props specific to the field to ``: +That way, users only have to pass the props specific to the field to the `PickerField.*` components: ```tsx - + {/** See demo above */} - - {/** See picker documentation */} - + {/** See picker documentation */} ``` diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index 5881394500a48..d086145589c0a 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -35,7 +35,7 @@ function CustomDatePicker(props) { - + {/** See calendar documentation */} @@ -64,7 +64,29 @@ TODO TODO -## Basic responsive usage +## Usage with date and time views + +### With Material UI + +TODO + +### Without Material UI + +The user can use the `` component to conditionally render the view components. +This is needed to build date time pickers: + +```tsx + + + {/** See calendar documentation */} + + + + {/** See digital clock documentation (not available yet) */} + + + +``` ## Add an action bar @@ -77,8 +99,8 @@ TODO The user can use the ``, `` and `` components to create an action bar and interact with the value: ```tsx - - {/** See demo above */} + + {/** See calendar documentation */}
Clear Today @@ -86,7 +108,7 @@ The user can use the ``, `` and `Cancel Close
-
+ ``` ## Add a toolbar @@ -97,31 +119,31 @@ TODO ### Without Material UI -The user can use the `Picker.ToolbarRoot` and `Picker.FormattedValue` components to create a toolbar for its picker: +The user can use the `` component to create a toolbar for its picker: ```tsx - - + +
- - {/** See demo above */} - +
+ {/** See calendar documentation */} +
``` The toolbar can also be used to switch between views thanks to the `` component: ```tsx - - + +
- - {/** See demo above */} - +
+ {/** See calendar documentation */} +
``` ## Add tabs @@ -132,7 +154,7 @@ TODO ### Without Material UI -The user can use the `Picker.SetView` component in combination with any `Tabs` component. +The user can use the `` component in combination with any Tabs / Tab components. The example below uses the `Tabs` component from Base UI as an example: @@ -140,9 +162,9 @@ The example below uses the `Tabs` component from Base UI as an example: import { Tabs } from '@base-ui-components/react/tabs'; import { Picker } from '@base-ui/x-date-pickers/Picker'; - - {({ view }) => ( - + + + {({ view }) => ( - {/** See demo above */} - - )} -; + )} + + {/** See calendar documentation */} +; ``` ## Add shortcuts @@ -173,8 +195,10 @@ TODO ### Without Material UI +The user can use the `` component to create a shortcut UI: + ```tsx - +
New Year's Day @@ -183,12 +207,12 @@ TODO Independence Day
- {/** See demo above */} -
+ {/** See calendar documentation */} + ``` :::success -To support the `isValid` param of the Material UI shortcut implement, a `useIsValidValue` hook could be added. +To support the `isValid` param of the Material UI shortcut, a `useIsValidValue` hook could be added. Without it, it's not trivial to use `useValidation` since it requires a value and params like the validation props or the timezone. ```tsx @@ -224,7 +248,27 @@ return ( ### `Picker.Root` -TODO +#### Props + +- `manager`: `PickerManager` - **required** + + :::success + See [#15395](https://github.com/mui/mui-x/issues/15395) for context. + ::: + +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. + + Same typing and behavior as today. + +- **Validation props**: list based on the `manager` prop + + For `useDateManager()` it would be `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. + + Same typing and behavior as today. + +- **Form props**: `disabled`, `readOnly`. + + Same typing and behavior as today. ### `Picker.FormattedValue` @@ -236,12 +280,42 @@ Formats the value based on the provided format. - `format`: `string` - **required** -### `Picker.Views` +### `Picker.MatchView` -TODO +Utility component to conditionally render some components based on the current view. +Doesn't render a DOM node (it does not have a `render` prop either). + +```tsx + + Only rendered when the view is "day" + + + + Only rendered when the view is "day" or "month" + +``` + +#### Props + +- `match`: `TView | readonly TView[]` - **required**. + +- `children`: `React.ReactNode` + +### `Picker.ContextValue` + +Utility component to access the picker public context. + +:::success +The user can also use `usePickerContext()`, but a component allows to not create a dedicated component to access things close from `` +::: + +#### Props ### `Picker.SetValue` +Renders a button to set the current value. +The button is disabled if the value is invalid. + #### Props - Extends `React.HTMLAttributes` @@ -250,28 +324,26 @@ TODO ### `Picker.AcceptValue` +Renders a button to accept the current value. + #### Props - Extends `React.HTMLAttributes` ### `Picker.CancelValue` +Renders a button to cancel the current value. + #### Props - Extends `React.HTMLAttributes` ### `Picker.SetView` +Renders a button to set the current visible view. + #### Props - Extends `React.HTMLAttributes` - `target`: `TView` - **required** - -### `Picker.Layout` - -TODO - -### `Picker.ToolbarRoot` - -TODO From 9eeb95295fb2f3df24905cfd812b6ad26a6d4d12 Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 08:24:29 +0100 Subject: [PATCH 11/46] Work on picker page --- docs/data/date-pickers/rfc/picker.md | 71 +++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index d086145589c0a..f9693f3d40ea3 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -27,10 +27,8 @@ function CustomDatePicker(props) { - - {/** See field documentation */} - 📅 - + {/** See field documentation */} + 📅 @@ -52,7 +50,24 @@ TODO ### Without Material UI -TODO +```tsx +function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + + {/** See field documentation */} + 📅 + + + + {/** See calendar documentation */} + + + ); +} +``` ## Basic responsive usage @@ -62,7 +77,51 @@ TODO ### Without Material UI -TODO +If the library does not provide any higher level utilities to create a responsive picker and sticks with "1 React component = 1 DOM element", here is what a responsive picker could look like: + +```tsx +function CustomDatePicker(props) { + const manager = useDateManager(); + const isDesktop = useMediaQuery('@media (pointer: fine)', { + defaultMatches: true, + }); + + const wrapView = (viewNode: React.ReactNode) => { + if (variant === 'mobile') { + return {viewNode}; + } + + return ( + + {viewNode} + + ); + }; + + return ( + + + + {/** See field documentation */} + {variant === 'mobile' ? ( + 📅 + ) : ( + 📅 + )} + + + {wrapView( + {/** See calendar documentation */}, + )} + + + ); +} +``` + +:::success + +::: ## Usage with date and time views From 84b532e160c4ffa52f31b464c2e56b1c53da0f2a Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 08:26:56 +0100 Subject: [PATCH 12/46] Work on picker page --- docs/data/date-pickers/rfc/picker.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index f9693f3d40ea3..e38ff395fa517 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -119,10 +119,6 @@ function CustomDatePicker(props) { } ``` -:::success - -::: - ## Usage with date and time views ### With Material UI @@ -370,10 +366,12 @@ The user can also use `usePickerContext()`, but a component allows to not create #### Props +- `children`: `(contextValue: PickerContextValue) => React.ReactNode` + ### `Picker.SetValue` Renders a button to set the current value. -The button is disabled if the value is invalid. +The button is disabled if the value is invalid (this could be configurable through an `acceptInvalidValue` prop). #### Props @@ -381,6 +379,8 @@ The button is disabled if the value is invalid. - `target`: `PickerValidDate` - **required** +- `importance`: `'set' | 'accept'`, default: `'accept'` + ### `Picker.AcceptValue` Renders a button to accept the current value. From 2d573520e5ae638074eb98929675c5eba4a3134e Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 08:41:31 +0100 Subject: [PATCH 13/46] Work on picker page --- docs/data/date-pickers/rfc/field.md | 78 ++++++++++++++++++++++------- docs/data/pages.ts | 18 +++---- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index bda1e1af2b1cc..b09e934612917 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -105,14 +105,49 @@ The concept of slots does not fit this use case very well, but the exploration o ### Without Material UI -To use the field inside a picker, it has to contain a way to open the picker. +#### Add a trigger to open the picker + +To be able to open the picker using its field, the user has to add a trigger button for the Popover or the Modal that is used inside the picker. +You can find more demos on the picker documentation on how to handle mobile and responsive pickers. + +```tsx +import { useDateManager } from '@base-ui/x-date-pickers/managers'; +import { PickerField } from '@base-ui/x-date-pickers/PickerField'; + +function CustomDateField(props) { + const manager = useDateManager(); + + return ( + + {/** See demo above */} + 📅 + + ); +} +``` :::success -TODO: Find the DX to define a trigger button. +If requested, a new utility hook could be added to easily check if the field is inside a picker. This would allow the same field component to be used as standalone and inside a picker: -- Should it a custom `Picker.Trigger` or directly the `Popover.Trigger` and `Dialog.Trigger`? -- If it uses the Base UI component, how should it handle the responsive version of the picker? - ::: +```tsx +import { useDateManager } from '@base-ui/x-date-pickers/managers'; +import { useIsInsidePicker } from '@base-ui/x-date-pickers/hooks'; +import { PickerField } from '@base-ui/x-date-pickers/PickerField'; + +function CustomDateField(props) { + const manager = useDateManager(); + const isInsidePicker = useIsInsidePicker(); + + return ( + + {/** See demo above */} + {isInsidePicker && 📅} + + ); +} +``` + +::: #### Inside a picker from `@mui/x-date-pickers` @@ -141,12 +176,13 @@ function CustomDatePicker(props) { const manager = useDateManager(); return ( - - - - {/** See picker documentation */} - - + + + + + {/** See picker documentation */} + + ); } ``` @@ -161,18 +197,22 @@ function CustomDatePicker(props) { const manager = useDateManager(); return ( - - {/** See demo above */} - - {/** See picker documentation */} - - + + + + {/** See demo above */} + 📅 + + + {/** See picker documentation */} + + ); } ``` :::success -When doing that, the `Picker.Field.Root` doesn't have to receive props like `minDate` because they are accessed using `usePickerContext` (or maybe a dedicated `usePickerValidationContext`). This makes composition viable between the picker and the field (same for the views). +When doing that, the `PickerField.Root` doesn't have to receive props like `minDate` because they are accessed using `usePickerContext` (or maybe a dedicated `usePickerValidationContext`). This makes composition viable between the picker and the field (same for the views). ::: ## Basic usage (multi input picker) @@ -245,7 +285,7 @@ function CustomDateField(props) { } ``` -## Anatomy of `Picker.*` +## Anatomy of `PickerField.*` ### `PickerField.Root` diff --git a/docs/data/pages.ts b/docs/data/pages.ts index ce51f97ea9e48..833a37b3d4cb8 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -257,6 +257,15 @@ const pages: MuiPage[] = [ }, ], }, + { + pathname: '/x/react-date-pickers/rfc', + title: 'Date and Time Pickers - new DX', + children: [ + { pathname: '/x/react-date-pickers/rfc/field', title: 'Field' }, + { pathname: '/x/react-date-pickers/rfc/calendar', title: 'Calendar' }, + { pathname: '/x/react-date-pickers/rfc/picker', title: 'Picker' }, + ], + }, { pathname: '/x/react-date-pickers-group', title: 'Date and Time Pickers', @@ -265,15 +274,6 @@ const pages: MuiPage[] = [ { pathname: '/x/react-date-pickers/getting-started' }, { pathname: '/x/react-date-pickers/base-concepts' }, { pathname: '/x/react-date-pickers/faq', title: 'FAQs' }, - { - pathname: '/x/react-date-pickers/rfc', - title: 'Composition and unstyled DX', - children: [ - { pathname: '/x/react-date-pickers/rfc/field', title: 'Field' }, - { pathname: '/x/react-date-pickers/rfc/calendar', title: 'Calendar' }, - { pathname: '/x/react-date-pickers/rfc/picker', title: 'Picker' }, - ], - }, { pathname: '/x/react-date-pickers-components', subheader: 'Components', From ee6d5aa1529fab25e8d5c5fe8727857f8e8c20ca Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 08:50:05 +0100 Subject: [PATCH 14/46] Reorder sections --- docs/data/date-pickers/rfc/calendar.md | 80 +++++++-------- docs/data/date-pickers/rfc/field.md | 134 ++++++++++++------------- docs/data/date-pickers/rfc/picker.md | 36 +++---- 3 files changed, 125 insertions(+), 125 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index dd6cef84368ec..2015d7a3ccb11 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -13,20 +13,6 @@ This page extends the initial proposal made in [#15598](https://github.com/mui/m ## Usage with only days -### With Material UI - -:::success -No DX change here compared to today -::: - -The user can use the `` and limit the views: - -```tsx -import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; - -; -``` - ### Without Material UI The user can use the `Calendar.Days.*` components to create a grid of days and the `Calendar.Header.*` to create a header to navigate across the months: @@ -57,26 +43,21 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar';
; ``` -## Usage with only months - ### With Material UI :::success No DX change here compared to today ::: -The user can use the `` component: +The user can use the `` and limit the views: ```tsx -import { MonthCalendar } from '@mui/x-date-pickers/MonthCalendar'; +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; - +; ``` -:::success -The big limitation here is that the `` component does not have a header to navigate through the years. -Once the `Calendar.*` unstyled component is ready, the `` should probably be reworked to improve this (or removed in favor of always using ``). -::: +## Usage with only months ### Without Material UI @@ -99,27 +80,27 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; ; ``` -## Usage with only years - ### With Material UI :::success No DX change here compared to today ::: -The user can use the `` component: +The user can use the `` component: ```tsx -import { YearCalendar } from '@mui/x-date-pickers/YearCalendar'; +import { MonthCalendar } from '@mui/x-date-pickers/MonthCalendar'; - + ``` :::success -The big limitation here is that the `` component does not have a header to navigate through the years. -Once the `Calendar.*` unstyled component is ready, the `` should probably be reworked to improve this (or removed in favor of always using ``). +The big limitation here is that the `` component does not have a header to navigate through the years. +Once the `Calendar.*` unstyled component is ready, the `` should probably be reworked to improve this (or removed in favor of always using ``). ::: +## Usage with only years + ### Without Material UI The user can use the `Calendar.Years.*` components to create a grid of years: @@ -134,26 +115,27 @@ import { Calendar } from '@base-ui/x-date-pickers/Calendar'; ; ``` -## Day + month + years - ### With Material UI :::success No DX change here compared to today ::: -The user can use the `` component and add the month view: +The user can use the `` component: ```tsx -import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; +import { YearCalendar } from '@mui/x-date-pickers/YearCalendar'; - + ``` :::success -When MD3 is supported, the default views of `` should probably be `['year', 'month', 'day']` +The big limitation here is that the `` component does not have a header to navigate through the years. +Once the `Calendar.*` unstyled component is ready, the `` should probably be reworked to improve this (or removed in favor of always using ``). ::: +## Day + month + years + ### Without Material UI ```tsx @@ -240,22 +222,26 @@ Today's `` header would look as follow: But the current behavior is not great, once the user is on the `year` view, there is no way to go back to the `day` view without picking a value. ::: -## Display week number - ### With Material UI :::success No DX change here compared to today ::: -The user can use the `` with the `displayWeekNumber` prop: +The user can use the `` component and add the month view: ```tsx import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; -; + ``` +:::success +When MD3 is supported, the default views of `` should probably be `['year', 'month', 'day']` +::: + +## Display week number + ### Without Material UI The user can use the `` and `` components to add a column to the grid: @@ -291,6 +277,20 @@ The user can use the `` and ` ``` +### With Material UI + +:::success +No DX change here compared to today +::: + +The user can use the `` with the `displayWeekNumber` prop: + +```tsx +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; + +; +``` + ## Override part of the UI ### With Material UI diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index b09e934612917..2c2ac755f2492 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -13,42 +13,6 @@ This page extends the initial proposal made in [this GitHub comment](https://git ## Basic standalone usage -### With Material UI - -The `@mui/x-date-pickers` package exposes one field per value type. -Those components are self-contained components (meaning they don't use composition). - -Here is a basic example of a ``: - -```tsx -import { DateField } from '@mui/x-date-pickers/DateField'; - -; -``` - -The behavior is the same for all the other fields: - -```tsx -; - -; - -; - -; - -; -``` - -:::success -This RFC proposes to rename `` into `` for concision when the single input range fields become the default and when the multi input range fields are gathered into a single component. -::: - -:::success -All these self-contained components are built on top of `PickerField`. -An intermediary internal component is needed to only create the component once and then have each field pass its `manager` to it. -::: - ### Without Material UI ```tsx @@ -82,27 +46,44 @@ The field can then be rendered just like the Material UI fields: ``` -## Basic usage inside a picker - ### With Material UI -:::success -No DX change here compared to today. -The only change is that the field component are detecting if there is a picker around them and adding an opening button if so (instead of having the picker pass a prop to define this opening button). -::: +The `@mui/x-date-pickers` package exposes one field per value type. +Those components are self-contained components (meaning they don't use composition). -The field exposed by `@mui/x-date-pickers` and `@mui/x-date-pickers` automatically +Here is a basic example of a ``: ```tsx -import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import { DateField } from '@mui/x-date-pickers/DateField'; -; +; +``` + +The behavior is the same for all the other fields: + +```tsx +; + +; + +; + +; + +; ``` :::success -The concept of slots does not fit this use case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so this RFC uses the tools currently available. +This RFC proposes to rename `` into `` for concision when the single input range fields become the default and when the multi input range fields are gathered into a single component. ::: +:::success +All these self-contained components are built on top of `PickerField`. +An intermediary internal component is needed to only create the component once and then have each field pass its `manager` to it. +::: + +## Basic usage inside a picker + ### Without Material UI #### Add a trigger to open the picker @@ -212,11 +193,37 @@ function CustomDatePicker(props) { ``` :::success -When doing that, the `PickerField.Root` doesn't have to receive props like `minDate` because they are accessed using `usePickerContext` (or maybe a dedicated `usePickerValidationContext`). This makes composition viable between the picker and the field (same for the views). +When doing that, the `` component doesn't have to receive props like `minDate` because they are accessed using `usePickerContext()` (or maybe a dedicated `usePickerValidationContext()`). This makes composition viable between the picker and the field (same for the views). +::: + +### With Material UI + +:::success +No DX change here compared to today. +The only change is that the field component are detecting if there is a picker around them and adding an opening button if so (instead of having the picker pass a prop to define this opening button). +::: + +The field exposed by `@mui/x-date-pickers` and `@mui/x-date-pickers` automatically + +```tsx +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +; +``` + +:::success +The concept of slots does not fit this use case very well, but the exploration of a better DX to override part of the UI in self-contained component is outside the scope of this documentation, so this RFC uses the tools currently available. ::: ## Basic usage (multi input picker) +### Without Material UI + +:::warning +This is not planned for now. +`Picker.*` could contain some additional components that would be the building blocks for `` but it does not seem to be the priority for now. +::: + ### With Material UI The `@mui/x-date-pickers` package also exposes a component to create multi input range fields as follow: @@ -239,30 +246,11 @@ When used inside a picker, `` can be passed directly and ``` :::success -THere is a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505). -::: - -### Without Material UI - -:::warning -This is not planned for now. -`Picker.*` could contain some additional components that would be the building blocks for `` but it does not seem to be the priority for now. +There is a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505). ::: ## Clearable field -### With Material UI - -:::success -No DX change here compared to today -::: - -```tsx - - - -``` - ### Without Material UI The user can use the `` component to add a button to clear the value: @@ -285,6 +273,18 @@ function CustomDateField(props) { } ``` +### With Material UI + +:::success +No DX change here compared to today +::: + +```tsx + + + +``` + ## Anatomy of `PickerField.*` ### `PickerField.Root` diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index e38ff395fa517..3eb6318eb7c91 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -13,10 +13,6 @@ This page extends the initial proposal made in [#14718](https://github.com/mui/m ## Basic usage in a Popover -### With Material UI - -TODO - ### Without Material UI ```tsx @@ -42,12 +38,12 @@ function CustomDatePicker(props) { } ``` -## Basic usage in a Dialog - ### With Material UI TODO +## Basic usage in a Dialog + ### Without Material UI ```tsx @@ -69,12 +65,12 @@ function CustomDatePicker(props) { } ``` -## Basic responsive usage - ### With Material UI TODO +## Basic responsive usage + ### Without Material UI If the library does not provide any higher level utilities to create a responsive picker and sticks with "1 React component = 1 DOM element", here is what a responsive picker could look like: @@ -119,12 +115,12 @@ function CustomDatePicker(props) { } ``` -## Usage with date and time views - ### With Material UI TODO +## Usage with date and time views + ### Without Material UI The user can use the `` component to conditionally render the view components. @@ -143,12 +139,12 @@ This is needed to build date time pickers: ``` -## Add an action bar - ### With Material UI TODO +## Add an action bar + ### Without Material UI The user can use the ``, `` and `` components to create an action bar and interact with the value: @@ -166,12 +162,12 @@ The user can use the ``, `` and ` ``` -## Add a toolbar - ### With Material UI TODO +## Add a toolbar + ### Without Material UI The user can use the `` component to create a toolbar for its picker: @@ -201,12 +197,12 @@ The toolbar can also be used to switch between views thanks to the ` ``` -## Add tabs - ### With Material UI TODO +## Add tabs + ### Without Material UI The user can use the `` component in combination with any Tabs / Tab components. @@ -242,12 +238,12 @@ import { Picker } from '@base-ui/x-date-pickers/Picker'; ; ``` -## Add shortcuts - ### With Material UI TODO +## Add shortcuts + ### Without Material UI The user can use the `` component to create a shortcut UI: @@ -299,6 +295,10 @@ return ( ::: +### With Material UI + +TODO + ## Anatomy of `Picker.*` ### `Picker.Root` From fc9117c05ffe77852d7a2b64533e7d1d2e7c4b4d Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 09:00:14 +0100 Subject: [PATCH 15/46] Change imports to match Base UI nomenclature --- docs/data/date-pickers/rfc/calendar.md | 20 ++++++------ docs/data/date-pickers/rfc/field.md | 28 ++++++++-------- docs/data/date-pickers/rfc/picker.md | 44 +++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 2015d7a3ccb11..43d20048c8a06 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -18,7 +18,7 @@ This page extends the initial proposal made in [#15598](https://github.com/mui/m The user can use the `Calendar.Days.*` components to create a grid of days and the `Calendar.Header.*` to create a header to navigate across the months: ```tsx -import { Calendar } from '@base-ui/x-date-pickers/Calendar'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
@@ -64,7 +64,7 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; The user can use the `Calendar.Months.*` components to create a grid of months and the `Calendar.Header.*` to create a header to navigate across the years: ```tsx -import { Calendar } from '@base-ui/x-date-pickers/Calendar'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
@@ -106,7 +106,7 @@ Once the `Calendar.*` unstyled component is ready, the `` shoul The user can use the `Calendar.Years.*` components to create a grid of years: ```tsx -import { Calendar } from '@base-ui/x-date-pickers/Calendar'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -312,7 +312,7 @@ The `` component can be built in a few different ways: This is mostly viable for components that don't interact a lot with the picker state. For example, if someone wants to build a custom header for their calendar that just displays the current month, they could do it from scratch: ```tsx - import { useCalendarContext } from '@base-ui/x-date-pickers/Calendar'; + import { useCalendarContext } from '@base-ui-components/react-x-date-pickers/calendar'; function CustomCalendarHeader() { const { currentMonth } = useCalendarContext(); @@ -328,12 +328,12 @@ The `` component can be built in a few different ways: That way, this components can be composed more freely, it now only has to be mounted inside ``. ::: -2. Using the primitives exposed by `@base-ui/x-date-pickers/Calendar`: +2. Using the primitives exposed by `@base-ui-components/react-x-date-pickers/calendar`: If the user wants to totally own the styling of this part of the UI (because he wants to build something really different from Material UI), he can use components like `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: ```tsx - import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CustomCalendarHeader() { return ( @@ -364,11 +364,11 @@ The `` component can be built in a few different ways: ``` :::success - The components like `` would be built on top of their `@base-ui/x-date-pickers/Calendar` counterparts and would be used to build ``. The packages expose several version but they don't have logic duplication. + The components like `` would be built on top of their `@base-ui-components/react-x-date-pickers/Calendar` counterparts and would be used to build ``. The packages expose several version but they don't have logic duplication. Internally, the code would look something like that: ```tsx - import { Calendar } from '@base-ui/x-date-pickers/Calendar'; + import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; export const PickerCalendarHeaderRoot = styled('div')({ display: 'flex', @@ -383,7 +383,7 @@ The `` component can be built in a few different ways: /** ... */ }); - // This component is purely presentational and not present in `@base-ui/x-date-pickers/Calendar'. + // This component is purely presentational and not present in `@base-ui-components/react-x-date-pickers/Calendar'. export const PickerCalendarHeaderLabelContainer = styled('div')({ /** ... */ }); @@ -409,7 +409,7 @@ The `` component can be built in a few different ways: Should it be: 1. `` like it would be today - 2. `` to match the exports from `@base-ui/x-date-pickers` + 2. `` to match the exports from `@base-ui-components/react-x-date-pickers` 3. Something else? ::: diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc/field.md index 2c2ac755f2492..271c3a2351259 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc/field.md @@ -16,8 +16,8 @@ This page extends the initial proposal made in [this GitHub comment](https://git ### Without Material UI ```tsx -import { useDateManager } from '@base-ui/x-date-pickers/managers'; -import { PickerField } from '@base-ui/x-date-pickers/PickerField'; +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { PickerField } from '@base-ui-components/react-x-date-pickers/picker-field'; function CustomDateField(props) { const manager = useDateManager(); @@ -92,8 +92,8 @@ To be able to open the picker using its field, the user has to add a trigger but You can find more demos on the picker documentation on how to handle mobile and responsive pickers. ```tsx -import { useDateManager } from '@base-ui/x-date-pickers/managers'; -import { PickerField } from '@base-ui/x-date-pickers/PickerField'; +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { PickerField } from '@base-ui-components/react-x-date-pickers/picker-field'; function CustomDateField(props) { const manager = useDateManager(); @@ -111,9 +111,9 @@ function CustomDateField(props) { If requested, a new utility hook could be added to easily check if the field is inside a picker. This would allow the same field component to be used as standalone and inside a picker: ```tsx -import { useDateManager } from '@base-ui/x-date-pickers/managers'; -import { useIsInsidePicker } from '@base-ui/x-date-pickers/hooks'; -import { PickerField } from '@base-ui/x-date-pickers/PickerField'; +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { useIsInsidePicker } from '@base-ui-components/react-x-date-pickers/hooks'; +import { PickerField } from '@base-ui-components/react-x-date-pickers/picker-field'; function CustomDateField(props) { const manager = useDateManager(); @@ -147,11 +147,11 @@ The concept of slots does not fit this use case very well, but the exploration o #### Inside an unstyled picker -The custom field can also be used inside a picker built with the composable `Picker.*` component from `@base-ui/x-date-pickers/Picker`: +The custom field can also be used inside a picker built with the composable `Picker.*` component from `@base-ui-components/react-x-date-pickers/picker`: ```tsx -import { useDateManager } from '@base-ui/x-date-pickers/managers'; -import { Picker } from '@base-ui/x-date-pickers/Picker'; +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; function CustomDatePicker(props) { const manager = useDateManager(); @@ -171,8 +171,8 @@ function CustomDatePicker(props) { The user can also inline their field if they want: ```tsx -import { useDateManager } from '@base-ui/x-date-pickers/managers'; -import { Picker } from '@base-ui/x-date-pickers/Picker'; +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; function CustomDatePicker(props) { const manager = useDateManager(); @@ -256,8 +256,8 @@ There is a POC of this in [#15505](https://github.com/mui/mui-x/pull/15505). The user can use the `` component to add a button to clear the value: ```tsx -import { useDateManager } from '@base-ui/x-date-pickers/managers'; -import { PickerField } from '@base-ui/x-date-pickers/PickerField'; +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { PickerField } from '@base-ui-components/react-x-date-pickers/picker-field'; function CustomDateField(props) { const manager = useDateManager(); diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index 3eb6318eb7c91..db3e59e8b0f64 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -16,6 +16,10 @@ This page extends the initial proposal made in [#14718](https://github.com/mui/m ### Without Material UI ```tsx +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; + function CustomDatePicker(props) { const manager = useDateManager(); @@ -36,17 +40,33 @@ function CustomDatePicker(props) { ); } + +; ``` ### With Material UI -TODO +The user can use the `` component: + +```tsx +import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker'; + +; +``` + +:::success +This component could be renamed `` to better match its behavior. +::: ## Basic usage in a Dialog ### Without Material UI ```tsx +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Dialog } from '@base-ui-components/react/dialog'; + function CustomDatePicker(props) { const manager = useDateManager(); @@ -63,11 +83,21 @@ function CustomDatePicker(props) { ); } + +; ``` ### With Material UI -TODO +```tsx +import { MobileDatePicker } from '@mui/x-date-pickers/MobileDatePicker'; + +; +``` + +:::success +This component could be renamed `` to better match its behavior. +::: ## Basic responsive usage @@ -76,6 +106,12 @@ TODO If the library does not provide any higher level utilities to create a responsive picker and sticks with "1 React component = 1 DOM element", here is what a responsive picker could look like: ```tsx +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { useMediaQuery } from '@base-ui-utils/useMediaQuery'; // not sure how the util package will be named +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; +import { Dialog } from '@base-ui-components/react/dialog'; + function CustomDatePicker(props) { const manager = useDateManager(); const isDesktop = useMediaQuery('@media (pointer: fine)', { @@ -211,7 +247,7 @@ The example below uses the `Tabs` component from Base UI as an example: ```tsx import { Tabs } from '@base-ui-components/react/tabs'; -import { Picker } from '@base-ui/x-date-pickers/Picker'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; @@ -267,7 +303,7 @@ To support the `isValid` param of the Material UI shortcut, a `useIsValidValue` Without it, it's not trivial to use `useValidation` since it requires a value and params like the validation props or the timezone. ```tsx -import { useIsValueValid } from '@base-ui/x-date-pickers/hooks'; +import { useIsValueValid } from'@base-ui-components/react-x-date-pickers/hooks'; const isValueValid = useIsValueValid(); From c848b58328d65e4004f0492964c4b86e49deba9f Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 09:30:55 +0100 Subject: [PATCH 16/46] Work on the picker page --- docs/data/date-pickers/rfc/picker.md | 70 ++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index db3e59e8b0f64..53b396279e164 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -15,6 +15,10 @@ This page extends the initial proposal made in [#14718](https://github.com/mui/m ### Without Material UI +#### With Base UI `Popover.*` components + +The user can use the `Picker.*` components in combination with the `Popover.*` components from `@base-ui-components/react` to build a picker: + ```tsx import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; @@ -44,6 +48,38 @@ function CustomDatePicker(props) { ; ``` +#### With React Aria `` components + +Even if Base UI will be the solution presented in the doc to connect the field and the view, nothing prevents the user from using another library: + +```tsx +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Dialog, DialogTrigger, Button, Popover } from 'react-aria-components'; + +function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + + + {/** See field documentation */} + + + + + {/** See calendar documentation */} + + + + + ); +} + +; +``` + ### With Material UI The user can use the `` component: @@ -62,6 +98,8 @@ This component could be renamed `` to better match its beha ### Without Material UI +The user can use the `Picker.*` components in combination with the `Modal.*` components from `@base-ui-components/react` to build a picker: + ```tsx import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; @@ -153,7 +191,13 @@ function CustomDatePicker(props) { ### With Material UI -TODO +The user can use the `` component: + +```tsx +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +; +``` ## Usage with date and time views @@ -163,6 +207,9 @@ The user can use the `` component to conditionally render th This is needed to build date time pickers: ```tsx +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; + {/** See calendar documentation */} @@ -172,7 +219,7 @@ This is needed to build date time pickers: {/** See digital clock documentation (not available yet) */} - +; ``` ### With Material UI @@ -186,6 +233,9 @@ TODO The user can use the ``, `` and `` components to create an action bar and interact with the value: ```tsx +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; + {/** See calendar documentation */}
@@ -209,17 +259,23 @@ TODO The user can use the `` component to create a toolbar for its picker: ```tsx +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; +
{/** See calendar documentation */} -
+; ``` The toolbar can also be used to switch between views thanks to the `` component: ```tsx +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; +
@@ -230,7 +286,7 @@ The toolbar can also be used to switch between views thanks to the `
{/** See calendar documentation */} -
+; ``` ### With Material UI @@ -285,6 +341,9 @@ TODO The user can use the `` component to create a shortcut UI: ```tsx +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Popover } from '@base-ui-components/react/popover'; +
@@ -295,7 +354,7 @@ The user can use the `` component to create a shortcut UI:
{/** See calendar documentation */} -
+; ``` :::success @@ -304,6 +363,7 @@ Without it, it's not trivial to use `useValidation` since it requires a value an ```tsx import { useIsValueValid } from'@base-ui-components/react-x-date-pickers/hooks'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; const isValueValid = useIsValueValid(); From f5438ed961b87e75e2452fdee2525a703122c2aa Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 28 Nov 2024 13:05:52 +0100 Subject: [PATCH 17/46] Work on the calendar page --- docs/data/date-pickers/rfc/calendar.md | 237 +++++++++++++++---------- docs/data/date-pickers/rfc/picker.md | 1 + 2 files changed, 143 insertions(+), 95 deletions(-) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc/calendar.md index 43d20048c8a06..7388684048f67 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc/calendar.md @@ -15,7 +15,7 @@ This page extends the initial proposal made in [#15598](https://github.com/mui/m ### Without Material UI -The user can use the `Calendar.Days.*` components to create a grid of days and the `Calendar.Header.*` to create a header to navigate across the months: +The user can use the `Calendar.Days.*` components to create a grid of days: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -140,32 +140,7 @@ Once the `Calendar.*` unstyled component is ready, the `` should ```tsx -
- {({ view }) => ( - -
- - - - - -
-
- - - - - -
-
- )} -
+
{/** See calendar header documentation */}
@@ -197,31 +172,6 @@ Once the `Calendar.*` unstyled component is ready, the `` should
``` -:::success -The header above tries to replicate the behavior of a MD3 Date Picker. -Today's `` header would look as follow: - -```tsx -
- {({ view }) => ( - - - {view === 'year' ? '▲' : '▼'} - - -
- - -
-
-
- )} -
-``` - -But the current behavior is not great, once the user is on the `year` view, there is no way to go back to the `day` view without picking a value. -::: - ### With Material UI :::success @@ -240,62 +190,93 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; When MD3 is supported, the default views of `` should probably be `['year', 'month', 'day']` ::: -## Display week number +## Calendar header ### Without Material UI -The user can use the `` and `` components to add a column to the grid: +The user can use the ``, `` and `` to build basically any kind of header they could think of: + +#### Very basic header (without month and year views) ```tsx - - - {({ days }) => ( - - # - {days.map((day) => ( - - ))} - - )} - - - {({ weeks }) => - weeks.map((week) => ( - - {({ days }) => ( - - - {days.map((day) => ( - - ))} - - )} - - )) - } - - +function CalendarHeader() { + return ( +
+ + + +
+ ); +} ``` -### With Material UI - -:::success -No DX change here compared to today -::: - -The user can use the `` with the `displayWeekNumber` prop: +#### MD2 header (MUI X implementation) ```tsx -import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; +import { + Calendar, + useCalendarContext, +} from '@base-ui-components/react-x-date-pickers/calendar'; -; +function CalendarHeader() { + const { view } = useCalendarContext(); + + return ( +
+ + + {view === 'year' ? '▲' : '▼'} + + +
+ + +
+
+
+ ); +} ``` -## Override part of the UI +#### MD3 header + +```tsx +function CalendarHeader() { + const { view } = useCalendarContext(); + return ( +
+
+ {view === 'day' && ( + + )} + + + + {view === 'day' && } +
+
+ {view === 'day' && ( + + )} + + + + {view === 'day' && } +
+
+ ); +} +``` ### With Material UI -Users can use slots to override part of the UI in self-contained components: +The user can use slots to override part of the UI in self-contained components: ```tsx @@ -325,12 +306,12 @@ The `` component can be built in a few different ways: :::success The `calendarHeader` slot does not receive `currentMonth` as a prop but instead access it using `useCalendarContext()`. - That way, this components can be composed more freely, it now only has to be mounted inside ``. + That way, the API is consistent with and without Material UI, and if we introduce a composable version with Material UI in the future it will work fine. ::: 2. Using the primitives exposed by `@base-ui-components/react-x-date-pickers/calendar`: - If the user wants to totally own the styling of this part of the UI (because he wants to build something really different from Material UI), he can use components like `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: + If the user wants to totally own the styling of this part of the UI (because the UI is really different from the default one), he can use components like `` or `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -338,7 +319,9 @@ The `` component can be built in a few different ways: function CustomCalendarHeader() { return (
+ +
); } @@ -414,6 +397,57 @@ The `` component can be built in a few different ways: ::: +## Display week number + +### Without Material UI + +The user can use the `` and `` components to add a column to the grid: + +```tsx + + + {({ days }) => ( + + # + {days.map((day) => ( + + ))} + + )} + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => ( + + + {days.map((day) => ( + + ))} + + )} + + )) + } + + +``` + +### With Material UI + +:::success +No DX change here compared to today +::: + +The user can use the `` with the `displayWeekNumber` prop: + +```tsx +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; + +; +``` + ## Anatomy of `Calendar.*` ### `Calendar.Root` @@ -492,6 +526,19 @@ Formats the value based on the provided format. - `format`: `string` - **required** +### `Calendar.ContextValue` + +Utility component to access the calendar public context. +Doesn't render a DOM node (it does not have a `render` prop either). + +:::success +The user can also use `useCalendarContext()`, but a component allows to not create a dedicated component to access things close from `` +::: + +#### Props + +- `children`: `(contextValue: CalendarContextValue) => React.ReactNode` + ### `Calendar.GoToMonth` Renders a button to go to the previous or the next month. diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc/picker.md index 53b396279e164..b042873dda18a 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc/picker.md @@ -455,6 +455,7 @@ Doesn't render a DOM node (it does not have a `render` prop either). ### `Picker.ContextValue` Utility component to access the picker public context. +Doesn't render a DOM node (it does not have a `render` prop either). :::success The user can also use `usePickerContext()`, but a component allows to not create a dedicated component to access things close from `` From b705092cd0712b1a33c9ffca7cbe529d6bece51e Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 13:44:12 +0100 Subject: [PATCH 18/46] Work --- .../{rfc/calendar.md => rfc-calendar.md} | 80 +++++-- docs/data/date-pickers/rfc-digital-clock.md | 139 ++++++++++++ .../{rfc/field.md => rfc-field.md} | 8 +- .../{rfc/picker.md => rfc-picker.md} | 199 ++++++++++++------ docs/data/pages.ts | 7 +- .../{rfc/calendar.js => rfc-calendar.js} | 2 +- .../x/react-date-pickers/rfc-digital-clock.js | 7 + .../{rfc/field.js => rfc-field.js} | 2 +- .../{rfc/picker.js => rfc-picker.js} | 2 +- 9 files changed, 349 insertions(+), 97 deletions(-) rename docs/data/date-pickers/{rfc/calendar.md => rfc-calendar.md} (89%) create mode 100644 docs/data/date-pickers/rfc-digital-clock.md rename docs/data/date-pickers/{rfc/field.md => rfc-field.md} (97%) rename docs/data/date-pickers/{rfc/picker.md => rfc-picker.md} (74%) rename docs/pages/x/react-date-pickers/{rfc/calendar.js => rfc-calendar.js} (75%) create mode 100644 docs/pages/x/react-date-pickers/rfc-digital-clock.js rename docs/pages/x/react-date-pickers/{rfc/field.js => rfc-field.js} (75%) rename docs/pages/x/react-date-pickers/{rfc/picker.js => rfc-picker.js} (75%) diff --git a/docs/data/date-pickers/rfc/calendar.md b/docs/data/date-pickers/rfc-calendar.md similarity index 89% rename from docs/data/date-pickers/rfc/calendar.md rename to docs/data/date-pickers/rfc-calendar.md index 7388684048f67..bf57c1d8aa43f 100644 --- a/docs/data/date-pickers/rfc/calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -28,13 +28,19 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- {({ days }) => days.map((day) => )} + {({ days }) => + days.map((day) => ) + } {({ weeks }) => weeks.map((week) => ( - {({ days }) => days.map((day) => )} + {({ days }) => + days.map((day) => ( + + )) + } )) } @@ -74,7 +80,9 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
{({ months }) => - months.map((month) => ) + months.map((month) => ( + + )) }
; @@ -110,7 +118,11 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - {({ years }) => years.map((year) => )} + {({ years }) => + years.map((year) => ( + + )) + } ; ``` @@ -144,13 +156,19 @@ Once the `Calendar.*` unstyled component is ready, the `` should - {({ days }) => days.map((day) => )} + {({ days }) => + days.map((day) => ) + } {({ weeks }) => weeks.map((week) => ( - - {({ days }) => days.map((day) => )} + + {({ days }) => + days.map((day) => ( + + )) + } )) } @@ -160,13 +178,19 @@ Once the `Calendar.*` unstyled component is ready, the `` should {({ months }) => - months.map((month) => ) + months.map((month) => ( + + )) } - {({ years }) => years.map((year) => )} + {({ years }) => + years.map((year) => ( + + )) + } @@ -410,7 +434,7 @@ The user can use the `` and ` # {days.map((day) => ( - + ))} )} @@ -418,12 +442,12 @@ The user can use the `` and ` {({ weeks }) => weeks.map((week) => ( - + {({ days }) => ( {days.map((day) => ( - + ))} )} @@ -593,11 +617,13 @@ Top level component for the `Calendar.Days.*` components. Renders the header of the day grid. -It expects a function as its children, which has the list of days as a parameter: +It expects a function as its children, which receives the list of days to render as a parameter: ```tsx - {({ days }) => days.map((day) => )} + {({ days }) => + days.map((day) => ) + } ``` @@ -629,11 +655,13 @@ Renders the header of the week number column. Renders the content all the days in a month (it is the DOM element that should contain all the weeks). -It expects a function as its children, which has the list of weeks to render as a parameter: +It expects a function as its children, which receives the list of weeks to render as a parameter: ```tsx - {({ weeks }) => weeks.map((week) => )} + {({ weeks }) => + weeks.map((week) => ) + } ``` @@ -651,11 +679,13 @@ Maybe it should be named ``. Renders the content all the days in a week. -It expects a function as its children, which has the list of days to render and the week number as a parameter: +It expects a function as its children, which receives the list of days to render and the week number as a parameter: ```tsx - {({ days }) => days.map((day) => )} + {({ days }) => + days.map((day) => ) + } ``` @@ -687,11 +717,15 @@ Renders the number of the current week. Top level component for the `Calendar.Months.*` components. -It expects a function as its children, which has the list of the months as a parameter: +It expects a function as its children, which receives the list of the months to render as a parameter: ```tsx - {({ months }) => months.map((month) => )} + {({ months }) => + months.map((month) => ( + + )) + } ``` @@ -742,11 +776,13 @@ Renders the cell for a single month. Top level component for the `Calendar.Years.*` components. -It expects a function as its children, which has the list of the years as a parameter: +It expects a function as its children, which receives the list of years to render as a parameter: ```tsx - {({ years }) => years.map((year) => )} + {({ years }) => + years.map((year) => ) + } ``` diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md new file mode 100644 index 0000000000000..e4abf815e0b70 --- /dev/null +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -0,0 +1,139 @@ +--- +productId: x-date-pickers +title: DX - Digital Clock +--- + +# Digital Clock + +

This page describes how people can use time views with Material UI and how they can build custom time views.

+ +## Usage with single section + +### Without Material UI + +The user can use the `` component to list all the time options in a flat list: + +```tsx + + + {({ items }) => + items.map((item) => ) + } + + +``` + +### With Material UI + +TODO + +## Usage with multi section + +### Without Material UI + +The user can use the `` component to list all the time options with one column per view: + +```tsx + + + + {(hours) => + hours.map((hour) => ) + } + + + {(minutes) => + minutes.map((minute) => ( + + )) + } + + + {(seconds) => + seconds.map((second) => ( + + )) + } + + + {(meridiems) => + meridiems.map((meridiem) => ( + + )) + } + + + +``` + +### With Material UI + +TODO + +## Anatomy of `DigitalClock.*` + +### `DigitalClock.Root` + +Top level component that wraps the other components. + +#### Props + +- Extends `React.HTMLAttributes` + +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. + + Same typing and behavior as today. + +- **Validation props**: `maxTime`, `minTime`, `disableFuture`, `disablePast`, `shouldDisableTime`, `timeSteps`. + + Same typing and behavior as today. + +- **Form props**: `disabled`, `readOnly`. + + Same typing and behavior as today. + +- `autoFocus`: `boolean` + +- `ampm`: `boolean`, default: `utils.is12HourCycleInCurrentLocale()` + +:::success +All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. + +That way, users only have to pass the props specific to the calendar to the `DigitalClock.*` components: + +```tsx + + {/** See the field documentation */} + + + + + TODO FIX + + {/** See demo above */} + + + + + +``` + +::: + +### `DigitalClock.ContentForSingleSection` + +#### Props + +TODO + +### `DigitalClock.ContentForMultiSection` + +#### Props + +TODO + +### `DigitalClock.Item` + +#### Props + +TODO diff --git a/docs/data/date-pickers/rfc/field.md b/docs/data/date-pickers/rfc-field.md similarity index 97% rename from docs/data/date-pickers/rfc/field.md rename to docs/data/date-pickers/rfc-field.md index 271c3a2351259..b2b938a21bafa 100644 --- a/docs/data/date-pickers/rfc/field.md +++ b/docs/data/date-pickers/rfc-field.md @@ -27,7 +27,7 @@ function CustomDateField(props) { {({ sections }) => sections.map((section) => ( - + @@ -354,12 +354,14 @@ That way, users only have to pass the props specific to the field to the `Picker It would expend `Field.Control` from `@base-ui-components/react/Field`. -It expects a function as its children, which has the list of sections as a parameter: +It expects a function as its children, which receives the list of sections to render as a parameter: ```tsx {({ sections }) => - sections.map((section) => ) + sections.map((section) => ( + + )) } ``` diff --git a/docs/data/date-pickers/rfc/picker.md b/docs/data/date-pickers/rfc-picker.md similarity index 74% rename from docs/data/date-pickers/rfc/picker.md rename to docs/data/date-pickers/rfc-picker.md index b042873dda18a..e26fd3f840934 100644 --- a/docs/data/date-pickers/rfc/picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -28,20 +28,22 @@ function CustomDatePicker(props) { const manager = useDateManager(); return ( - - - - {/** See field documentation */} - 📅 - - - - - {/** See calendar documentation */} - - - - + + {({ open, setOpen }) => ( + + + {/** See field documentation */} + 📅 + + + + + {/** See calendar documentation */} + + + + )} + ); } @@ -61,19 +63,21 @@ function CustomDatePicker(props) { const manager = useDateManager(); return ( - - - - {/** See field documentation */} - - - - - {/** See calendar documentation */} - - - - + + {({ open, setOpen }) => ( + + + {/** See field documentation */} + + + + + {/** See calendar documentation */} + + + + )} + ); } @@ -98,7 +102,9 @@ This component could be renamed `` to better match its beha ### Without Material UI -The user can use the `Picker.*` components in combination with the `Modal.*` components from `@base-ui-components/react` to build a picker: +#### With Base UI `Dialog.*` components + +The user can use the `Picker.*` components in combination with the `Dialog.*` components from `@base-ui-components/react` to build a picker: ```tsx import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; @@ -109,16 +115,54 @@ function CustomDatePicker(props) { const manager = useDateManager(); return ( - - - {/** See field documentation */} - 📅 - - - - {/** See calendar documentation */} - - + + {({ open, setOpen }) => ( + + + {/** See field documentation */} + 📅 + + + + {/** See calendar documentation */} + + + )} + + ); +} + +; +``` + +#### With Mantine `` component + +The user can use a Modal that expect different props for its lifecycle: + +```tsx +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Modal, Button } from '@mantine/core'; + +function CustomDatePicker(props) { + const manager = useDateManager(); + + return ( + + {({ open, openPicker, closePicker }) => ( + + + {/** See field documentation */} + + + + + {/** See calendar documentation */} + + + + )} + ); } @@ -145,7 +189,7 @@ If the library does not provide any higher level utilities to create a responsiv ```tsx import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; -import { useMediaQuery } from '@base-ui-utils/useMediaQuery'; // not sure how the util package will be named +import { useMediaQuery } from '@base-ui-components/react-utils/useMediaQuery'; // not sure how the util package will be named import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Popover } from '@base-ui-components/react/popover'; import { Dialog } from '@base-ui-components/react/dialog'; @@ -156,35 +200,45 @@ function CustomDatePicker(props) { defaultMatches: true, }); - const wrapView = (viewNode: React.ReactNode) => { - if (variant === 'mobile') { - return {viewNode}; - } + const field = ( + + {/** See field documentation */} + {isDesktop ? ( + 📅 + ) : ( + 📅 + )} + + ); - return ( - - {viewNode} - - ); - }; + const view = {/** See calendar documentation */}; - return ( - + if (isDesktop) { + return ( - - {/** See field documentation */} - {variant === 'mobile' ? ( - 📅 - ) : ( - 📅 - )} - - - {wrapView( - {/** See calendar documentation */}, + {({ open, setOpen }) => ( + + {field} + + + {view} + + )} - + ); + } + + return ( + + {({ open, setOpen }) => ( + + {field} + + {view} + + )} + ); } ``` @@ -273,8 +327,8 @@ import { Popover } from '@base-ui-components/react/popover'; The toolbar can also be used to switch between views thanks to the `` component: ```tsx -import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Popover } from '@base-ui-components/react/popover'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker';
@@ -303,9 +357,10 @@ The example below uses the `Tabs` component from Base UI as an example: ```tsx import { Tabs } from '@base-ui-components/react/tabs'; +import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; - + {({ view }) => ( @@ -327,7 +382,7 @@ import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; )} {/** See calendar documentation */} -; +; ``` ### With Material UI @@ -399,6 +454,16 @@ TODO ### `Picker.Root` +Top level component that wraps the other components. + +It expects a function as its children, which receives the context value as a parameter: + +```tsx + + {({ open, setOpen }) => } + +``` + #### Props - `manager`: `PickerManager` - **required** @@ -407,6 +472,8 @@ TODO See [#15395](https://github.com/mui/mui-x/issues/15395) for context. ::: +- `children`: `(contextValue: PickerContextValue) => React.ReactNode` + - **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. Same typing and behavior as today. diff --git a/docs/data/pages.ts b/docs/data/pages.ts index fb705db73cc76..74300d468f845 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -256,9 +256,10 @@ const pages: MuiPage[] = [ pathname: '/x/react-date-pickers/rfc', title: 'Date and Time Pickers - new DX', children: [ - { pathname: '/x/react-date-pickers/rfc/field', title: 'Field' }, - { pathname: '/x/react-date-pickers/rfc/calendar', title: 'Calendar' }, - { pathname: '/x/react-date-pickers/rfc/picker', title: 'Picker' }, + { pathname: '/x/react-date-pickers/rfc-field', title: 'Field' }, + { pathname: '/x/react-date-pickers/rfc-calendar', title: 'Calendar' }, + { pathname: '/x/react-date-pickers/rfc-digital-clock', title: 'DigitalClock' }, + { pathname: '/x/react-date-pickers/rfc-picker', title: 'Picker' }, ], }, { diff --git a/docs/pages/x/react-date-pickers/rfc/calendar.js b/docs/pages/x/react-date-pickers/rfc-calendar.js similarity index 75% rename from docs/pages/x/react-date-pickers/rfc/calendar.js rename to docs/pages/x/react-date-pickers/rfc-calendar.js index 79ffed51ba95a..702b6d21560ee 100644 --- a/docs/pages/x/react-date-pickers/rfc/calendar.js +++ b/docs/pages/x/react-date-pickers/rfc-calendar.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from 'docsx/data/date-pickers/rfc/calendar.md?muiMarkdown'; +import * as pageProps from 'docsx/data/date-pickers/rfc-calendar.md?muiMarkdown'; export default function Page() { return ; diff --git a/docs/pages/x/react-date-pickers/rfc-digital-clock.js b/docs/pages/x/react-date-pickers/rfc-digital-clock.js new file mode 100644 index 0000000000000..9126fc2941f66 --- /dev/null +++ b/docs/pages/x/react-date-pickers/rfc-digital-clock.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/rfc-digital-clock.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/x/react-date-pickers/rfc/field.js b/docs/pages/x/react-date-pickers/rfc-field.js similarity index 75% rename from docs/pages/x/react-date-pickers/rfc/field.js rename to docs/pages/x/react-date-pickers/rfc-field.js index c305b80976aa6..afb95e4a78d36 100644 --- a/docs/pages/x/react-date-pickers/rfc/field.js +++ b/docs/pages/x/react-date-pickers/rfc-field.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from 'docsx/data/date-pickers/rfc/field.md?muiMarkdown'; +import * as pageProps from 'docsx/data/date-pickers/rfc-field.md?muiMarkdown'; export default function Page() { return ; diff --git a/docs/pages/x/react-date-pickers/rfc/picker.js b/docs/pages/x/react-date-pickers/rfc-picker.js similarity index 75% rename from docs/pages/x/react-date-pickers/rfc/picker.js rename to docs/pages/x/react-date-pickers/rfc-picker.js index 4e937b03b8b75..fe3714e044859 100644 --- a/docs/pages/x/react-date-pickers/rfc/picker.js +++ b/docs/pages/x/react-date-pickers/rfc-picker.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from 'docsx/data/date-pickers/rfc/picker.md?muiMarkdown'; +import * as pageProps from 'docsx/data/date-pickers/rfc-picker.md?muiMarkdown'; export default function Page() { return ; From 137cdb8d8fc7c0423a4732cf378437243044f213 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 15:23:09 +0100 Subject: [PATCH 19/46] Work --- docs/data/date-pickers/rfc-calendar.md | 125 +++++++++----- docs/data/date-pickers/rfc-digital-clock.md | 173 +++++++++++++++----- docs/data/date-pickers/rfc-picker.md | 2 +- 3 files changed, 220 insertions(+), 80 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index bf57c1d8aa43f..108edf58dac39 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -81,7 +81,7 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ months }) => months.map((month) => ( - + )) } @@ -119,9 +119,7 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ years }) => - years.map((year) => ( - - )) + years.map((year) => ) } ; @@ -151,49 +149,43 @@ Once the `Calendar.*` unstyled component is ready, the `` should ### Without Material UI ```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; +
{/** See calendar header documentation */}
- - - - {({ days }) => - days.map((day) => ) - } - - - {({ weeks }) => - weeks.map((week) => ( - - {({ days }) => - days.map((day) => ( - - )) - } - - )) - } - - - - - - {({ months }) => - months.map((month) => ( - - )) + + + {({ days }) => + days.map((day) => ) } - - - - - {({ years }) => - years.map((year) => ( - + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => + days.map((day) => ( + + )) + } + )) } - - -
+ + + + {({ months }) => + months.map((month) => ( + + )) + } + + + {({ years }) => + years.map((year) => ) + } + +; ``` ### With Material UI @@ -223,6 +215,8 @@ The user can use the ``, `` and #### Very basic header (without month and year views) ```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + function CalendarHeader() { return (
@@ -265,6 +259,8 @@ function CalendarHeader() { #### MD3 header ```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + function CalendarHeader() { const { view } = useCalendarContext(); return ( @@ -298,6 +294,47 @@ function CalendarHeader() { } ``` +#### Header with dropdown for months and years + +The user can create a custom header where the month and the year editing is done through a menu, while the day calendar is always visible below: + +```tsx +import { Menu } from '@base-ui-components/react/menu'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + +function CalendarHeader() { + const { view } = useCalendarContext(); + return ( +
+ + } /> + + }> + {({ months }) => + months.map((month) => ( + + )) + } + + + + + } /> + + }> + {({ years }) => + years.map((year) => ( + + )) + } + + + +
+ ); +} +``` + ### With Material UI The user can use slots to override part of the UI in self-contained components: @@ -762,6 +799,8 @@ It expects a function as its children, which receives the list of the months to The MVP could probably not contain any keyboard navigation. ::: +- `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"month"`. + ### `Calendar.Months.Cell` Renders the cell for a single month. @@ -801,6 +840,8 @@ It expects a function as its children, which receives the list of years to rende See the equivalent prop in `Calendar.Months.Root` for more details. ::: +- `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"year"`. + ### `Calendar.Years.Cell` Renders the cell for a single year. diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index e4abf815e0b70..93ad2effb3e37 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -7,19 +7,21 @@ title: DX - Digital Clock

This page describes how people can use time views with Material UI and how they can build custom time views.

-## Usage with single section +## Single section ### Without Material UI -The user can use the `` component to list all the time options in a flat list: +The user can use the `` component to list all the time options in a flat list: ```tsx - - {({ items }) => - items.map((item) => ) + + {({ options }) => + options.map((option) => ( + + )) } - + ``` @@ -27,42 +29,139 @@ The user can use the `` component to lis TODO -## Usage with multi section +## Multi section (meridiem) ### Without Material UI -The user can use the `` component to list all the time options with one column per view: +The user can use the ``, `` and `` components to list all the time options with one column per view: ```tsx - - - - {(hours) => - hours.map((hour) => ) - } - - - {(minutes) => - minutes.map((minute) => ( - - )) - } - - - {(seconds) => - seconds.map((second) => ( - - )) - } - - - {(meridiems) => - meridiems.map((meridiem) => ( - - )) - } - - + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + +``` + +## Multi section (meridiem) + +### Without Material UI + +The user can use the ``, `` and `` components to list all the time options with one column per view: + +```tsx + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + +``` + +### With Material UI + +TODO + +## Multi section (no meridiem) + +### Without Material UI + +The user can use the ``, ``, `` and `` components to list all the time options with one column per view: + +```tsx + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + +``` + +### With Material UI + +TODO + +## Multi section (auto meridiem) + +### Without Material UI + +The user can use the ``, ``, `` and `` components to list all the time options with one column per view: + +```tsx + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + ``` diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index e26fd3f840934..267957fc3b150 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -20,9 +20,9 @@ This page extends the initial proposal made in [#14718](https://github.com/mui/m The user can use the `Picker.*` components in combination with the `Popover.*` components from `@base-ui-components/react` to build a picker: ```tsx +import { Popover } from '@base-ui-components/react/popover'; import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; -import { Popover } from '@base-ui-components/react/popover'; function CustomDatePicker(props) { const manager = useDateManager(); From 7ba4bbdbeed3e3401f7be9beb1a19ead515a8123 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 15:34:46 +0100 Subject: [PATCH 20/46] Work --- docs/data/date-pickers/rfc-digital-clock.md | 63 ++++++--------------- 1 file changed, 16 insertions(+), 47 deletions(-) diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 93ad2effb3e37..f0fe4371930e0 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -29,14 +29,14 @@ The user can use the `` component to list all the time o TODO -## Multi section (meridiem) +## Multi section (no meridiem) ### Without Material UI The user can use the ``, `` and `` components to list all the time options with one column per view: ```tsx - + {({ options }) => options.map((option) => ( @@ -51,31 +51,29 @@ The user can use the ``, ` - - {({ options }) => - options.map((option) => ( - - )) - } - ``` +### With Material UI + +TODO + ## Multi section (meridiem) ### Without Material UI -The user can use the ``, `` and `` components to list all the time options with one column per view: +The user can use the `` component to add a column to edit this section. +It should be used in combination with the `` component: ```tsx - - + + {({ options }) => options.map((option) => ( )) } - + {({ options }) => options.map((option) => ( @@ -97,14 +95,14 @@ The user can use the ``, ``, ``, `` and `` components to list all the time options with one column per view: +The user can use the `` component to add a column to edit this section: ```tsx - + {({ options }) => options.map((option) => ( @@ -119,42 +117,13 @@ The user can use the ``, ` - - {({ options }) => - options.map((option) => ( - - )) - } - - -``` - -### With Material UI - -TODO - -## Multi section (auto meridiem) - -### Without Material UI - -The user can use the ``, ``, `` and `` components to list all the time options with one column per view: - -```tsx - - - {({ options }) => - options.map((option) => ( - - )) - } - - + {({ options }) => options.map((option) => ( )) } - + {({ options }) => options.map((option) => ( From 3cfb57270804dee91e3da6215a01f3aa6900e7a9 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 15:37:35 +0100 Subject: [PATCH 21/46] Work --- docs/data/date-pickers/rfc-digital-clock.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index f0fe4371930e0..29f5431f64adf 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -162,8 +162,6 @@ Top level component that wraps the other components. - `autoFocus`: `boolean` -- `ampm`: `boolean`, default: `utils.is12HourCycleInCurrentLocale()` - :::success All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. @@ -175,11 +173,8 @@ That way, users only have to pass the props specific to the calendar to the `Dig - - TODO FIX - - {/** See demo above */} - + + {/** See demo above */} From a1c885d260ed619d468274a3764c83efcfe3bd8b Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 15:49:11 +0100 Subject: [PATCH 22/46] Work --- docs/data/date-pickers/rfc-calendar.md | 178 ++++++++++---------- docs/data/date-pickers/rfc-digital-clock.md | 30 +++- docs/data/pages.ts | 2 +- 3 files changed, 118 insertions(+), 92 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 108edf58dac39..c5e224f099adf 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -15,7 +15,7 @@ This page extends the initial proposal made in [#15598](https://github.com/mui/m ### Without Material UI -The user can use the `Calendar.Days.*` components to create a grid of days: +The user can use the ``, ``, ``, ``, `` and `` components to create a grid of days: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -26,26 +26,28 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- - + + {({ days }) => - days.map((day) => ) + days.map((day) => ( + + )) } - - + + {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => ( - + )) } - + )) } - - + + ; ``` @@ -67,7 +69,7 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; ### Without Material UI -The user can use the `Calendar.Months.*` components to create a grid of months and the `Calendar.Header.*` to create a header to navigate across the years: +The user can use the `` and `` components to create a grid of months and utility components like `` and `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -78,13 +80,13 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- + {({ months }) => months.map((month) => ( - + )) } - + ; ``` @@ -111,17 +113,17 @@ Once the `Calendar.*` unstyled component is ready, the `` shoul ### Without Material UI -The user can use the `Calendar.Years.*` components to create a grid of years: +The user can use the `` and `` components to create a grid of years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - + {({ years }) => - years.map((year) => ) + years.map((year) => ) } - + ; ``` @@ -153,38 +155,40 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
{/** See calendar header documentation */}
- - + + {({ days }) => - days.map((day) => ) + days.map((day) => ( + + )) } - - + + {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => ( - + )) } - + )) } - - - + + + {({ months }) => months.map((month) => ( - + )) } - - + + {({ years }) => - years.map((year) => ) + years.map((year) => ) } - +
; ``` @@ -309,25 +313,25 @@ function CalendarHeader() { } /> - }> + }> {({ months }) => months.map((month) => ( - + )) } - + } /> - }> + }> {({ years }) => years.map((year) => ( - + )) } - +
@@ -462,37 +466,37 @@ The `` component can be built in a few different ways: ### Without Material UI -The user can use the `` and `` components to add a column to the grid: +The user can use the `` and `` components to add a column to the grid: ```tsx - - + + {({ days }) => ( - # + # {days.map((day) => ( - + ))} )} - - + + {({ weeks }) => weeks.map((week) => ( - + {({ days }) => ( - + {days.map((day) => ( - + ))} )} - + )) } - - + + ``` ### With Material UI @@ -545,9 +549,7 @@ That way, users only have to pass the props specific to the calendar to the `Cal - - {/** See demo above */} - + {/** See demo above */} @@ -640,9 +642,9 @@ Renders a button to set the current visible view. - `target`: `TView` -### `Calendar.Days.Root` +### `Calendar.Days` -Top level component for the `Calendar.Days.*` components. +Top level component for the `"day"` view. #### Props @@ -650,18 +652,18 @@ Top level component for the `Calendar.Days.*` components. - `fixedWeekNumber`: `number` -### `Calendar.Days.Header` +### `Calendar.DaysHeader` Renders the header of the day grid. It expects a function as its children, which receives the list of days to render as a parameter: ```tsx - + {({ days }) => - days.map((day) => ) + days.map((day) => ) } - + ``` #### Props @@ -670,7 +672,7 @@ It expects a function as its children, which receives the list of days to render - `children`: `(params: { days: PickerValidDate[] }) => React.ReactNode` -### `Calendar.Days.HeaderCell` +### `Calendar.DaysHeaderCell` Renders the header of a day in the week. @@ -680,7 +682,7 @@ Renders the header of a day in the week. - `value`: `PickerValidDate` - **required**. -### `Calendar.Days.WeekNumberHeaderCell` +### `Calendar.DaysWeekNumberHeaderCell` Renders the header of the week number column. @@ -688,18 +690,18 @@ Renders the header of the week number column. - Extends `React.HTMLAttributes` -### `Calendar.Days.Content` +### `Calendar.DaysContent` Renders the content all the days in a month (it is the DOM element that should contain all the weeks). It expects a function as its children, which receives the list of weeks to render as a parameter: ```tsx - + {({ weeks }) => - weeks.map((week) => ) + weeks.map((week) => ) } - + ``` :::success @@ -712,18 +714,18 @@ Maybe it should be named ``. - `children`: `(params: { weeks: PickerValidDate[] }) => React.ReactNode` -### `Calendar.Days.WeekRow` +### `Calendar.DaysWeekRow` Renders the content all the days in a week. It expects a function as its children, which receives the list of days to render and the week number as a parameter: ```tsx - + {({ days }) => - days.map((day) => ) + days.map((day) => ) } - + ``` #### Props @@ -734,7 +736,7 @@ It expects a function as its children, which receives the list of days to render - `children`: `(params: { days: PickerValidDate[], week: PickerValidDate }) => React.ReactNode` -### `Calendar.Days.Cell` +### `Calendar.DaysCell` Renders the cell for a single day. @@ -744,26 +746,26 @@ Renders the cell for a single day. - `value`: `PickerValidDate` - **required** -### `Calendar.Days.WeekNumberCell` +### `Calendar.DaysWeekNumberCell` Renders the number of the current week. - Extends `React.HTMLAttributes` -### `Calendar.Months.Root` +### `Calendar.Months` -Top level component for the `Calendar.Months.*` components. +Top level component for the `"month"` view. It expects a function as its children, which receives the list of the months to render as a parameter: ```tsx - + {({ months }) => months.map((month) => ( - + )) } - + ``` #### Props @@ -801,7 +803,7 @@ It expects a function as its children, which receives the list of the months to - `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"month"`. -### `Calendar.Months.Cell` +### `Calendar.MonthsCell` Renders the cell for a single month. @@ -811,18 +813,18 @@ Renders the cell for a single month. - `value`: `PickerValidDate` - **required**. -### `Calendar.Years.Root` +### `Calendar.Years` -Top level component for the `Calendar.Years.*` components. +Top level component for the `"year"` view. It expects a function as its children, which receives the list of years to render as a parameter: ```tsx - + {({ years }) => - years.map((year) => ) + years.map((year) => ) } - + ``` #### Props @@ -837,12 +839,12 @@ It expects a function as its children, which receives the list of years to rende :::success The `yearsPerRow` prop is needed to have a working keyboard navigation. - See the equivalent prop in `Calendar.Months.Root` for more details. + See the equivalent prop in `Calendar.Months` for more details. ::: - `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"year"`. -### `Calendar.Years.Cell` +### `Calendar.YearsCell` Renders the cell for a single year. diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 29f5431f64adf..cd426d26087b4 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -183,19 +183,43 @@ That way, users only have to pass the props specific to the calendar to the `Dig ::: -### `DigitalClock.ContentForSingleSection` +### `DigitalClock.Options` #### Props TODO -### `DigitalClock.ContentForMultiSection` +### `DigitalClock.HoursOptions` #### Props TODO -### `DigitalClock.Item` +### `DigitalClock.HoursWithMeridiemOptions` + +#### Props + +TODO + +### `DigitalClock.MeridiemOptions` + +#### Props + +TODO + +### `DigitalClock.MinutesOptions` + +#### Props + +TODO + +### `DigitalClock.SecondsOptions` + +#### Props + +TODO + +### `DigitalClock.Option` #### Props diff --git a/docs/data/pages.ts b/docs/data/pages.ts index 74300d468f845..9a655d0d30bcc 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -258,7 +258,7 @@ const pages: MuiPage[] = [ children: [ { pathname: '/x/react-date-pickers/rfc-field', title: 'Field' }, { pathname: '/x/react-date-pickers/rfc-calendar', title: 'Calendar' }, - { pathname: '/x/react-date-pickers/rfc-digital-clock', title: 'DigitalClock' }, + { pathname: '/x/react-date-pickers/rfc-digital-clock', title: 'Digital Clock' }, { pathname: '/x/react-date-pickers/rfc-picker', title: 'Picker' }, ], }, From 71af8e1e848cbff25caf85ea54a31ea6addc66e6 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 16:25:46 +0100 Subject: [PATCH 23/46] Work --- docs/data/date-pickers/rfc-calendar.md | 291 +++++++++++++++++-------- 1 file changed, 206 insertions(+), 85 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index c5e224f099adf..bff97ed807da4 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -15,7 +15,7 @@ This page extends the initial proposal made in [#15598](https://github.com/mui/m ### Without Material UI -The user can use the ``, ``, ``, ``, `` and `` components to create a grid of days: +The user can use the ``, ``, ``, ``, `` and `` components to create a grid of days: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -26,15 +26,15 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- - + + {({ days }) => days.map((day) => ( - + )) } - - + + {({ weeks }) => weeks.map((week) => ( @@ -46,8 +46,8 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; )) } - - + +
; ``` @@ -69,7 +69,9 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; ### Without Material UI -The user can use the `` and `` components to create a grid of months and utility components like `` and `` to create a header to navigate across the years: +#### List layout + +The user can use the `` and `` components to create a list of months and utility components like `` and `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -80,13 +82,42 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - + {({ months }) => months.map((month) => ( )) } - + +
; +``` + +#### Grid layout + +The user can use the ``, `` and `` components to create a grid of months and utility components like `` and `` to create a header to navigate across the years: + +```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + + +
+ + + +
+ + {({ rows }) => + rows.map((row) => ( + + {({ months }) => + months.map((month) => ( + + )) + } + + )) + } +
; ``` @@ -113,17 +144,43 @@ Once the `Calendar.*` unstyled component is ready, the `` shoul ### Without Material UI -The user can use the `` and `` components to create a grid of years: +#### List layout + +The user can use the `` and `` components to create a list of years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - + {({ years }) => years.map((year) => ) } - + +
; +``` + +#### Grid layout + +The user can use the ``, `` and `` components to create a grid of years: + +```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + + + + {({ rows }) => + rows.map((row) => ( + + {({ years }) => + years.map((year) => ( + + )) + } + + )) + } + ; ``` @@ -155,15 +212,15 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
{/** See calendar header documentation */}
- - + + {({ days }) => days.map((day) => ( - + )) } - - + + {({ weeks }) => weeks.map((week) => ( @@ -175,20 +232,20 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; )) } - - - + + + {({ months }) => months.map((month) => ( )) } - - + + {({ years }) => years.map((year) => ) } - +
; ``` @@ -325,7 +382,7 @@ function CalendarHeader() { } /> - }> + }> {({ years }) => years.map((year) => ( @@ -443,7 +500,7 @@ The `` component can be built in a few different ways: - WeekNumberCell + }; ``` @@ -466,27 +523,29 @@ The `` component can be built in a few different ways: ### Without Material UI -The user can use the `` and `` components to add a column to the grid: +The user can use the `` and `` components to add a column to the grid: ```tsx - - + + {({ days }) => ( - # + + # + {days.map((day) => ( - + ))} )} - - + + {({ weeks }) => weeks.map((week) => ( {({ days }) => ( - + {days.map((day) => ( ))} @@ -495,8 +554,8 @@ The user can use the `` and ` )) } - - + + ``` ### With Material UI @@ -549,7 +608,9 @@ That way, users only have to pass the props specific to the calendar to the `Cal - {/** See demo above */} + + {/** See demo above */} + @@ -642,7 +703,7 @@ Renders a button to set the current visible view. - `target`: `TView` -### `Calendar.Days` +### `Calendar.DaysGrid` Top level component for the `"day"` view. @@ -652,18 +713,20 @@ Top level component for the `"day"` view. - `fixedWeekNumber`: `number` -### `Calendar.DaysHeader` +### `Calendar.DaysGridHeader` Renders the header of the day grid. It expects a function as its children, which receives the list of days to render as a parameter: ```tsx - + {({ days }) => - days.map((day) => ) + days.map((day) => ( + + )) } - + ``` #### Props @@ -672,7 +735,7 @@ It expects a function as its children, which receives the list of days to render - `children`: `(params: { days: PickerValidDate[] }) => React.ReactNode` -### `Calendar.DaysHeaderCell` +### `Calendar.DaysGridHeaderCell` Renders the header of a day in the week. @@ -682,7 +745,7 @@ Renders the header of a day in the week. - `value`: `PickerValidDate` - **required**. -### `Calendar.DaysWeekNumberHeaderCell` +### `Calendar.DaysGridWeekNumberHeaderCell` Renders the header of the week number column. @@ -690,24 +753,20 @@ Renders the header of the week number column. - Extends `React.HTMLAttributes` -### `Calendar.DaysContent` +### `Calendar.DaysGridBody` Renders the content all the days in a month (it is the DOM element that should contain all the weeks). It expects a function as its children, which receives the list of weeks to render as a parameter: ```tsx - + {({ weeks }) => weeks.map((week) => ) } - + ``` -:::success -Maybe it should be named ``. -::: - #### Props - Extends `React.HTMLAttributes` @@ -746,26 +805,26 @@ Renders the cell for a single day. - `value`: `PickerValidDate` - **required** -### `Calendar.DaysWeekNumberCell` +### `Calendar.DaysGridWeekNumberCell` Renders the number of the current week. - Extends `React.HTMLAttributes` -### `Calendar.Months` +### `Calendar.MonthsList` Top level component for the `"month"` view. It expects a function as its children, which receives the list of the months to render as a parameter: ```tsx - + {({ months }) => months.map((month) => ( )) } - + ``` #### Props @@ -774,35 +833,58 @@ It expects a function as its children, which receives the list of the months to - `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` -- `monthsOrder`: `'asc' | 'desc'`, default: `'asc'`. +- `itemsOrder`: `'asc' | 'desc'`, default: `'asc'`. -- `monthsPerRow`: `number`, default: `1` +- `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"month"`. - :::success - The `monthsOrder` and `monthsPerRow` prop is needed to have a working keyboard navigation. - But it's not a great DX, especially if the user wants to vary the amount of items per row based on the viewport width. +### `Calendar.MonthsGrid` - The navigation behavior should looks something like this: +Top level component for the `"month"` view when the layout is a grid. - - if `monthsPerRow === 1`: +It expects a function as its children, which receives the list of rows to render as a parameter: - - ArrowLeft do nothing - - ArrowRight do nothing - - ArrowTop go to the month rendered above - - ArrowBottom go to month rendered below +```tsx + + {({ rows }) => + rows.map((row) => ) + } + +``` - - if `monthsPerRow > 1`: - - ArrowLeft go the month rendered on the left, and if none should go to the outer-right month of the line rendered above - - ArrowRight go the month rendered on the right, and if none should go to the outer-left month of the line rendered below - - ArrowTop go to the month rendered above - - ArrowBottom go to month rendered below +#### Props - And with no assumption on the layout, this seems to be a real challenge to achieve. - The MVP could probably not contain any keyboard navigation. - ::: +- Extends `React.HTMLAttributes` + +- `children`: `(params: { rows: PickerValidDate[] }) => React.ReactNode` + +- `itemsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `itemsPerRow`: `number` **required**. - `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"month"`. +### `Calendar.MonthsRow` + +Renders a row of months. + +It expects a function as its children, which receives the list of months to render as a parameter: + +```tsx + + {({ months }) => + months.map((month) => ( + + )) + } + +``` + +#### Props + +- Extends `React.HTMLAttributes` + +- `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` + ### `Calendar.MonthsCell` Renders the cell for a single month. @@ -813,18 +895,18 @@ Renders the cell for a single month. - `value`: `PickerValidDate` - **required**. -### `Calendar.Years` +### `Calendar.YearsList` -Top level component for the `"year"` view. +Top level component for the `"year"` view when the layout is a list. It expects a function as its children, which receives the list of years to render as a parameter: ```tsx - + {({ years }) => years.map((year) => ) } - + ``` #### Props @@ -833,17 +915,56 @@ It expects a function as its children, which receives the list of years to rende - `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` -- `yearsOrder`: `'asc' | 'desc'`, default: `'asc'`. +- `itemsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"year"`. + +### `Calendar.YearsGrid` -- `yearsPerRow`: `number`, default: `1` +Top level component for the `"year"` view when the layout is a grid. - :::success - The `yearsPerRow` prop is needed to have a working keyboard navigation. - See the equivalent prop in `Calendar.Months` for more details. - ::: +It expects a function as its children, which receives the list of rows to render as a parameter: + +```tsx + + {({ rows }) => + rows.map((row) => ) + } + +``` + +#### Props + +- Extends `React.HTMLAttributes` + +- `children`: `(params: { rows: PickerValidDate[] }) => React.ReactNode` + +- `itemsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `itemsPerRow`: `number` **required**. - `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the current view is `"year"`. +### `Calendar.YearsRow` + +Renders a row of years. + +It expects a function as its children, which receives the list of years to render as a parameter: + +```tsx + + {({ years }) => + years.map((year) => ) + } + +``` + +#### Props + +- Extends `React.HTMLAttributes` + +- `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` + ### `Calendar.YearsCell` Renders the cell for a single year. From 353e309a39e40b269f4a580c5dc0f184fc5756ea Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 16:49:41 +0100 Subject: [PATCH 24/46] Work --- docs/data/date-pickers/rfc-calendar.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index bff97ed807da4..5d224b9294a19 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -227,16 +227,7 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ days }) => days.map((day) => ( - )) - } - - )) - } - - - - {({ months }) => - months.map((month) => ( + ))DaysWeekRow )) } From 4e4b0b472021f38787af03ba5f0b99978c05ec57 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 17:06:47 +0100 Subject: [PATCH 25/46] Work --- docs/data/date-pickers/rfc-digital-clock.md | 58 ++++++++++++--------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index cd426d26087b4..11455d2a34147 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -7,29 +7,7 @@ title: DX - Digital Clock

This page describes how people can use time views with Material UI and how they can build custom time views.

-## Single section - -### Without Material UI - -The user can use the `` component to list all the time options in a flat list: - -```tsx - - - {({ options }) => - options.map((option) => ( - - )) - } - - -``` - -### With Material UI - -TODO - -## Multi section (no meridiem) +## Multi section - without meridiem ### Without Material UI @@ -58,7 +36,7 @@ The user can use the ``, `` component to add a column TODO +## Multi section - custom steps + +### Without Material UI + +TODO + +### With Material UI + +TODO + +## Single section + +### Without Material UI + +The user can use the `` component to manually list options: + +```tsx + + + + + + + +``` + +### With Material UI + +TODO + ## Anatomy of `DigitalClock.*` ### `DigitalClock.Root` From 290728b3c56bd4cd51c2e9cb2d12195b4c97b757 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 17:12:22 +0100 Subject: [PATCH 26/46] Work --- docs/data/date-pickers/rfc-digital-clock.md | 58 ++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 11455d2a34147..8d9b61a1e13a3 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -73,6 +73,62 @@ It should be used in combination with the ` + {ampm ? ( + + {({ options }) => + options.map((option) => ( + + )) + } + + ) : ( + + {({ options }) => + options.map((option) => ( + + )) + } + + )} + + {({ options }) => + options.map((option) => ( + + )) + } + + {ampm && ( + + {({ options }) => + options.map((option) => ( + + )) + } + + )} + + ); +} +``` + +### With Material UI + +TODO + ## Multi section - with seconds ### Without Material UI @@ -160,7 +216,7 @@ Top level component that wraps the other components. Same typing and behavior as today. -- **Validation props**: `maxTime`, `minTime`, `disableFuture`, `disablePast`, `shouldDisableTime`, `timeSteps`. +- **Validation props**: `maxTime`, `minTime`, `disableFuture`, `disablePast`, `shouldDisableTime`. Same typing and behavior as today. From 58c2b6cec256869c96e896b1f559de7f651456d8 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 17:17:08 +0100 Subject: [PATCH 27/46] Work --- docs/data/date-pickers/rfc-digital-clock.md | 50 ++++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 8d9b61a1e13a3..6d5f3cd323241 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -77,7 +77,7 @@ TODO ### Without Material UI -The user can use the `useIs12HourCycleInCurrentLocale()` hook to know if the `ampm` should be enabled based on the current locale and build the UI accordingly: +The user can use the `useIs12HourCycleInCurrentLocale()` hook to know if the meridiem should be enabled based on the current locale and build the UI accordingly: ```tsx function App(props) { @@ -176,7 +176,53 @@ TODO ### Without Material UI -TODO +The ``, ``, `` and `` components take a `step` prop that allow to customize the step between two consecutive options. +By default, the step is of `1` for the hours and 5 for the minutes and seconds: + +```tsx + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + +``` + +```tsx + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + + {({ options }) => + options.map((option) => ( + + )) + } + + +``` ### With Material UI From c3ff6e5dd9b21a3bbde3401ae5397504781d4211 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 17:27:37 +0100 Subject: [PATCH 28/46] Work --- docs/data/date-pickers/rfc-digital-clock.md | 149 ++++++++++++-------- 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 6d5f3cd323241..9f07df6b2377d 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -11,21 +11,19 @@ title: DX - Digital Clock ### Without Material UI -The user can use the ``, `` and `` components to list all the time options with one column per view: +The user can use the `` and `` components to list all the time options with one column per view: ```tsx - {({ options }) => - options.map((option) => ( - - )) + {({ hours }) => + hours.map((hour) => ) } - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } @@ -46,23 +44,21 @@ It should be used in combination with the ` - {({ options }) => - options.map((option) => ( - - )) + {({ hours }) => + hours.map((hour) => ) } - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } - {({ options }) => - options.map((option) => ( - + {({ meridiems }) => + meridiems.map((meridiem) => ( + )) } @@ -89,33 +85,33 @@ function App(props) { {ampm ? ( - {({ options }) => - options.map((option) => ( - + {({ hours }) => + hours.map((hour) => ( + )) } ) : ( - {({ options }) => - options.map((option) => ( - + {({ hours }) => + hours.map((hour) => ( + )) } )} - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } {ampm && ( - {({ options }) => - options.map((option) => ( - + {({ meridiems }) => + meridiems.map((meridiem) => ( + )) } @@ -138,30 +134,28 @@ The user can use the `` component to add a column ```tsx - {({ options }) => - options.map((option) => ( - - )) + {({ hours }) => + hours.map((hour) => ) } - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } - {({ options }) => - options.map((option) => ( - + {({ seconds }) => + seconds.map((second) => ( + )) } - {({ options }) => - options.map((option) => ( - + {({ meridiems }) => + meridiems.map((meridiem) => ( + )) } @@ -182,16 +176,14 @@ By default, the step is of `1` for the hours and 5 for the minutes and seconds: ```tsx - {({ options }) => - options.map((option) => ( - - )) + {({ hours }) => + hours.map((hour) => ) } - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } @@ -201,23 +193,21 @@ By default, the step is of `1` for the hours and 5 for the minutes and seconds: ```tsx - {({ options }) => - options.map((option) => ( - - )) + {({ hours }) => + hours.map((hour) => ) } - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } - {({ options }) => - options.map((option) => ( - + {({ minutes }) => + minutes.map((minute) => ( + )) } @@ -228,6 +218,33 @@ By default, the step is of `1` for the hours and 5 for the minutes and seconds: TODO +## Multi section - custom format + +### Without Material UI + +By default, the `` uses a default format provided by its parent (for example ``). +The user can override this format using the `format` prop: + +```tsx + + + {({ hours }) => + hours.map((hour) => ( + + )) + } + + +``` + +### With Material UI + +TODO + ## Single section ### Without Material UI @@ -325,12 +342,22 @@ TODO ### `DigitalClock.SecondsOptions` +Renders a list of options to select the section of the current value. + +It expects a function as its children, which receives the list of seconds as a parameter + #### Props TODO ### `DigitalClock.Option` +Renders the button for a single option + #### Props -TODO +- Extends `React.HTMLAttributes` + +- `value`: `PickerValidDate` **required** + +- `format`: `string`, default: provided by the parent From 4d841dae3d58ed70554e39d9c977068c5b6e48ea Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 17:37:55 +0100 Subject: [PATCH 29/46] Work --- docs/data/date-pickers/rfc-calendar.md | 11 +- docs/data/date-pickers/rfc-digital-clock.md | 168 +++++++++++++++----- 2 files changed, 140 insertions(+), 39 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 5d224b9294a19..bff97ed807da4 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -227,7 +227,16 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ days }) => days.map((day) => ( - ))DaysWeekRow + )) + } + + )) + } + + + + {({ months }) => + months.map((month) => ( )) } diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 9f07df6b2377d..05937e9955a7d 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -11,22 +11,22 @@ title: DX - Digital Clock ### Without Material UI -The user can use the `` and `` components to list all the time options with one column per view: +The user can use the `` and `` components to list all the time options with one column per view: ```tsx - + {({ hours }) => hours.map((hour) => ) } - - + + {({ minutes }) => minutes.map((minute) => ( )) } - + ``` @@ -48,13 +48,13 @@ It should be used in combination with the ` ) } - + {({ minutes }) => minutes.map((minute) => ( )) } - + {({ meridiems }) => meridiems.map((meridiem) => ( @@ -100,13 +100,13 @@ function App(props) { } )} - + {({ minutes }) => minutes.map((minute) => ( )) } - + {ampm && ( {({ meridiems }) => @@ -129,29 +129,29 @@ TODO ### Without Material UI -The user can use the `` component to add a column to edit this section: +The user can use the `` component to add a column to edit this section: ```tsx - + {({ hours }) => hours.map((hour) => ) } - - + + {({ minutes }) => minutes.map((minute) => ( )) } - - + + {({ seconds }) => seconds.map((second) => ( )) } - + {({ meridiems }) => meridiems.map((meridiem) => ( @@ -175,42 +175,42 @@ By default, the step is of `1` for the hours and 5 for the minutes and seconds: ```tsx - + {({ hours }) => hours.map((hour) => ) } - - + + {({ minutes }) => minutes.map((minute) => ( )) } - + ``` ```tsx - + {({ hours }) => hours.map((hour) => ) } - - + + {({ minutes }) => minutes.map((minute) => ( )) } - - + + {({ minutes }) => minutes.map((minute) => ( )) } - + ``` @@ -227,7 +227,7 @@ The user can override this format using the `format` prop: ```tsx - + {({ hours }) => hours.map((hour) => ( )) } - + ``` @@ -312,43 +312,135 @@ That way, users only have to pass the props specific to the calendar to the `Dig ### `DigitalClock.Options` +Renders a list of options. + #### Props +- Extends `React.HTMLAttributes` + TODO -### `DigitalClock.HoursOptions` +### `DigitalClock.HourOptions` + +Renders a list of options to select the hours of the current value. + +It expects a function as its children, which receives the list of hours as a parameter: + +```tsx + + {({ hours }) => + hours.map((hour) => ) + } + +``` #### Props -TODO +- Extends `React.HTMLAttributes` + +- `children`: `(params: { hours: PickerValidDate[] }) => React.ReactNode` + +- `skipInvalid`: `boolean`, default: `false` + If `true`, the invalid options are not rendered ### `DigitalClock.HoursWithMeridiemOptions` +Renders a list of options to select the hours of the current value. +The options will only be hours inside the same meridiem as the one currently selected, this component needs to be used in combination with ``. + +It expects a function as its children, which receives the list of hours as a parameter: + +```tsx + + {({ hours }) => + hours.map((hour) => ) + } + +``` + #### Props -TODO +- Extends `React.HTMLAttributes` + +- `children`: `(params: { hours: PickerValidDate[] }) => React.ReactNode` + +- `skipInvalid`: `boolean`, default: `false` + If `true`, the invalid options are not rendered ### `DigitalClock.MeridiemOptions` +Renders a list of options to select the meridiem of the current value. + +It expects a function as its children, which receives the list of meridiems as a parameter: + +```tsx + + {({ meridiems }) => + meridiems.map((meridiem) => ( + + )) + } + +``` + #### Props -TODO +- Extends `React.HTMLAttributes` + +- `children`: `(params: { meridiems: PickerValidDate[] }) => React.ReactNode` -### `DigitalClock.MinutesOptions` +- `skipInvalid`: `boolean`, default: `false` + If `true`, the invalid options are not rendered + +### `DigitalClock.MinuteOptions` + +Renders a list of options to select the minutes of the current value. + +It expects a function as its children, which receives the list of minutes as a parameter: + +```tsx + + {({ minutes }) => + minutes.map((minute) => ( + + )) + } + +``` #### Props -TODO +- Extends `React.HTMLAttributes` + +- `children`: `(params: { hours: PickerValidDate[] }) => React.ReactNode` -### `DigitalClock.SecondsOptions` +- `skipInvalid`: `boolean`, default: `false` + If `true`, the invalid options are not rendered -Renders a list of options to select the section of the current value. +### `DigitalClock.SecondOptions` -It expects a function as its children, which receives the list of seconds as a parameter +Renders a list of options to select the seconds of the current value. + +It expects a function as its children, which receives the list of seconds as a parameter: + +```tsx + + {({ seconds }) => + seconds.map((second) => ( + + )) + } + +``` #### Props -TODO +- Extends `React.HTMLAttributes` + +- `children`: `(params: { seconds: PickerValidDate[] }) => React.ReactNode` + +- `skipInvalid`: `boolean`, default: `false` + If `true`, the invalid options are not rendered ### `DigitalClock.Option` From d8275382b1f2ec379d185bb2099965640d7b4075 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 3 Dec 2024 17:44:59 +0100 Subject: [PATCH 30/46] Work --- docs/data/date-pickers/rfc-calendar.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index bff97ed807da4..e861e2a220901 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -827,6 +827,8 @@ It expects a function as its children, which receives the list of the months to
``` +This component takes care of the keyboard navigation (for example Arrow Up). + #### Props - Extends `React.HTMLAttributes` @@ -909,6 +911,8 @@ It expects a function as its children, which receives the list of years to rende ``` +This component takes care of the keyboard navigation (for example Arrow Up). + #### Props - Extends `React.HTMLAttributes` From 1264c060bba9ee66d5a34cf37bb3ce58a7750952 Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 4 Dec 2024 13:51:59 +0100 Subject: [PATCH 31/46] Work --- docs/data/date-pickers/rfc-picker.md | 93 +++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index 267957fc3b150..6c137678cefff 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -11,7 +11,7 @@ title: DX - Picker This page extends the initial proposal made in [#14718](https://github.com/mui/mui-x/issues/14718) ::: -## Basic usage in a Popover +## Usage in a Popover ### Without Material UI @@ -24,7 +24,7 @@ import { Popover } from '@base-ui-components/react/popover'; import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; -function CustomDatePicker(props) { +function DesktopDatePicker(props) { const manager = useDateManager(); return ( @@ -47,7 +47,7 @@ function CustomDatePicker(props) { ); } -; +; ``` #### With React Aria `` components @@ -59,7 +59,7 @@ import { useDateManager } from '@base-ui-components/react-x-date-pickers/manager import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Dialog, DialogTrigger, Button, Popover } from 'react-aria-components'; -function CustomDatePicker(props) { +function DesktopDatePicker(props) { const manager = useDateManager(); return ( @@ -81,7 +81,7 @@ function CustomDatePicker(props) { ); } -; +; ``` ### With Material UI @@ -98,7 +98,7 @@ import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker'; This component could be renamed `` to better match its behavior. ::: -## Basic usage in a Dialog +## Usage in a Dialog ### Without Material UI @@ -111,7 +111,7 @@ import { useDateManager } from '@base-ui-components/react-x-date-pickers/manager import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Dialog } from '@base-ui-components/react/dialog'; -function CustomDatePicker(props) { +function MobileDatePicker(props) { const manager = useDateManager(); return ( @@ -132,7 +132,7 @@ function CustomDatePicker(props) { ); } -; +; ``` #### With Mantine `` component @@ -144,7 +144,7 @@ import { useDateManager } from '@base-ui-components/react-x-date-pickers/manager import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Modal, Button } from '@mantine/core'; -function CustomDatePicker(props) { +function MobileDatePicker(props) { const manager = useDateManager(); return ( @@ -166,7 +166,7 @@ function CustomDatePicker(props) { ); } -; +; ``` ### With Material UI @@ -181,7 +181,7 @@ import { MobileDatePicker } from '@mui/x-date-pickers/MobileDatePicker'; This component could be renamed `` to better match its behavior. ::: -## Basic responsive usage +## Responsive usage ### Without Material UI @@ -194,7 +194,7 @@ import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Popover } from '@base-ui-components/react/popover'; import { Dialog } from '@base-ui-components/react/dialog'; -function CustomDatePicker(props) { +function DatePicker(props) { const manager = useDateManager(); const isDesktop = useMediaQuery('@media (pointer: fine)', { defaultMatches: true, @@ -241,6 +241,8 @@ function CustomDatePicker(props) {
); } + + ``` ### With Material UI @@ -253,6 +255,37 @@ import { DatePicker } from '@mui/x-date-pickers/DatePicker'; ; ``` +## Static usage + +### Without Material UI + +The user can use the `` component to create a static picker. +Most of the time, the user can use directly components such as `Calendar.*`, but the static picker can be useful in the following scenarios: + +- several view components are used together (the main use case is to create a Date Time Picker). The static picker will make sure the value is correctly handled between those components. +- the user wants to add UI elements like a shortcut panel using utility components like ``. + +```tsx +import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; + +function StaticDatePicker(props) { + const manager = useDateManager(); + + return ( + + {/** See calendar documentation */} + + ); +} + +; +``` + +### With Material UI + +TODO + ## Usage with date and time views ### Without Material UI @@ -269,9 +302,7 @@ import { Popover } from '@base-ui-components/react/popover'; {/** See calendar documentation */} - - {/** See digital clock documentation (not available yet) */} - + {/** See digital clock documentation */} ; ``` @@ -488,6 +519,38 @@ It expects a function as its children, which receives the context value as a par Same typing and behavior as today. +- **Open props**: `open`, `onOpenChange` + + The `onOpenChange` replaces the `onOpen` and `onClose` props in the current implementation + +#### `Picker.StaticRoot` + +Top level component that wraps the other components when there is not field UI but only views. + +- `manager`: `PickerManager` - **required** + + :::success + See [#15395](https://github.com/mui/mui-x/issues/15395) for context. + ::: + +- `children`: `(contextValue: PickerContextValue) => React.ReactNode` + +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. + + Same typing and behavior as today. + +- **Validation props**: list based on the `manager` prop + + For `useDateManager()` it would be `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. + + Same typing and behavior as today. + +- **Form props**: `disabled`, `readOnly`. + + Same typing and behavior as today. + +#### Props + ### `Picker.FormattedValue` Formats the value based on the provided format. From 7a1f932a37155cb6f76a6ac834edca66cadfa2a8 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 10 Dec 2024 08:52:13 +0100 Subject: [PATCH 32/46] Work on the calendar --- docs/data/date-pickers/rfc-calendar.md | 103 ++++++++++++++++++ docs/data/date-pickers/rfc-range-calendar.md | 66 +++++++++++ docs/data/pages.ts | 5 + .../react-date-pickers/rfc-range-calendar.js | 7 ++ 4 files changed, 181 insertions(+) create mode 100644 docs/data/date-pickers/rfc-range-calendar.md create mode 100644 docs/pages/x/react-date-pickers/rfc-range-calendar.js diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index e861e2a220901..f36939e251105 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -519,6 +519,107 @@ The `` component can be built in a few different ways: ::: +## Display multiple months + +### Without Material UI + +The user can use the `offset` prop of the `` component to render months with an offset compared to the currently visible month: + +```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + +function CalendarGrid({ offset }) { + return ( + + + {({ days }) => + days.map((day) => ( + + )) + } + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => + days.map((day) => ( + + )) + } + + )) + } + + + ); +} + + +
{/** See demo below for the navigation with multiple months */}
+
+ + +
+
; +``` + +#### Month navigation with multiple months + +There is two way to navigate to the next / previous months: + +1. With the `` button +2. With the arrow navigation when the target is not in the current month + +When rendering multiple months, both those navigation technic only navigate one month at the time. +For example, if you were rendering May and June, pressing `` will render June and July. + +The user can use the `monthPageSize` prop on the `` component to customize this behavior. + +If the prop receives a number, it will move by the amount of month both for `` and for arrow navigation: + +```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + +function CalendarHeader() { + return ( + +
+ + + +
+ + +
+ ); +} +``` + +But the user can also distinguish both behaviors by providing an object: + +```tsx +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + +function CalendarHeader() { + return ( + +
+ + + +
+ + +
+ ); +} +``` + +### With Material UI + +This is currently not doable. + ## Display week number ### Without Material UI @@ -596,6 +697,8 @@ Top level component that wraps the other components. - `autoFocus`: `boolean` +- `monthPageSize`: `number | { keyboard: number, button: number }`, default: `1`. The amount of months to navigate by in the day view when pressing `` or with arrow navigation. + :::success All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. diff --git a/docs/data/date-pickers/rfc-range-calendar.md b/docs/data/date-pickers/rfc-range-calendar.md new file mode 100644 index 0000000000000..935742f395773 --- /dev/null +++ b/docs/data/date-pickers/rfc-range-calendar.md @@ -0,0 +1,66 @@ +--- +productId: x-date-pickers +title: DX - RangeCalendar +--- + +# Range Calendar + +

This page describes how people can use date range views with Material UI and how they can build custom date range views.

+ +:::success +Almost all the components of `RangeCalendar.*` are the same as their `Calendar.*` counterpart. +::: + +## Usage with only days + +### Without Material UI + +The user can use the ``, ``, ``, ``, `` and `` components to create a grid of days: + +```tsx +import { RangeCalendar } from '@base-ui-components/react-x-date-pickers-pro/range-calendar'; + + +
+ ◀ + + ▶ +
+ + + {({ days }) => + days.map((day) => ( + + )) + } + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => + days.map((day) => ( + + )) + } + + )) + } + + +
; +``` + +### With Material UI + +:::success +No DX change here compared to today +::: + +The user can use the ``: + +```tsx +import { DateRangeCalendar } from '@mui/x-date-pickers/DateCalendar'; + +; +``` diff --git a/docs/data/pages.ts b/docs/data/pages.ts index e86aeb12d8d5b..7ba1dbb5b5eaa 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -258,6 +258,11 @@ const pages: MuiPage[] = [ children: [ { pathname: '/x/react-date-pickers/rfc-field', title: 'Field' }, { pathname: '/x/react-date-pickers/rfc-calendar', title: 'Calendar' }, + { + pathname: '/x/react-date-pickers/rfc-range-calendar', + title: 'Range Calendar', + plan: 'pro', + }, { pathname: '/x/react-date-pickers/rfc-digital-clock', title: 'Digital Clock' }, { pathname: '/x/react-date-pickers/rfc-picker', title: 'Picker' }, ], diff --git a/docs/pages/x/react-date-pickers/rfc-range-calendar.js b/docs/pages/x/react-date-pickers/rfc-range-calendar.js new file mode 100644 index 0000000000000..5c62aa41ee64d --- /dev/null +++ b/docs/pages/x/react-date-pickers/rfc-range-calendar.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/rfc-range-calendar.md?muiMarkdown'; + +export default function Page() { + return ; +} From b130e532dd6f9eb9192fdf94a1e03c62f951c143 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 10 Dec 2024 13:49:33 +0100 Subject: [PATCH 33/46] Work --- docs/data/date-pickers/rfc-calendar.md | 6 ++++++ docs/data/date-pickers/rfc-digital-clock.md | 2 +- docs/data/date-pickers/rfc-picker.md | 10 +++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index f36939e251105..f9faa0aa90e29 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -1081,3 +1081,9 @@ Renders the cell for a single year. - Extends `React.HTMLAttributes` - `value`: `PickerValidDate` - **required**. + +#### `Calendar.supportedViews` + +Utility variable that helps building Date Time Pickers without hardcoding the list of views (which could become outdated if we introduce new views in the future). + +Value: `["day", "month", "year"]` diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 05937e9955a7d..94fae1e523747 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -11,7 +11,7 @@ title: DX - Digital Clock ### Without Material UI -The user can use the `` and `` components to list all the time options with one column per view: +The user can use the `` and `` components to list all the time options with one column per section: ```tsx diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index 6c137678cefff..4958e5bfa5ae8 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -298,10 +298,10 @@ import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Popover } from '@base-ui-components/react/popover'; - + {/** See calendar documentation */} - + {/** See digital clock documentation */} ; @@ -523,7 +523,9 @@ It expects a function as its children, which receives the context value as a par The `onOpenChange` replaces the `onOpen` and `onClose` props in the current implementation -#### `Picker.StaticRoot` +### `Picker.StaticRoot` + +#### Props Top level component that wraps the other components when there is not field UI but only views. @@ -549,8 +551,6 @@ Top level component that wraps the other components when there is not field UI b Same typing and behavior as today. -#### Props - ### `Picker.FormattedValue` Formats the value based on the provided format. From 078a33ae235433e636bd7e3728f253b1dbba587a Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 10 Dec 2024 14:13:02 +0100 Subject: [PATCH 34/46] Work --- docs/data/date-pickers/rfc-calendar.md | 104 ++++++++++--------------- docs/data/date-pickers/rfc-picker.md | 87 +++++++++++---------- 2 files changed, 85 insertions(+), 106 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index f9faa0aa90e29..4782441171bfa 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -271,9 +271,9 @@ When MD3 is supported, the default views of `` should probably b ### Without Material UI -The user can use the ``, `` and `` to build basically any kind of header they could think of: +The user can use the ``, `` and `` to build basically any kind of header they could think of: -#### Very basic header (without month and year views) +#### Very basic header (without month and year UI) ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -298,20 +298,22 @@ import { } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { view } = useCalendarContext(); + const { activeSection } = useCalendarContext(); return (
- + - {view === 'year' ? '▲' : '▼'} - - + {activeSection === 'year' ? '▲' : '▼'} + + {activeSection === 'day' && (
-
+ )}
); } @@ -323,32 +325,36 @@ function CalendarHeader() { import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { view } = useCalendarContext(); + const { activeSection } = useCalendarContext(); return (
- {view === 'day' && ( + {activeSection === 'day' && ( )} - - - {view === 'day' && } + + {activeSection === 'day' && ( + + )}
- {view === 'day' && ( + {activeSection === 'day' && ( )} - - - {view === 'day' && } + + {activeSection === 'day' && ( + + )}
); @@ -364,7 +370,6 @@ import { Menu } from '@base-ui-components/react/menu'; import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { view } = useCalendarContext(); return (
@@ -697,7 +702,7 @@ Top level component that wraps the other components. - `autoFocus`: `boolean` -- `monthPageSize`: `number | { keyboard: number, button: number }`, default: `1`. The amount of months to navigate by in the day view when pressing `` or with arrow navigation. +- `monthPageSize`: `number | { keyboard: number, button: number }`, default: `1`. The amount of months to navigate by in the day grid when pressing `` or with arrow navigation. :::success All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. @@ -722,27 +727,6 @@ That way, users only have to pass the props specific to the calendar to the `Cal ::: -### `Calendar.MatchView` - -Utility component to conditionally render some components based on the current view. -Doesn't render a DOM node (it does not have a `render` prop either). - -```tsx - - Only rendered when the view is "day" - - - - Only rendered when the view is "day" or "month" - -``` - -#### Props - -- `match`: `TView | readonly TView[]` - **required**. - -- `children`: `React.ReactNode` - ### `Calendar.FormattedValue` Formats the value based on the provided format. @@ -796,19 +780,19 @@ It does not modify the value it only navigates to the target year. TODO: Clarify the behavior when multiple calendars are rendered at once. ::: -### `Calendar.SetView` +### `Picker.SetActiveSection` -Renders a button to set the current visible view. +Renders a button to set the active section. #### Props -- Extends `React.HTMLAttributes` +- Extends `React.HTMLAttributes` -- `target`: `TView` +- `target`: `"day" | "month" | "year"` - **required** ### `Calendar.DaysGrid` -Top level component for the `"day"` view. +Top level component to pick a day. #### Props @@ -916,7 +900,7 @@ Renders the number of the current week. ### `Calendar.MonthsList` -Top level component for the `"month"` view. +Top level component to pick a month. It expects a function as its children, which receives the list of the months to render as a parameter: @@ -940,11 +924,11 @@ This component takes care of the keyboard navigation (for example ` - `value`: `PickerValidDate` - **required**. - -#### `Calendar.supportedViews` - -Utility variable that helps building Date Time Pickers without hardcoding the list of views (which could become outdated if we introduce new views in the future). - -Value: `["day", "month", "year"]` diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index 4958e5bfa5ae8..2b6d6153126da 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -286,24 +286,45 @@ function StaticDatePicker(props) { TODO -## Usage with date and time views +## Usage with date and time ### Without Material UI -The user can use the `` component to conditionally render the view components. -This is needed to build date time pickers: +The user can use both the `Calendar.*` and the `DigitalClock.*` components together to render the date and the time picking UI side by side: ```tsx +import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; +import { DigitalClock } from '@base-ui-components/react-x-date-pickers/digital-clock'; + + + {/** See calendar documentation */} + {/** See digital clock documentation */} +; +``` + +If the user wants to set the UI to select the date, then the time, he can conditionally render the view component based on the active section: + +```tsx import { Popover } from '@base-ui-components/react/popover'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; +import { DigitalClock } from '@base-ui-components/react-x-date-pickers/digital-clock'; +import { isDateSection } from '@base-ui-components/react-x-date-pickers/utils'; - - {/** See calendar documentation */} - - - {/** See digital clock documentation */} - + + {({ activeSection }) => + isDateSection(activeSection) ? ( + {/** See calendar documentation */} + ) : ( + + {/** See digital clock documentation */} + + ) + } + ; ``` @@ -355,7 +376,7 @@ import { Popover } from '@base-ui-components/react/popover'; ; ``` -The toolbar can also be used to switch between views thanks to the `` component: +The toolbar can also be used to switch between sections thanks to the `` component: ```tsx import { Popover } from '@base-ui-components/react/popover'; @@ -363,12 +384,12 @@ import { Picker } from '@base-ui-components/react-x-date-pickers/picker';
- + - - + + - +
{/** See calendar documentation */}
; @@ -382,7 +403,7 @@ TODO ### Without Material UI -The user can use the `` component in combination with any Tabs / Tab components. +The user can use the `` component in combination with any Tabs / Tab components. The example below uses the `Tabs` component from Base UI as an example: @@ -390,21 +411,22 @@ The example below uses the `Tabs` component from Base UI as an example: import { Tabs } from '@base-ui-components/react/tabs'; import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { isDateSection } from '@base-ui-components/react-x-date-pickers/utils'; - {({ view }) => ( - + {({ activeSection }) => ( + } + render={(props) => } > Date } + render={(props) => } > Time @@ -561,27 +583,6 @@ Formats the value based on the provided format. - `format`: `string` - **required** -### `Picker.MatchView` - -Utility component to conditionally render some components based on the current view. -Doesn't render a DOM node (it does not have a `render` prop either). - -```tsx - - Only rendered when the view is "day" - - - - Only rendered when the view is "day" or "month" - -``` - -#### Props - -- `match`: `TView | readonly TView[]` - **required**. - -- `children`: `React.ReactNode` - ### `Picker.ContextValue` Utility component to access the picker public context. @@ -624,12 +625,12 @@ Renders a button to cancel the current value. - Extends `React.HTMLAttributes` -### `Picker.SetView` +### `Picker.SetActiveSection` -Renders a button to set the current visible view. +Renders a button to set the active section. #### Props - Extends `React.HTMLAttributes` -- `target`: `TView` - **required** +- `target`: `PickerSectionType` (current `FieldSectionType` that would be renamed) - **required** From 6789e39e5a5c1a908855a07cae384a18a0768d51 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 10 Dec 2024 14:17:11 +0100 Subject: [PATCH 35/46] Work --- docs/data/date-pickers/rfc-overview.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/data/date-pickers/rfc-overview.md diff --git a/docs/data/date-pickers/rfc-overview.md b/docs/data/date-pickers/rfc-overview.md new file mode 100644 index 0000000000000..01003dd5b3bbf --- /dev/null +++ b/docs/data/date-pickers/rfc-overview.md @@ -0,0 +1,10 @@ +--- +productId: x-date-pickers +title: DX - Overview +--- + +# Overview + +

This page describes the main principles of the new DX.

+ +- The concept of _view_ is removed in favor of a concept of _active section_ that is shared with the field and make no assumption about how those sections are rendered. From 9229ec6e64472ddef18b0b9d81fe6666f930b455 Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 12 Dec 2024 11:23:45 +0100 Subject: [PATCH 36/46] Fix --- docs/data/date-pickers/rfc-calendar.md | 62 +++++++------- docs/data/date-pickers/rfc-overview.md | 81 +++++++++++++++++++ docs/data/pages.ts | 1 + .../x/react-date-pickers/rfc-overview.js | 7 ++ 4 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 docs/pages/x/react-date-pickers/rfc-overview.js diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 4782441171bfa..74e6f7bf59e19 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -22,9 +22,9 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- + - +
@@ -71,16 +71,16 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; #### List layout -The user can use the `` and `` components to create a list of months and utility components like `` and `` to create a header to navigate across the years: +The user can use the `` and `` components to create a list of months and utility components like `` and `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- + - +
{({ months }) => @@ -94,16 +94,16 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; #### Grid layout -The user can use the ``, `` and `` components to create a grid of months and utility components like `` and `` to create a header to navigate across the years: +The user can use the ``, `` and `` components to create a grid of months and utility components like `` and `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar';
- + - +
{({ rows }) => @@ -271,7 +271,7 @@ When MD3 is supported, the default views of `` should probably b ### Without Material UI -The user can use the ``, `` and `` to build basically any kind of header they could think of: +The user can use the ``, `` and `` to build basically any kind of header they could think of: #### Very basic header (without month and year UI) @@ -281,9 +281,9 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { return (
- + - +
); } @@ -310,8 +310,8 @@ function CalendarHeader() {
{activeSection === 'day' && (
- - + +
)}
@@ -330,7 +330,7 @@ function CalendarHeader() {
{activeSection === 'day' && ( - + )} {activeSection === 'day' && ( - + )}
{activeSection === 'day' && ( - + )} {activeSection === 'day' && ( - + )}
@@ -438,7 +438,7 @@ The `` component can be built in a few different ways: 2. Using the primitives exposed by `@base-ui-components/react-x-date-pickers/calendar`: - If the user wants to totally own the styling of this part of the UI (because the UI is really different from the default one), he can use components like `` or `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: + If the user wants to totally own the styling of this part of the UI (because the UI is really different from the default one), he can use components like `` or `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -446,9 +446,9 @@ The `` component can be built in a few different ways: function CustomCalendarHeader() { return (
- + - +
); } @@ -573,15 +573,15 @@ function CalendarGrid({ offset }) { There is two way to navigate to the next / previous months: -1. With the `` button +1. With the `` button 2. With the arrow navigation when the target is not in the current month When rendering multiple months, both those navigation technic only navigate one month at the time. -For example, if you were rendering May and June, pressing `` will render June and July. +For example, if you were rendering May and June, pressing `` will render June and July. The user can use the `monthPageSize` prop on the `` component to customize this behavior. -If the prop receives a number, it will move by the amount of month both for `` and for arrow navigation: +If the prop receives a number, it will move by the amount of month both for `` and for arrow navigation: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -590,9 +590,9 @@ function CalendarHeader() { return (
- + - +
@@ -610,9 +610,9 @@ function CalendarHeader() { return (
- + - +
@@ -702,7 +702,7 @@ Top level component that wraps the other components. - `autoFocus`: `boolean` -- `monthPageSize`: `number | { keyboard: number, button: number }`, default: `1`. The amount of months to navigate by in the day grid when pressing `` or with arrow navigation. +- `monthPageSize`: `number | { keyboard: number, button: number }`, default: `1`. The amount of months to navigate by in the day grid when pressing `` or with arrow navigation. :::success All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. @@ -750,7 +750,7 @@ The user can also use `useCalendarContext()`, but a component allows to not crea - `children`: `(contextValue: CalendarContextValue) => React.ReactNode` -### `Calendar.GoToMonth` +### `Calendar.SetVisibleMonth` Renders a button to go to the previous or the next month. It does not modify the value it only navigates to the target month. @@ -765,7 +765,7 @@ It does not modify the value it only navigates to the target month. TODO: Clarify the behavior when multiple calendars are rendered at once. ::: -### `Calendar.GoToYear` +### `Calendar.SetVisibleYear` Renders a button to go to the previous or the next month. It does not modify the value it only navigates to the target year. @@ -780,7 +780,7 @@ It does not modify the value it only navigates to the target year. TODO: Clarify the behavior when multiple calendars are rendered at once. ::: -### `Picker.SetActiveSection` +### `Calendar.SetActiveSection` Renders a button to set the active section. diff --git a/docs/data/date-pickers/rfc-overview.md b/docs/data/date-pickers/rfc-overview.md index 01003dd5b3bbf..58f3b590bd9a5 100644 --- a/docs/data/date-pickers/rfc-overview.md +++ b/docs/data/date-pickers/rfc-overview.md @@ -7,4 +7,85 @@ title: DX - Overview

This page describes the main principles of the new DX.

+## General principles + +### Composition + +All the components displayed in the pages below are following the Base UI DX which means: + +- One component = one HTML element (except for elements like hidden ``) + +- Every component can receive a `render` prop to override the rendered element: + + ```tsx + import List from '@mui/material/List'; + import ListItem from '@mui/material/ListItem'; + import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + + }> + {({ months }) => + months.map((month) => ( + } + /> + )) + } + ; + ``` + + This `render` prop can also accept a function that receives the `props` and the `state` of the component (equivalent of our `ownerState`): + + ```tsx + import List from '@mui/material/List'; + import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; + + ( + + )} + > + {/** See demo above */} + ; + ``` + +- Every component can receive a `className` prop, they don't have any `className` by default: + + ```tsx + // Will always have the class "day" + + + // Will always have the class "day" + // Will only have the class "day-selected" when the day is selected + clsx("day", state.isDaySelected && "day-selected")} + /> + ``` + + :::success + For most use-cases, people should use the `data-attr` instead of creating custom classes. + The state of the Date and Time Pickers is quite big so we won't add one `data-attr` for each property in it on each component. + We will probably add the most useful one (`data-selected` on the `` component for example) and people can use the `className` prop for more advanced use cases. + ::: + +- Components can have `data-attr` to allow conditional styling + + ```tsx + + ``` + + ```css + .day { + background-color: red; + } + + .day[data-selected] { + background-color: green; + } + ``` + +## Lifecycle of the components + - The concept of _view_ is removed in favor of a concept of _active section_ that is shared with the field and make no assumption about how those sections are rendered. diff --git a/docs/data/pages.ts b/docs/data/pages.ts index 7ba1dbb5b5eaa..0939b5174ebe8 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -256,6 +256,7 @@ const pages: MuiPage[] = [ pathname: '/x/react-date-pickers/rfc', title: 'Date and Time Pickers - new DX', children: [ + { pathname: '/x/react-date-pickers/rfc-overview', title: 'Overview' }, { pathname: '/x/react-date-pickers/rfc-field', title: 'Field' }, { pathname: '/x/react-date-pickers/rfc-calendar', title: 'Calendar' }, { diff --git a/docs/pages/x/react-date-pickers/rfc-overview.js b/docs/pages/x/react-date-pickers/rfc-overview.js new file mode 100644 index 0000000000000..18b5089b4fa77 --- /dev/null +++ b/docs/pages/x/react-date-pickers/rfc-overview.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/rfc-overview.md?muiMarkdown'; + +export default function Page() { + return ; +} From 1ffc9050c845c0a47a8176a34e3e80f1d22bf48c Mon Sep 17 00:00:00 2001 From: flavien Date: Fri, 13 Dec 2024 13:35:09 +0100 Subject: [PATCH 37/46] Add examples of usage for utility components --- docs/data/date-pickers/rfc-picker.md | 33 ++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index 2b6d6153126da..606d0863c3ed0 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -583,6 +583,10 @@ Formats the value based on the provided format. - `format`: `string` - **required** +#### Usages in the styled version + +- The title / individual sections in all the toolbar components (in combination with ``) + ### `Picker.ContextValue` Utility component to access the picker public context. @@ -599,7 +603,6 @@ The user can also use `usePickerContext()`, but a component allows to not create ### `Picker.SetValue` Renders a button to set the current value. -The button is disabled if the value is invalid (this could be configurable through an `acceptInvalidValue` prop). #### Props @@ -607,7 +610,15 @@ The button is disabled if the value is invalid (this could be configurable throu - `target`: `PickerValidDate` - **required** -- `importance`: `'set' | 'accept'`, default: `'accept'` +- `importance`: `'set' | 'accept'`, default: `'accept'` (equivalent of the `changeImportance` prop on the `shortcut` slot) + +- `skipValidation`: `boolean`, default: `false` (by default the button is disabled is the target value is not passing validation) + +#### Usages in the styled version + +- The List Item of `` (people creating custom UIs can also use this component) + +- The Button of `` that sets the value to today or clear the value ### `Picker.AcceptValue` @@ -617,6 +628,10 @@ Renders a button to accept the current value. - Extends `React.HTMLAttributes` +#### Usages in the styled version + +- The Button of `` that accepts the value + ### `Picker.CancelValue` Renders a button to cancel the current value. @@ -625,12 +640,26 @@ Renders a button to cancel the current value. - Extends `React.HTMLAttributes` +#### Usages in the styled version + +- The Button of `` that cancels the value + ### `Picker.SetActiveSection` Renders a button to set the active section. +#### Usages in the styled version + +- The Tab in `` + +- The Tab in `` (might require manually using `usePickerContext` to make the range position change work) + #### Props - Extends `React.HTMLAttributes` - `target`: `PickerSectionType` (current `FieldSectionType` that would be renamed) - **required** + +#### Usages in the styled version + +- The title / individual sections in all the toolbar components (in combination with ``) From 899728e24b811b48f5b35a1a3598c42ea82c63ed Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 2 Jan 2025 16:56:53 +0100 Subject: [PATCH 38/46] Remove FormattedValue --- docs/data/date-pickers/rfc-calendar.md | 199 ++++++++++++++----------- docs/data/date-pickers/rfc-picker.md | 92 +++++------- 2 files changed, 149 insertions(+), 142 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 74e6f7bf59e19..a8ac0fcf11911 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -21,33 +21,37 @@ The user can use the ``, ``, ` -
- - - -
- - - {({ days }) => - days.map((day) => ( - - )) - } - - - {({ weeks }) => - weeks.map((week) => ( - - {({ days }) => - days.map((day) => ( - - )) - } - - )) - } - - + {({ visibleMonth }) => ( + +
+ + {visibleMonth.format('MMMM YYYY')} + +
+ + + {({ days }) => + days.map((day) => ( + + )) + } + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => + days.map((day) => ( + + )) + } + + )) + } + + +
+ )}
; ``` @@ -71,53 +75,61 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; #### List layout -The user can use the `` and `` components to create a list of months and utility components like `` and `` to create a header to navigate across the years: +The user can use the `` and `` components to create a list of months and utility components like `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; -
- - - -
- - {({ months }) => - months.map((month) => ( - - )) - } - + {({ visibleMonth }) => ( + +
+ + {visibleMonth.format('YYYY')}} + +
+ + {({ months }) => + months.map((month) => ( + + )) + } + +
+ )}
; ``` #### Grid layout -The user can use the ``, `` and `` components to create a grid of months and utility components like `` and `` to create a header to navigate across the years: +The user can use the ``, `` and `` components to create a grid of months and utility components like `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; -
- - - -
- - {({ rows }) => - rows.map((row) => ( - - {({ months }) => - months.map((month) => ( - - )) - } - - )) - } -
+ {({ visibleMonth }) => ( + +
+ + {visibleMonth.format('YYYY')}} + +
+ + {({ rows }) => + rows.map((row) => ( + + {({ months }) => + months.map((month) => ( + + )) + } + + )) + } + +
+ )}
; ``` @@ -271,7 +283,7 @@ When MD3 is supported, the default views of `` should probably b ### Without Material UI -The user can use the ``, `` and `` to build basically any kind of header they could think of: +The user can use the `` and `` to build basically any kind of header they could think of: #### Very basic header (without month and year UI) @@ -279,10 +291,12 @@ The user can use the ``, ` - + {visibleMonth.format('MMMM YYYY')} ); @@ -298,14 +312,14 @@ import { } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { activeSection } = useCalendarContext(); + const { visibleMonth, activeSection } = useCalendarContext(); return (
- + {visibleMonth.format('MMMM YYYY')} {activeSection === 'year' ? '▲' : '▼'} {activeSection === 'day' && ( @@ -325,7 +339,8 @@ function CalendarHeader() { import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { activeSection } = useCalendarContext(); + const { visibleMonth, activeSection } = useCalendarContext(); + return (
@@ -336,7 +351,7 @@ function CalendarHeader() { target={activeSection === 'year' ? 'day' : 'year'} disabled={activeSection === 'month'} > - + {visibleMonth.format('MMMM')}} {activeSection === 'day' && ( @@ -350,7 +365,7 @@ function CalendarHeader() { target={activeSection === 'month' ? 'day' : 'month'} disabled={activeSection === 'year'} > - + {visibleMonth.format('YYYY')}} {activeSection === 'day' && ( @@ -370,30 +385,32 @@ import { Menu } from '@base-ui-components/react/menu'; import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { + const { visibleMonth, activeSection } = useCalendarContext(); + return (
- } /> + {visibleMonth.format('MMMM')} - }> + }> {({ months }) => months.map((month) => ( )) } - + - } /> + {visibleMonth.format('YYYY')} - }> + }> {({ years }) => years.map((year) => ( )) } - +
@@ -438,16 +455,18 @@ The `` component can be built in a few different ways: 2. Using the primitives exposed by `@base-ui-components/react-x-date-pickers/calendar`: - If the user wants to totally own the styling of this part of the UI (because the UI is really different from the default one), he can use components like `` or `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: + If the user wants to totally own the styling of this part of the UI (because the UI is really different from the default one), he can use components like `` only for this part of the UI while still using `@mui/x-date-pickers` for everything he doesn't want to deeply customize: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CustomCalendarHeader() { + const { visibleMonth } = useCalendarContext(); + return (
- + {visibleMonth.format('MMMM YYYY')}
); @@ -489,7 +508,8 @@ The `` component can be built in a few different ways: paddingRight: 12, }); - export const PickerCalendarHeaderLabel = styled(Calendar.FormattedValue)({ + // This component is purely presentational and not present in `@base-ui-components/react-x-date-pickers/Calendar'. + export const PickerCalendarHeaderLabel = styled('span')({ /** ... */ }); @@ -500,10 +520,12 @@ The `` component can be built in a few different ways: export const PickerCalendarHeader = (props) => { const { format, ...other } = props; + const { value } = useCalendarContext(); + return ( - + {value.format(format)} }; @@ -587,11 +609,15 @@ If the prop receives a number, it will move by the amount of month both for `
- + {visibleMonth.format('MMMM YYYY')} + {' – '} + {visibleMonth.add(1, 'month').format('MMMM YYYY')}
@@ -607,11 +633,15 @@ But the user can also distinguish both behaviors by providing an object: import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { + const { visibleMonth } = useCalendarContext(); + return (
- + {visibleMonth.format('MMMM YYYY')} + {' – '} + {visibleMonth.add(1, 'month').format('MMMM YYYY')}
@@ -704,6 +734,8 @@ Top level component that wraps the other components. - `monthPageSize`: `number | { keyboard: number, button: number }`, default: `1`. The amount of months to navigate by in the day grid when pressing `` or with arrow navigation. +- `children`: `React.ReactNode | (contextValue: CalendarContextValue) => React.ReactNode` + :::success All the props that the picker can pass to the calendar (validation props, value props, etc...) are read both from the props and from `usePickerContext` so that the calendar can be used inside a picker built with composition. @@ -727,16 +759,6 @@ That way, users only have to pass the props specific to the calendar to the `Cal ::: -### `Calendar.FormattedValue` - -Formats the value based on the provided format. - -#### Props - -- Extends `React.HTMLAttributes` - -- `format`: `string` - **required** - ### `Calendar.ContextValue` Utility component to access the calendar public context. @@ -744,6 +766,7 @@ Doesn't render a DOM node (it does not have a `render` prop either). :::success The user can also use `useCalendarContext()`, but a component allows to not create a dedicated component to access things close from `` +We should probably start without it and add it if we feel the need. ::: #### Props diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index 606d0863c3ed0..99fb9935d6c7e 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -191,20 +191,7 @@ If the library does not provide any higher level utilities to create a responsiv import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; import { useMediaQuery } from '@base-ui-components/react-utils/useMediaQuery'; // not sure how the util package will be named import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; -import { Popover } from '@base-ui-components/react/popover'; -import { Dialog } from '@base-ui-components/react/dialog'; - -function DatePicker(props) { - const manager = useDateManager(); - const isDesktop = useMediaQuery('@media (pointer: fine)', { - defaultMatches: true, - }); - - const field = ( - - {/** See field documentation */} - {isDesktop ? ( - 📅 +import { Popover } from '@base-ui-components/react/popover';picker ) : ( 📅 )} @@ -339,8 +326,8 @@ TODO The user can use the ``, `` and `` components to create an action bar and interact with the value: ```tsx -import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Popover } from '@base-ui-components/react/popover'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; {/** See calendar documentation */} @@ -362,18 +349,23 @@ TODO ### Without Material UI -The user can use the `` component to create a toolbar for its picker: +The user can use the `` component to create a toolbar for its picker: ```tsx -import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Popover } from '@base-ui-components/react/popover'; +import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { usePickerContext } from '@base-ui-components/react-x-date-pickers/hooks'; - -
- -
- {/** See calendar documentation */} -
; +function PickerToolbar() { + const { value } = usePickerContext(); + + return ( + +
{value.format('MMMM YYYY')}
+ {/** See calendar documentation */} +
+ ); +} ``` The toolbar can also be used to switch between sections thanks to the `` component: @@ -381,18 +373,25 @@ The toolbar can also be used to switch between sections thanks to the ` -
- - - - - - -
- {/** See calendar documentation */} -
; +function PickerToolbar() { + const { value } = usePickerContext(); + + return ( + +
+ + {value.format('YYYY')} + + + {value.format('DD MMMM')} + +
+ {/** See calendar documentation */} +
+ ); +} ``` ### With Material UI @@ -573,20 +572,6 @@ Top level component that wraps the other components when there is not field UI b Same typing and behavior as today. -### `Picker.FormattedValue` - -Formats the value based on the provided format. - -#### Props - -- Extends `React.HTMLAttributes` - -- `format`: `string` - **required** - -#### Usages in the styled version - -- The title / individual sections in all the toolbar components (in combination with ``) - ### `Picker.ContextValue` Utility component to access the picker public context. @@ -594,6 +579,7 @@ Doesn't render a DOM node (it does not have a `render` prop either). :::success The user can also use `usePickerContext()`, but a component allows to not create a dedicated component to access things close from `` +We should probably start without it and add it if we feel the need. ::: #### Props @@ -610,10 +596,12 @@ Renders a button to set the current value. - `target`: `PickerValidDate` - **required** -- `importance`: `'set' | 'accept'`, default: `'accept'` (equivalent of the `changeImportance` prop on the `shortcut` slot) - - `skipValidation`: `boolean`, default: `false` (by default the button is disabled is the target value is not passing validation) +- `changeImportance`: `'set' | 'accept'`, default: `'accept'` + +- `skipPublicationIfPristine`: `boolean`, default: `false` + #### Usages in the styled version - The List Item of `` (people creating custom UIs can also use this component) @@ -659,7 +647,3 @@ Renders a button to set the active section. - Extends `React.HTMLAttributes` - `target`: `PickerSectionType` (current `FieldSectionType` that would be renamed) - **required** - -#### Usages in the styled version - -- The title / individual sections in all the toolbar components (in combination with ``) From 197f9781eb216c799ba16e525a7cbc4071f2f4ae Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 2 Jan 2025 17:01:30 +0100 Subject: [PATCH 39/46] Fix --- docs/data/date-pickers/rfc-range-calendar.md | 58 +++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/docs/data/date-pickers/rfc-range-calendar.md b/docs/data/date-pickers/rfc-range-calendar.md index 935742f395773..e338b28b29637 100644 --- a/docs/data/date-pickers/rfc-range-calendar.md +++ b/docs/data/date-pickers/rfc-range-calendar.md @@ -21,33 +21,37 @@ The user can use the ``, ` -
- ◀ - - ▶ -
- - - {({ days }) => - days.map((day) => ( - - )) - } - - - {({ weeks }) => - weeks.map((week) => ( - - {({ days }) => - days.map((day) => ( - - )) - } - - )) - } - - + {({ visibleMonth }) => ( + +
+ + {visibleMonth.format('MMMM YYYY')} + +
+ + + {({ days }) => + days.map((day) => ( + + )) + } + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => + days.map((day) => ( + + )) + } + + )) + } + + +
+ )} ; ``` From ede2530c64cfc5787966f8933a96d9053192ed10 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 7 Jan 2025 08:57:47 +0100 Subject: [PATCH 40/46] Apply changes from POC --- docs/data/date-pickers/rfc-calendar.md | 344 +++++++++++-------------- 1 file changed, 148 insertions(+), 196 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index a8ac0fcf11911..ea55190e79aaf 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -20,7 +20,7 @@ The user can use the ``, ``, ` + {({ visibleMonth }) => (
@@ -80,12 +80,12 @@ The user can use the `` and `` com ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - + {({ visibleMonth }) => (
- {visibleMonth.format('YYYY')}} + {visibleMonth.format('YYYY')}
@@ -102,29 +102,23 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; #### Grid layout -The user can use the ``, `` and `` components to create a grid of months and utility components like `` to create a header to navigate across the years: +The user can use the `` and `` components to create a grid of months and utility components like `` to create a header to navigate across the years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - + {({ visibleMonth }) => (
- {visibleMonth.format('YYYY')}} + {visibleMonth.format('YYYY')}
- - {({ rows }) => - rows.map((row) => ( - - {({ months }) => - months.map((month) => ( - - )) - } - + + {({ months }) => + months.map((month) => ( + )) } @@ -163,7 +157,7 @@ The user can use the `` and `` compo ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - + {({ years }) => years.map((year) => ) @@ -174,25 +168,17 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; #### Grid layout -The user can use the ``, `` and `` components to create a grid of years: +The user can use the `` and `` components to create a grid of years: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - - - {({ rows }) => - rows.map((row) => ( - - {({ years }) => - years.map((year) => ( - - )) - } - - )) + + + {({ years }) => + years.map((year) => ) } - + ; ``` @@ -222,43 +208,68 @@ Once the `Calendar.*` unstyled component is ready, the `` should ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - -
{/** See calendar header documentation */}
- - - {({ days }) => - days.map((day) => ( - - )) - } - - - {({ weeks }) => - weeks.map((week) => ( - +function DateCalendar() { + const [value, setValue] = React.useState(null); + const [activeSection, setActiveSection] = React.useState<'day' | 'month' | 'year'>( + 'day', + ); + + const handleValueChange = (newValue, context) => { + if (context.section === 'month' || context.section === 'year') { + setActiveSection('day'); + } + + setValue(newValue); + }; + + return ( + +
{/** See calendar header documentation */}
+ {activeSection === 'day' && ( + + {({ days }) => days.map((day) => ( - + )) } -
- )) - } -
-
- - {({ months }) => - months.map((month) => ( - - )) - } - - - {({ years }) => - years.map((year) => ) - } - -
; + + + {({ weeks }) => + weeks.map((week) => ( + + {({ days }) => + days.map((day) => ( + + )) + } + + )) + } + + + )} + {activeSection === 'month' && ( + + {({ months }) => + months.map((month) => ( + + )) + } + + )} + {activeSection === 'year' && ( + + {({ years }) => + years.map((year) => ( + + )) + } + + )} +
+ ); +} ``` ### With Material UI @@ -283,7 +294,7 @@ When MD3 is supported, the default views of `` should probably b ### Without Material UI -The user can use the `` and `` to build basically any kind of header they could think of: +The user can use the `` to build basically any kind of header they could think of: #### Very basic header (without month and year UI) @@ -311,17 +322,23 @@ import { useCalendarContext, } from '@base-ui-components/react-x-date-pickers/calendar'; -function CalendarHeader() { - const { visibleMonth, activeSection } = useCalendarContext(); +function CalendarHeader(props: { + activeSection: 'day' | 'month' | 'year'; + onActiveSectionChange: (activeSection: 'day' | 'month' | 'year') => void; +}) { + const { activeSection, onActiveSectionChange } = props; + const { visibleMonth } = useCalendarContext(); return (
- + onActiveSectionChange(activeSection === 'year' ? 'month' : 'year') + } > {visibleMonth.format('MMMM YYYY')} {activeSection === 'year' ? '▲' : '▼'} - +
{activeSection === 'day' && (
@@ -333,13 +350,36 @@ function CalendarHeader() { } ``` +The `activeSection` and `onActiveSectionChange` needs to be passed by the parent component: + +```tsx +function DateCalendar() { + const [activeSection, setActiveSection] = React.useState<'day' | 'month' | 'year'>( + 'day', + ); + return ( + +
+ {/** Rest of the UI */} + + ); +} +``` + #### MD3 header ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; -function CalendarHeader() { - const { visibleMonth, activeSection } = useCalendarContext(); +function CalendarHeader(props: { + activeSection: 'day' | 'month' | 'year'; + onActiveSectionChange: (activeSection: 'day' | 'month' | 'year') => void; +}) { + const { activeSection, onActiveSectionChange } = props; + const { visibleMonth } = useCalendarContext(); return (
@@ -347,12 +387,14 @@ function CalendarHeader() { {activeSection === 'day' && ( )} - + onActiveSectionChange(activeSection === 'year' ? 'day' : 'year') + } disabled={activeSection === 'month'} > - {visibleMonth.format('MMMM')}} - + {visibleMonth.format('MMMM')} + {activeSection === 'day' && ( )} @@ -361,12 +403,14 @@ function CalendarHeader() { {activeSection === 'day' && ( )} - + onActiveSectionChange(activeSection === 'month' ? 'day' : 'month') + } disabled={activeSection === 'year'} > - {visibleMonth.format('YYYY')}} - + {visibleMonth.format('YYYY')} + {activeSection === 'day' && ( )} @@ -582,7 +626,7 @@ function CalendarGrid({ offset }) { ); } - +
{/** See demo below for the navigation with multiple months */}
@@ -659,16 +703,16 @@ This is currently not doable. ### Without Material UI -The user can use the `` and `` components to add a column to the grid: +The user can add custom elements to add the week number to the grid: ```tsx {({ days }) => ( - + # - + {days.map((day) => ( ))} @@ -681,7 +725,9 @@ The user can use the `` and ` {({ days }) => ( - + + {days[0].week()} + {days.map((day) => ( ))} @@ -718,9 +764,9 @@ Top level component that wraps the other components. - Extends `React.HTMLAttributes` -- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onValueChange`, `onError` and `timezone`. - Same typing and behavior as today. + Same typing and behavior as today (just `onChange` becomes `onValueChange`) - **Validation props**: `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. @@ -759,20 +805,6 @@ That way, users only have to pass the props specific to the calendar to the `Cal ::: -### `Calendar.ContextValue` - -Utility component to access the calendar public context. -Doesn't render a DOM node (it does not have a `render` prop either). - -:::success -The user can also use `useCalendarContext()`, but a component allows to not create a dedicated component to access things close from `` -We should probably start without it and add it if we feel the need. -::: - -#### Props - -- `children`: `(contextValue: CalendarContextValue) => React.ReactNode` - ### `Calendar.SetVisibleMonth` Renders a button to go to the previous or the next month. @@ -782,7 +814,7 @@ It does not modify the value it only navigates to the target month. - Extends `React.HTMLAttributes` -- `target`: `'previous' | 'next'` +- `target`: `'previous' | 'next' | PickerValidDate` :::success TODO: Clarify the behavior when multiple calendars are rendered at once. @@ -797,22 +829,12 @@ It does not modify the value it only navigates to the target year. - Extends `React.HTMLAttributes` -- `target`: `'previous' | 'next'` +- `target`: `'previous' | 'next' | PickerValidDate` :::success TODO: Clarify the behavior when multiple calendars are rendered at once. ::: -### `Calendar.SetActiveSection` - -Renders a button to set the active section. - -#### Props - -- Extends `React.HTMLAttributes` - -- `target`: `"day" | "month" | "year"` - **required** - ### `Calendar.DaysGrid` Top level component to pick a day. @@ -845,24 +867,6 @@ It expects a function as its children, which receives the list of days to render - `children`: `(params: { days: PickerValidDate[] }) => React.ReactNode` -### `Calendar.DaysGridHeaderCell` - -Renders the header of a day in the week. - -#### Props - -- Extends `React.HTMLAttributes` - -- `value`: `PickerValidDate` - **required**. - -### `Calendar.DaysGridWeekNumberHeaderCell` - -Renders the header of the week number column. - -#### Props - -- Extends `React.HTMLAttributes` - ### `Calendar.DaysGridBody` Renders the content all the days in a month (it is the DOM element that should contain all the weeks). @@ -915,12 +919,6 @@ Renders the cell for a single day. - `value`: `PickerValidDate` - **required** -### `Calendar.DaysGridWeekNumberCell` - -Renders the number of the current week. - -- Extends `React.HTMLAttributes` - ### `Calendar.MonthsList` Top level component to pick a month. @@ -953,42 +951,16 @@ This component takes care of the keyboard navigation (for example + {({ months }) => months.map((month) => ( )) } - + ``` #### Props @@ -997,6 +969,10 @@ It expects a function as its children, which receives the list of months to rend - `children`: `(params: { months: PickerValidDate[] }) => React.ReactNode` +- `cellsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `cellsPerRow`: `number` **required**. + ### `Calendar.MonthsCell` Renders the cell for a single month. @@ -1029,48 +1005,20 @@ This component takes care of the keyboard navigation (for example - {({ rows }) => - rows.map((row) => ) - } - -``` - -#### Props - -- Extends `React.HTMLAttributes` - -- `children`: `(params: { rows: PickerValidDate[] }) => React.ReactNode` - -- `itemsOrder`: `'asc' | 'desc'`, default: `'asc'`. - -- `itemsPerRow`: `number` **required**. - -- `alwaysVisible`: `boolean`, default: `false`. By default this component is only rendered when the active section is `"year"`. - -### `Calendar.YearsRow` - -Renders a row of years. - It expects a function as its children, which receives the list of years to render as a parameter: ```tsx - + {({ years }) => years.map((year) => ) } - + ``` #### Props @@ -1079,6 +1027,10 @@ It expects a function as its children, which receives the list of years to rende - `children`: `(params: { years: PickerValidDate[] }) => React.ReactNode` +- `cellsOrder`: `'asc' | 'desc'`, default: `'asc'`. + +- `cellsPerRow`: `number` **required**. + ### `Calendar.YearsCell` Renders the cell for a single year. From c60d96f516d096eb325da341b08dd87364135b4a Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 7 Jan 2025 09:32:07 +0100 Subject: [PATCH 41/46] Work --- docs/data/date-pickers/rfc-calendar.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index ea55190e79aaf..6311fba3cc505 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -963,6 +963,8 @@ It expects a function as its children, which receives the list of months to rend ``` +This component takes care of the keyboard navigation (for example Arrow Up). + #### Props - Extends `React.HTMLAttributes` @@ -1021,6 +1023,8 @@ It expects a function as its children, which receives the list of years to rende ``` +This component takes care of the keyboard navigation (for example Arrow Up). + #### Props - Extends `React.HTMLAttributes` From cf949c74a978f83b1dd1a5f8057c0e8ef9978eda Mon Sep 17 00:00:00 2001 From: flavien Date: Fri, 17 Jan 2025 17:31:14 +0100 Subject: [PATCH 42/46] Work --- docs/data/date-pickers/rfc-calendar.md | 86 +++------ docs/data/date-pickers/rfc-digital-clock.md | 49 +++-- docs/data/date-pickers/rfc-picker.md | 198 +++++++------------- 3 files changed, 118 insertions(+), 215 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 6311fba3cc505..6b5482b6c4a87 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -23,11 +23,11 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ visibleMonth }) => ( -
+
{visibleMonth.format('MMMM YYYY')} -
+
{({ days }) => @@ -83,11 +83,11 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ visibleMonth }) => ( -
+
{visibleMonth.format('YYYY')} -
+ {({ months }) => months.map((month) => ( @@ -110,11 +110,11 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ visibleMonth }) => ( -
+
{visibleMonth.format('YYYY')} -
+ {({ months }) => months.map((month) => ( @@ -224,7 +224,7 @@ function DateCalendar() { return ( -
{/** See calendar header documentation */}
+
{/** See calendar header documentation */}
{activeSection === 'day' && ( @@ -305,11 +305,11 @@ function CalendarHeader() { const { visibleMonth } = useCalendarContext(); return ( -
+
{visibleMonth.format('MMMM YYYY')} -
+ ); } ``` @@ -330,7 +330,7 @@ function CalendarHeader(props: { const { visibleMonth } = useCalendarContext(); return ( -
+
onActiveSectionChange(activeSection === 'year' ? 'month' : 'year') @@ -345,7 +345,7 @@ function CalendarHeader(props: {
)} -
+ ); } ``` @@ -382,7 +382,7 @@ function CalendarHeader(props: { const { visibleMonth } = useCalendarContext(); return ( -
+
{activeSection === 'day' && ( @@ -415,49 +415,7 @@ function CalendarHeader(props: { )}
-
- ); -} -``` - -#### Header with dropdown for months and years - -The user can create a custom header where the month and the year editing is done through a menu, while the day calendar is always visible below: - -```tsx -import { Menu } from '@base-ui-components/react/menu'; -import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - -function CalendarHeader() { - const { visibleMonth, activeSection } = useCalendarContext(); - - return ( -
- - {visibleMonth.format('MMMM')} - - }> - {({ months }) => - months.map((month) => ( - - )) - } - - - - - {visibleMonth.format('YYYY')} - - }> - {({ years }) => - years.map((year) => ( - - )) - } - - - -
+ ); } ``` @@ -486,7 +444,7 @@ The `` component can be built in a few different ways: function CustomCalendarHeader() { const { currentMonth } = useCalendarContext(); - return
{currentMonth.format('MMMM YYYY')}
; + return
{currentMonth.format('MMMM YYYY')}
; } ``` @@ -508,11 +466,11 @@ The `` component can be built in a few different ways: const { visibleMonth } = useCalendarContext(); return ( -
+
{visibleMonth.format('MMMM YYYY')} -
+ ); } ``` @@ -627,7 +585,7 @@ function CalendarGrid({ offset }) { } -
{/** See demo below for the navigation with multiple months */}
+
{/** See demo below for the navigation with multiple months */}
@@ -657,13 +615,13 @@ function CalendarHeader() { return ( -
+
{visibleMonth.format('MMMM YYYY')} {' – '} {visibleMonth.add(1, 'month').format('MMMM YYYY')} -
+
@@ -681,13 +639,13 @@ function CalendarHeader() { return ( -
+
{visibleMonth.format('MMMM YYYY')} {' – '} {visibleMonth.add(1, 'month').format('MMMM YYYY')} -
+
@@ -768,7 +726,7 @@ Top level component that wraps the other components. Same typing and behavior as today (just `onChange` becomes `onValueChange`) -- **Validation props**: `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. +- **Validation props**: `maxDate`, `minDate`, `disableFuture`, `disablePast`, `isDateInvalid`, `isMonthInvalid` and `isYearInvalid` (equivalent of the current `shouldDisableDate`, `shouldDisableMonth` and `shouldDisableYear`). Same typing and behavior as today. diff --git a/docs/data/date-pickers/rfc-digital-clock.md b/docs/data/date-pickers/rfc-digital-clock.md index 94fae1e523747..69a5eee064122 100644 --- a/docs/data/date-pickers/rfc-digital-clock.md +++ b/docs/data/date-pickers/rfc-digital-clock.md @@ -14,7 +14,7 @@ title: DX - Digital Clock The user can use the `` and `` components to list all the time options with one column per section: ```tsx - + {({ hours }) => hours.map((hour) => ) @@ -42,7 +42,7 @@ The user can use the `` component to add a colum It should be used in combination with the `` component: ```tsx - + {({ hours }) => hours.map((hour) => ) @@ -65,6 +65,11 @@ It should be used in combination with the ` ``` +:::success +We could also skip `` and instead add a `ampm` prop on ``. +But I like the idea of having two distinct components that could host different props in the future. +::: + ### With Material UI TODO @@ -132,7 +137,7 @@ TODO The user can use the `` component to add a column to edit this section: ```tsx - + {({ hours }) => hours.map((hour) => ) @@ -152,13 +157,6 @@ The user can use the `` component to add a column )) } - - {({ meridiems }) => - meridiems.map((meridiem) => ( - - )) - } - ``` @@ -171,10 +169,10 @@ TODO ### Without Material UI The ``, ``, `` and `` components take a `step` prop that allow to customize the step between two consecutive options. -By default, the step is of `1` for the hours and 5 for the minutes and seconds: +By default, the step is of `1` for the hours and `5` for the minutes and seconds: ```tsx - + {({ hours }) => hours.map((hour) => ) @@ -191,7 +189,7 @@ By default, the step is of `1` for the hours and 5 for the minutes and seconds: ``` ```tsx - + {({ hours }) => hours.map((hour) => ) @@ -226,7 +224,7 @@ By default, the `` uses a default format provided by its The user can override this format using the `format` prop: ```tsx - + {({ hours }) => hours.map((hour) => ( @@ -252,7 +250,7 @@ TODO The user can use the `` component to manually list options: ```tsx - + @@ -261,6 +259,23 @@ The user can use the `` component to manually list optio ``` +:::succcess +Do we think it would be interesting to have a component for single-section but where we own the list generation? +Something like: + +```tsx + + + {' '} + // Very unclear DX for the `step` prop + {({ option }) => } + + +``` + +I think it's not a requirement for an MVP. +::: + ### With Material UI TODO @@ -275,11 +290,11 @@ Top level component that wraps the other components. - Extends `React.HTMLAttributes` -- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onValueChange`, `onError` and `timezone`. Same typing and behavior as today. -- **Validation props**: `maxTime`, `minTime`, `disableFuture`, `disablePast`, `shouldDisableTime`. +- **Validation props**: `maxTime`, `minTime`, `disableFuture`, `disablePast`, `isTimeInvalid` (equivalent of the current `shouldDisableTime`). Same typing and behavior as today. diff --git a/docs/data/date-pickers/rfc-picker.md b/docs/data/date-pickers/rfc-picker.md index 99fb9935d6c7e..e300aa2dc957b 100644 --- a/docs/data/date-pickers/rfc-picker.md +++ b/docs/data/date-pickers/rfc-picker.md @@ -11,6 +11,10 @@ title: DX - Picker This page extends the initial proposal made in [#14718](https://github.com/mui/mui-x/issues/14718) ::: +:::success +We might need a `RangePicker.*` component that would expose additional tools like the range position. +::: + ## Usage in a Popover ### Without Material UI @@ -191,10 +195,18 @@ If the library does not provide any higher level utilities to create a responsiv import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; import { useMediaQuery } from '@base-ui-components/react-utils/useMediaQuery'; // not sure how the util package will be named import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; -import { Popover } from '@base-ui-components/react/popover';picker - ) : ( - 📅 - )} +import { Popover } from '@base-ui-components/react/popover'; + +function DatePicker(props) { + const isDesktop = useMediaQuery('@media (pointer: fine)'); + + const field = ( + + {/** See field documentation **/} + {isDesktop + ? 📅 + : 📅 + } ); @@ -229,7 +241,7 @@ import { Popover } from '@base-ui-components/react/popover';picker ); } - + ``` ### With Material UI @@ -242,42 +254,35 @@ import { DatePicker } from '@mui/x-date-pickers/DatePicker'; ; ``` -## Static usage +## Usage with date and time ### Without Material UI -The user can use the `` component to create a static picker. -Most of the time, the user can use directly components such as `Calendar.*`, but the static picker can be useful in the following scenarios: - -- several view components are used together (the main use case is to create a Date Time Picker). The static picker will make sure the value is correctly handled between those components. -- the user wants to add UI elements like a shortcut panel using utility components like ``. +The user can use both the `Calendar.*` and the `DigitalClock.*` components together to render the date and the time picking UI side by side. ```tsx -import { useDateManager } from '@base-ui-components/react-x-date-pickers/managers'; +import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; +import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; +import { DigitalClock } from '@base-ui-components/react-x-date-pickers/digital-clock'; -function StaticDatePicker(props) { - const manager = useDateManager(); +function PickerView() { + const [activeSection, setActiveSection] = React.useState('day'); return ( - + {/** See calendar documentation */} - + {/** See digital clock documentation */} + ); } - -; ``` -### With Material UI - -TODO - -## Usage with date and time - -### Without Material UI +:::success +One big things to still clarify here is how we can provide the right tools for focus management without adding a view management system into our components. +::: -The user can use both the `Calendar.*` and the `DigitalClock.*` components together to render the date and the time picking UI side by side: +If the user wants to set the UI to select the date, then the time, he can conditionally render the view component based on some external state: ```tsx import { Popover } from '@base-ui-components/react/popover'; @@ -285,34 +290,21 @@ import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; import { DigitalClock } from '@base-ui-components/react-x-date-pickers/digital-clock'; - - {/** See calendar documentation */} - {/** See digital clock documentation */} -; -``` - -If the user wants to set the UI to select the date, then the time, he can conditionally render the view component based on the active section: - -```tsx -import { Popover } from '@base-ui-components/react/popover'; -import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; -import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; -import { DigitalClock } from '@base-ui-components/react-x-date-pickers/digital-clock'; -import { isDateSection } from '@base-ui-components/react-x-date-pickers/utils'; +function PickerView() { + const [activeSection, setActiveSection] = React.useState('day'); - - - {({ activeSection }) => - isDateSection(activeSection) ? ( + return ( + + {['day', 'month', 'year'].includes(activeSection) ? ( {/** See calendar documentation */} ) : ( {/** See digital clock documentation */} - ) - } - -; + )} + + ); +} ``` ### With Material UI @@ -349,14 +341,14 @@ TODO ### Without Material UI -The user can use the `` component to create a toolbar for its picker: +The user can use the the `usePickerContext()` hook to access to information like the current value and create a toolbar above the view content: ```tsx import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { usePickerContext } from '@base-ui-components/react-x-date-pickers/hooks'; -function PickerToolbar() { +function PickerView() { const { value } = usePickerContext(); return ( @@ -368,25 +360,26 @@ function PickerToolbar() { } ``` -The toolbar can also be used to switch between sections thanks to the `` component: +This toolbar can also be used to switch between sections if the parent component has a state to decide which one is currently rendered: ```tsx import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; import { usePickerContext } from '@base-ui-components/react-x-date-pickers/hooks'; -function PickerToolbar() { +function PickerView() { + const [activeSection, setActiveSection] = React.useState('day'); const { value } = usePickerContext(); return (
- + +
{/** See calendar documentation */}
@@ -402,7 +395,7 @@ TODO ### Without Material UI -The user can use the `` component in combination with any Tabs / Tab components. +The user can also build a `Tabs` component using the same tools and the toolbar: The example below uses the `Tabs` component from Base UI as an example: @@ -410,31 +403,26 @@ The example below uses the `Tabs` component from Base UI as an example: import { Tabs } from '@base-ui-components/react/tabs'; import { Popover } from '@base-ui-components/react/popover'; import { Picker } from '@base-ui-components/react-x-date-pickers/picker'; -import { isDateSection } from '@base-ui-components/react-x-date-pickers/utils'; - - - {({ activeSection }) => ( - +functon PickerViews() { + const [activeSection, setActiveSection] = React.useState('day'); + + return ( + + - } - > + onActiveSectionChange('day')}> Date - } - > + onActiveSectionChange('hours')}> Time - )} - - {/** See calendar documentation */} -; + {/** See calendar documentation */} + + ) +} ``` ### With Material UI @@ -526,13 +514,13 @@ It expects a function as its children, which receives the context value as a par - `children`: `(contextValue: PickerContextValue) => React.ReactNode` -- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. +- **Value props**: `value`, `defaultValue`, `referenceDate`, `onValueChange`, `onError` and `timezone`. Same typing and behavior as today. - **Validation props**: list based on the `manager` prop - For `useDateManager()` it would be `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. + For `useDateManager()` it would be `maxDate`, `minDate`, `disableFuture`, `disablePast`, `isDateInvalid`, `isMonthInvalid`, `isYearInvalid`. Same typing and behavior as today. @@ -544,48 +532,6 @@ It expects a function as its children, which receives the context value as a par The `onOpenChange` replaces the `onOpen` and `onClose` props in the current implementation -### `Picker.StaticRoot` - -#### Props - -Top level component that wraps the other components when there is not field UI but only views. - -- `manager`: `PickerManager` - **required** - - :::success - See [#15395](https://github.com/mui/mui-x/issues/15395) for context. - ::: - -- `children`: `(contextValue: PickerContextValue) => React.ReactNode` - -- **Value props**: `value`, `defaultValue`, `referenceDate`, `onChange`, `onError` and `timezone`. - - Same typing and behavior as today. - -- **Validation props**: list based on the `manager` prop - - For `useDateManager()` it would be `maxDate`, `minDate`, `disableFuture`, `disablePast`, `shouldDisableDate`, `shouldDisableMonth`, `shouldDisableYear`. - - Same typing and behavior as today. - -- **Form props**: `disabled`, `readOnly`. - - Same typing and behavior as today. - -### `Picker.ContextValue` - -Utility component to access the picker public context. -Doesn't render a DOM node (it does not have a `render` prop either). - -:::success -The user can also use `usePickerContext()`, but a component allows to not create a dedicated component to access things close from `` -We should probably start without it and add it if we feel the need. -::: - -#### Props - -- `children`: `(contextValue: PickerContextValue) => React.ReactNode` - ### `Picker.SetValue` Renders a button to set the current value. @@ -631,19 +577,3 @@ Renders a button to cancel the current value. #### Usages in the styled version - The Button of `` that cancels the value - -### `Picker.SetActiveSection` - -Renders a button to set the active section. - -#### Usages in the styled version - -- The Tab in `` - -- The Tab in `` (might require manually using `usePickerContext` to make the range position change work) - -#### Props - -- Extends `React.HTMLAttributes` - -- `target`: `PickerSectionType` (current `FieldSectionType` that would be renamed) - **required** From 50cf1cfb031c91c83bcbbdd0c2524414b3cff650 Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 20 Jan 2025 16:04:04 +0100 Subject: [PATCH 43/46] Fix --- docs/data/date-pickers/rfc-overview.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/data/date-pickers/rfc-overview.md b/docs/data/date-pickers/rfc-overview.md index 58f3b590bd9a5..98eaf706aa8ab 100644 --- a/docs/data/date-pickers/rfc-overview.md +++ b/docs/data/date-pickers/rfc-overview.md @@ -85,7 +85,3 @@ All the components displayed in the pages below are following the Base UI DX whi background-color: green; } ``` - -## Lifecycle of the components - -- The concept of _view_ is removed in favor of a concept of _active section_ that is shared with the field and make no assumption about how those sections are rendered. From 787c31f7af0a8da9d857c00eec98b9202d6b9998 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 21 Jan 2025 17:20:31 +0100 Subject: [PATCH 44/46] Sync with POC --- docs/data/date-pickers/rfc-calendar.md | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 6b5482b6c4a87..48eac15bc2d22 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -21,11 +21,11 @@ The user can use the ``, ``, ` - {({ visibleMonth }) => ( + {({ visibleDate }) => (
- {visibleMonth.format('MMMM YYYY')} + {visibleDate.format('MMMM YYYY')}
@@ -81,11 +81,11 @@ The user can use the `` and `` com import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - {({ visibleMonth }) => ( + {({ visibleDate }) => (
- {visibleMonth.format('YYYY')} + {visibleDate.format('YYYY')}
@@ -108,11 +108,11 @@ The user can use the `` and `` com import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; - {({ visibleMonth }) => ( + {({ visibleDate }) => (
- {visibleMonth.format('YYYY')} + {visibleDate.format('YYYY')}
@@ -302,12 +302,12 @@ The user can use the `` to build basically any kind import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { visibleMonth } = useCalendarContext(); + const { visibleDate } = useCalendarContext(); return (
- {visibleMonth.format('MMMM YYYY')} + {visibleDate.format('MMMM YYYY')}
); @@ -327,7 +327,7 @@ function CalendarHeader(props: { onActiveSectionChange: (activeSection: 'day' | 'month' | 'year') => void; }) { const { activeSection, onActiveSectionChange } = props; - const { visibleMonth } = useCalendarContext(); + const { visibleDate } = useCalendarContext(); return (
@@ -336,7 +336,7 @@ function CalendarHeader(props: { onActiveSectionChange(activeSection === 'year' ? 'month' : 'year') } > - {visibleMonth.format('MMMM YYYY')} + {visibleDate.format('MMMM YYYY')} {activeSection === 'year' ? '▲' : '▼'}
{activeSection === 'day' && ( @@ -379,7 +379,7 @@ function CalendarHeader(props: { onActiveSectionChange: (activeSection: 'day' | 'month' | 'year') => void; }) { const { activeSection, onActiveSectionChange } = props; - const { visibleMonth } = useCalendarContext(); + const { visibleDate } = useCalendarContext(); return (
@@ -388,12 +388,12 @@ function CalendarHeader(props: { )} {activeSection === 'day' && ( @@ -409,7 +409,7 @@ function CalendarHeader(props: { } disabled={activeSection === 'year'} > - {visibleMonth.format('YYYY')} + {visibleDate.format('YYYY')} {activeSection === 'day' && ( @@ -463,12 +463,12 @@ The `` component can be built in a few different ways: import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CustomCalendarHeader() { - const { visibleMonth } = useCalendarContext(); + const { visibleDate } = useCalendarContext(); return (
- {visibleMonth.format('MMMM YYYY')} + {visibleDate.format('MMMM YYYY')}
); @@ -611,15 +611,15 @@ If the prop receives a number, it will move by the amount of month both for `
- {visibleMonth.format('MMMM YYYY')} + {visibleDate.format('MMMM YYYY')} {' – '} - {visibleMonth.add(1, 'month').format('MMMM YYYY')} + {visibleDate.add(1, 'month').format('MMMM YYYY')}
@@ -635,15 +635,15 @@ But the user can also distinguish both behaviors by providing an object: import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; function CalendarHeader() { - const { visibleMonth } = useCalendarContext(); + const { visibleDate } = useCalendarContext(); return (
- {visibleMonth.format('MMMM YYYY')} + {visibleDate.format('MMMM YYYY')} {' – '} - {visibleMonth.add(1, 'month').format('MMMM YYYY')} + {visibleDate.add(1, 'month').format('MMMM YYYY')}
From 92249f8c62462f0313d6d22872a41c10f7ccca7d Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 23 Jan 2025 09:01:17 +0100 Subject: [PATCH 45/46] Rename Calendar.DaysWeekRow => Calendar.DaysGridRow --- docs/data/date-pickers/rfc-calendar.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index 6311fba3cc505..693c2549d4da0 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -15,7 +15,7 @@ This page extends the initial proposal made in [#15598](https://github.com/mui/m ### Without Material UI -The user can use the ``, ``, ``, ``, `` and `` components to create a grid of days: +The user can use the ``, ``, ``, ``, `` and `` components to create a grid of days: ```tsx import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; @@ -39,13 +39,13 @@ import { Calendar } from '@base-ui-components/react-x-date-pickers/calendar'; {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => ( )) } - + )) } @@ -237,13 +237,13 @@ function DateCalendar() { {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => ( )) } - + )) } @@ -612,13 +612,13 @@ function CalendarGrid({ offset }) { {({ weeks }) => weeks.map((week) => ( - + {({ days }) => days.map((day) => ( )) } - + )) } @@ -722,7 +722,7 @@ The user can add custom elements to add the week number to the grid: {({ weeks }) => weeks.map((week) => ( - + {({ days }) => ( @@ -733,7 +733,7 @@ The user can add custom elements to add the week number to the grid: ))} )} - + )) } @@ -876,7 +876,7 @@ It expects a function as its children, which receives the list of weeks to rende ```tsx {({ weeks }) => - weeks.map((week) => ) + weeks.map((week) => ) } ``` @@ -887,18 +887,18 @@ It expects a function as its children, which receives the list of weeks to rende - `children`: `(params: { weeks: PickerValidDate[] }) => React.ReactNode` -### `Calendar.DaysWeekRow` +### `Calendar.DaysGridRow` Renders the content all the days in a week. It expects a function as its children, which receives the list of days to render and the week number as a parameter: ```tsx - + {({ days }) => days.map((day) => ) } - + ``` #### Props From 686953cad22611d577182b5387a1161bff2f4313 Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 23 Jan 2025 09:28:40 +0100 Subject: [PATCH 46/46] --amend --- docs/data/date-pickers/rfc-calendar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/date-pickers/rfc-calendar.md b/docs/data/date-pickers/rfc-calendar.md index ed811d2af7de7..7863ed0f0d267 100644 --- a/docs/data/date-pickers/rfc-calendar.md +++ b/docs/data/date-pickers/rfc-calendar.md @@ -388,7 +388,7 @@ function CalendarHeader(props: { )}