Skip to content

Conversation

LukasTy
Copy link
Member

@LukasTy LukasTy commented Jul 21, 2025

Noticed a problem with inputAdornment resolution while exploring #17738 and checking https://mui.com/x/react-date-pickers/custom-opening-button/#add-an-icon-next-to-the-opening-button
Screenshot 2025-07-21 at 17 30 39

The problem is on this line:

const { ownerState: endInputAdornmentOwnerState, ...endInputAdornmentProps } = useSlotProps({
elementType: InputAdornment,
externalSlotProps: slotProps?.inputAdornment,

A forgotten case to handle ?? pickerFieldUIContext.slots.inputAdornment.
This felt too fragile to me, given that we've already made a mistake here without noticing. 🙈


This particular issue has been recently resolved with a single line targeted fix: #19399, but I feel like the general approach could still be improved.
Besides, this PR also fixes an additional issue.


I refactored how slots and slotProps are propagated to avoid the need to target slotProps ?? context.slotProps.

@LukasTy LukasTy self-assigned this Jul 21, 2025
@LukasTy LukasTy added type: bug It doesn't behave as expected. scope: pickers Changes related to the date/time pickers. labels Jul 21, 2025
@mui-bot
Copy link

mui-bot commented Jul 21, 2025

Deploy preview: https://deploy-preview-18867--material-ui-x.netlify.app/

Bundle size report

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 🔺+7B(0.00%) ▼-2B(0.00%)
@mui/x-date-pickers-pro 🔺+105B(+0.03%) 🔺+17B(+0.02%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)

Details of bundle changes

Generated by 🚫 dangerJS against 401b4a1

Comment on lines +138 to +140
{...(isSingleInput && {
inputRef,
})}
Copy link
Member Author

Choose a reason for hiding this comment

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

Multi Input fields do not support inputRef prop

</InputAdornment>
);
}
// handle the case of showing custom `inputAdornment` for Field components
Copy link
Member Author

Choose a reason for hiding this comment

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

This is to handle a case when a field component would have an inputAdornment slot.
Technically, the API contract declares support for it... 🤷
Basically, to handle a DateField component instead of DatePicker in this demo.

* Overridable component slots.
* @default {}
*/
slots?: PickerFieldUISlots;
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the main change, PickerFieldUi no longer supports slots and slotProps AND the same props in the context.
In every case, these props are passed via context.

Copy link
Member

@flaviendelangle flaviendelangle left a comment

Choose a reason for hiding this comment

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

Thanks for taking a look at it!

</Layout>
</PickersModalDialog>
</PickerFieldUIContextProvider>
<Field slots={slots} slotProps={slotProps} inputRef={inputRef} {...fieldProps} />
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this remove the ability to use props.slotProps.field.slotProps.xxx at the picker level?
For example:

<DatePicker 
  slotProps={{
    field: {
      slotProps: {
        clearIcon: { sx: { opacity: 0 } },
      }
    }
  }}
 />

Since it's part of fieldProps but now it would override the props we pass and potentially break stuff (remove the toolbar title id for example).

In most cases it's probably not something we want to encourage (since the slots also exist at the picker level).
But it might be required for some edge cases

Copy link
Member Author

Choose a reason for hiding this comment

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

I've tested the snippet you provided in the deployed doc, and it seems to work. 🤔 🤷
Screenshot 2025-07-28 at 09 18 06

Copy link
Member

Choose a reason for hiding this comment

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

OK I did found the scenario that do not work 😆

import * as React from 'react';
import dayjs from 'dayjs';
import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';

export default function BasicDatePicker() {
  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <DemoContainer components={['DatePicker']}>
        <DatePicker
          defaultValue={dayjs()}
          slotProps={{
            openPickerButton: {
              sx: { color: 'green' },
            },
            field: {
              slotProps: {
                openPickerButton: { 'data-testid': 'open-picker-button' },
              },
            },
          }}
        />
      </DemoContainer>
    </LocalizationProvider>
  );
}

From what I can see, on master it's slotProps.openPickerButton that has the highest priority.
And on your PR it's slotProps.field.slotProps.openPickerButton (because of the spread I commented on I think).

Both fail to correctly merge the 2 objects though.

Feel free to ignore it if you feel it's too much of an edge case.
It's problematic if we set one of the two internally (because it would prevent the user to user the other one without bugs), but I don't think we do.

Copy link
Member Author

@LukasTy LukasTy Sep 10, 2025

Choose a reason for hiding this comment

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

@flaviendelangle I have updated the solution.
Added a few tests to ensure the fixed Field.slots.inputAdornment behavior stays intact.
Also inverted the order of props to keep the existing behavior you noticed in your comment.

I will just add a note, that based on TS, your example is invalid, field slotProp does not have it's own slotProps. 🙈

@LukasTy LukasTy requested a review from flaviendelangle July 28, 2025 06:19
@LukasTy LukasTy force-pushed the fix-pickers-inputAdornment-behavior branch from 28b5b0d to dce13e3 Compare July 31, 2025 14:11
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Sep 2, 2025
Copy link

github-actions bot commented Sep 2, 2025

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Sep 10, 2025
@LukasTy LukasTy changed the title [pickers] Ensure slots and slotProps are propagated to internal component [pickers] Refactor slots and slotProps propagation strategy Sep 10, 2025
render(
<DateField
enableAccessibleFieldDOMStructure
slots={{ inputAdornment: CustomInputAdornment }}
Copy link
Member Author

@LukasTy LukasTy Sep 10, 2025

Choose a reason for hiding this comment

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

Add tests to ensure this slot behaves as expected on Field components - this is the main bug-fix in this PR.

@LukasTy LukasTy requested a review from MBilalShafi September 10, 2025 12:43
Copy link
Member

@flaviendelangle flaviendelangle left a comment

Choose a reason for hiding this comment

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

Couldn't find any problematic edge case 👌

@LukasTy LukasTy merged commit 8a264a1 into mui:master Sep 15, 2025
21 checks passed
@LukasTy LukasTy deleted the fix-pickers-inputAdornment-behavior branch September 15, 2025 08:38
JCQuintas pushed a commit to JCQuintas/mui-x that referenced this pull request Sep 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: pickers Changes related to the date/time pickers. type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants