Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DatePicker] Make the month drop-down from CalendarPicker available in sx #6218

Closed
2 tasks done
TheRealCuran opened this issue Sep 19, 2022 · 10 comments
Closed
2 tasks done
Labels
component: DatePicker The React component. component: pickers This is the name of the generic UI component, not the React module! customization: css Design CSS customizability dx Related to developers' experience

Comments

@TheRealCuran
Copy link

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Summary 💡

I maintain an Electron app, that sets a global fontSize of 1.3rem. This size propagates to the font size of the text in the month drop-down of the <CalendarPicker /> component, making it overflow:
image

I thought it would be easy fixing this, by adding a sx property to my <DatePicker /> and (re-)set the fontSize to a better value for this particular component. However I didn't manage to address the <CalendarPicker />, since it gets created dynamically and especially since there is a <div> with the role="presentation" that overwrites any value you might assign to & .MuiCalendarPicker-root:
image

I did try stuff like:

<DatePicker
  sx={{
    '& .MuiCalendarPicker-root': {
      '& div[role="presentation"]': {
        fontSize: 'initial', 
      },
    },
  }}
/>

but as I said, that never got applied, since the component is inserted dynamically (AFAICT).

In the end I put the above snippet into the theme (which is OK for me, since I only have these pickers in one view and the size issue applies to all of them anyway):

MuiCalendarPicker: {
  styleOverrides: {
    root: sx({
      '& div[role="presentation"]': {
        fontSize: 'initial',
      },
    }),
  },
},

I would love to have a way to set this in my <DatePicker>'s sx property. I imagine something like this:

<DatePicker
  sx={{
    '& .MuiCalendarPicker-select': {
      fontSize: 'initial', // or whatever other property you might want to set
    },
  }}
/>

This also applies to .MuiCalendarPicker-root, because if that was reachable, it would be possible to force the fontSize in any case.

Examples 🌈

This is how I want it to look:
image

Motivation 🔦

I had to abuse the theme to style a particular component. And if I had to do different sizes for different pages I would already have to work with two themes, introduce styled components, etc. to change the value of one sub-component properties style.

Order ID 💳 (optional)

47016

@TheRealCuran TheRealCuran added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Sep 19, 2022
@LukasTy
Copy link
Member

LukasTy commented Sep 20, 2022

Hello @TheRealCuran
We've just recently released (v5.0.2) quite a big overhaul of pickers styling in both themeAugmentation (TS) side and adding classes to various components missing them.

I've tried replicating your case in web and was able to solve the issue with a very similar solution to your expected one:

sx={{
  '& .MuiPickersCalendarHeader-label': {
    fontSize: 'initial',
  },
}}

Could you confirm if it solves your issue?

@LukasTy LukasTy added component: pickers This is the name of the generic UI component, not the React module! component: DatePicker The React component. customization: css Design CSS customizability dx Related to developers' experience and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Sep 20, 2022
@TheRealCuran
Copy link
Author

Hey @LukasTy ,
betrayed by my Renovate instance :-/ (meant I didn't see the 5.0.2 update). Anyway this does not solve my issue with <DatePicker /> and the styling of the used <CalendarPicker /> component. I see the new CSS classes, but the override from the sx prop in <DatePicker />still doesn't get applied:
image

My <DatePicker /> looks like this:

<DatePicker
  sx={{
    '& .MuiPickersCalendarHeader-label': {
      fontSize: 'initial',
    },
  }}
  ampm={false}
  inputFormat="MM/yyyy"
  mask="__/____"
  views={['year', 'month']}
  renderInput={({ InputProps, ...params }) => (
    <TextField
      {...params}
      InputProps={{
        ...InputProps,
        endAdornment: (
          <React.Fragment>
            {this.props.searchOptions.fromDate && (
            <IconButton onClick={(e) => {
              e.stopPropagation();
              actions.searchSelectFrom(null);
            }}
            >
              <Clear />
            </IconButton>
            )}
            {InputProps?.endAdornment}
          </React.Fragment>
        ),
      }}
    />
  )}
  aria-label="select start date"
  value={this.dateFromEpoch(this.props.searchOptions.fromDate)}
  onChange={newDate => actions.searchSelectFrom(newDate.valueOf())}
/>

But maybe I am doing something really wrong here? If I move this to the theme it works again, which is already an improvement, since I get rid of the experimental sx() there and get something that is directly addressable.

Apart from that: I can't find the CSS class .MuiPickersCalendarHeader-label in the documentation, which would have helped in finding out about it. ;-)
image

@LukasTy
Copy link
Member

LukasTy commented Sep 20, 2022

@TheRealCuran Sorry for causing confusion with sx solution. I probably mistakenly tested it with StaticDatePicker where it would work.
In usual DatePicker the sx prop won't work as it is not propagated to the popper/modal, which is opened and appended to the bottom of body (be default).

If you need it fixed globally in your application, I would say that using a styleOverride is the easiest approach.

Apart from that: I can't find the CSS class .MuiPickersCalendarHeader-label in the documentation, which would have helped in finding out about it. ;-)

Yes, we are aware of this shortcoming as we did not update the documentation to include all the possible pickers sub-components, which are now style-able/overridable.
We'll have to think of how to improve this (documentation) part with the next major release.
For now, the easiest way to identify what is overridable is using TS codebase and importing import type {} from '@mui/x-date-pickers/themeAugmentation'; which will provide code completion with all the possible options.

@TheRealCuran
Copy link
Author

In usual DatePicker the sx prop won't work as it is not propagated to the popper/modal, which is opened and appended to the bottom of body (be default).

Yeah, that is basically what this feature request is about: provide a way to style those dynamic parts too through sx (I don't mind if I need to use a special syntax for it or a special tool to generate it; maybe it could also be made available through the componentProps and then have a distinct sx in there?).

Yes, we are aware of this shortcoming as we did not update the documentation to include all the possible pickers sub-components, which are now style-able/overridable.
We'll have to think of how to improve this (documentation) part with the next major release.

That would be much appreciated, I had other issues, where I only found the missing documentation part somewhere in a ticket or elsewhere.

For now, the easiest way to identify what is overridable is using TS codebase and importing import type {} from '@mui/x-date-pickers/themeAugmentation'; which will provide code completion with all the possible options.

This app is sadly still purely JS and while I do have a branch converting it to TS, that one needs a lot more work (mostly because it is the best time to get rid of some other technical debt as well). But thanks for the suggestion.

@LukasTy
Copy link
Member

LukasTy commented Sep 20, 2022

Yeah, that is basically what this feature request is about: provide a way to style those dynamic parts too through sx (I don't mind if I need to use a special syntax for it or a special tool to generate it; maybe it could also be made available through the componentProps and then have a distinct sx in there?).

I'm just curious to know—do you specifically need to have different styles through the application?

Because the sx prop is a new approach introduced in v5 with the indent of having easy way to provide styling in certain cases. There might still be a few instances missing correct usage/propagation of this prop. Although, we've made effort to apply sx prop to the root element on every root pickers component.
Whereas the styleOverrides have existed previously as arguably a better DX for overriding certain styled components styles and helps to achieve consistent styling needs among the application.

TL.DR.:

  • use styleOverrides for styles needed throughout application
  • use sx for styles needed in certain use cases

@TheRealCuran
Copy link
Author

Yeah, I do need the ability to style this individually and would appreciate the sx option very much. There is an update in the queue which will add another picker in another place, where I already saw, that I would like to have the ability to override some of the <CalendarPicker /> properties.

And I think what is missing here (and probably other places) is, that sx can only address the styles of directly rendered (sub) components. If something is added dynamically it becomes inaccessible. And that would be really helpful to have as a one-off solution as well. sx was an awesome edition to the v5 update, I really love it.

@LukasTy
Copy link
Member

LukasTy commented Sep 20, 2022

I see, in such case, I'd say that your best bet with the current implementation is the following snippet:

// overrides style in desktop version
PaperProps={{
  sx: {
    '.MuiPickersCalendarHeader-label': {
      fontSize: 'initial',
    },
  },
}}
// overrides style in mobile version (if you need it)
DialogProps={{
  sx: {
    '.MuiPickersCalendarHeader-label': {
      fontSize: 'initial',
    },
  },
}}

As you can see, this case helped in discovering an inconsistency—MobileDatePicker should also consume and use PaperProps as the Desktop version does.

@TheRealCuran
Copy link
Author

Thanks! Yeah, that looks good.

I leave it up to you if you want to keep this request open or not. I can see arguments for both solutions being "better". Pushing this into the componentsProps (or in this case specialised properties on the picker) has the benefit of clearly separating where a style should be applied. On the other hand having it in the sx of the actual component I am setting up feels more like the way sx (and styled components) are training me to do my styles. At least that's what I get from the current docs, where having eg. a styled component is looking like this:

export const MyStyledComp = styled(MyStyledCompImpl, {
  name: 'MyStyledComp',
  slot: 'Root',
})<MyStyledCompProps>(({ theme }) => ({
  '& .MyStyledComp-active': {
    // some props here
    '&:hover': {
      // some other props here
    }
  },
}))

@LukasTy
Copy link
Member

LukasTy commented Sep 20, 2022

Pushing this into the componentsProps (or in this case specialised properties on the picker) has the benefit of clearly separating where a style should be applied.

I'm not sure it would be the best approach to add a prop for basically every different component.
Pickers are a bit more rare case, because they have a Popup and Modal components, which are not children of the root component in the DOM, hence, we can't override all the styles with the sx prop on the root (DatePicker in this case) component.
But that's the reason we have such props as PaperProps—to which we can provide an sx prop and override any styles for children elements in the Paper component.

Do you see any possible non-intrusive improvement for this case @alexfauquette @flaviendelangle ?

@LukasTy
Copy link
Member

LukasTy commented Jul 14, 2023

This no longer seem like a problem as we can easily target all slots and pass the sx prop to them if needed.
The up-to-date solution for this problem (#6218 (comment)) could be:

slotProps={{
  layout: {
    sx: {
      ".MuiPickersCalendarHeader-label": {
        fontSize: "inherit"
      }
    }
  }
}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: DatePicker The React component. component: pickers This is the name of the generic UI component, not the React module! customization: css Design CSS customizability dx Related to developers' experience
Projects
None yet
Development

No branches or pull requests

2 participants