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

[base] Override the types of slotProps per slot #35964

Merged
merged 5 commits into from
Feb 13, 2023

Conversation

hbjORbj
Copy link
Member

@hbjORbj hbjORbj commented Jan 27, 2023

Closes #34906

This PR goes with option 1 described in the issue above

  1. Have a separate type for each slot override (see [POC] slot overrides: interface per slot #35662)
export interface BadgeUnstyledRootSlotPropsOverrides {}
export interface BadgeUnstyledBadgeSlotPropsOverrides {}

export interface BadgeUnstyledOwnProps {
  // ...
  slotProps?: {
    root?: SlotComponentProps<
      'span',
      BadgeUnstyledRootSlotPropsOverrides,
      BadgeUnstyledOwnerState
    >;
    badge?: SlotComponentProps<
      'span',
      BadgeUnstyledBadgeSlotPropsOverrides,
      BadgeUnstyledOwnerState
    >;
  };
}

This could be slightly easier to use for developers. They would augment the required interface and the changes will apply only to one slot.
It would be slightly more cumbersome to implement, though, and would create many new types (up to 8 in case of SliderUnstyled).


Note to be added to CHANGELOG in the upcoming release

Breaking Changes for MUI Base:

  • The way of overriding the types of slotProps prop has changed. Developers can now override them per slot.
  • The naming convention of ${ComponentName}ComponentsPropsOverrides is replaced with ${ComponentName}${SlotName}SlotPropsOverrides.
 declare module '@mui/base/SwitchUnstyled' {
-  interface SwitchUnstyledComponentsPropsOverrides {
+  interface SwitchUnstyledRootSlotPropsOverrides {
     'data-a'?: string;
+  }
+
+  interface SwitchUnstyledInputSlotPropsOverrides {
     'data-b'?: string;
+  }
+
+  interface SwitchUnstyledThumbSlotPropsOverrides {
     'data-c'?: string;
+  }
+
+  interface SwitchUnstyledTrackSlotPropsOverrides {
     'data-d'?: string;
   }
 }

@mui-bot
Copy link

mui-bot commented Jan 27, 2023

Netlify deploy preview

No updates.

Bundle size report

No bundle size changes

Generated by 🚫 dangerJS against 40d5b49

@hbjORbj hbjORbj changed the title [Base] Override the types of slotProps per slot [Base] Override the types of slotProps per slot Jan 27, 2023
@hbjORbj hbjORbj changed the title [Base] Override the types of slotProps per slot [base] Override the types of slotProps per slot Jan 27, 2023
@hbjORbj hbjORbj added this to the MUI Base stable release milestone Jan 27, 2023
@hbjORbj hbjORbj self-assigned this Jan 27, 2023
@michaldudak
Copy link
Member

Looks good! As this is a breaking change, could you please add a short description of changes that need to be done by developers after updating to this version?

@hbjORbj
Copy link
Member Author

hbjORbj commented Feb 1, 2023

Sure, I will try writing a Codemod script as well for this breaking change.

@michaldudak
Copy link
Member

The codemod could be tricky (if not impossible) to get right. It's hard to know which slots a developer wants to override (unless you create overrides for all of them, for example copying the shape of InputUnstyledComponentsPropsOverrides to both InputUnstyledRootSlotOverrides and InputUnstyledInputSlotOverrides)

@hbjORbj
Copy link
Member Author

hbjORbj commented Feb 2, 2023

(unless you create overrides for all of them, for example copying the shape of InputUnstyledComponentsPropsOverrides to both InputUnstyledRootSlotOverrides and InputUnstyledInputSlotOverrides)

Yes, this was my idea. So developers can clean it up afterwards. I thought it's still useful as it reduces lots of manual work for those who have many of these type declarations. Let me know if you think it's not worth the effort.

e.g.,

actual.ts:
declare module '@mui/base/SwitchUnstyled' {
  interface SwitchUnstyledComponentsPropsOverrides {
    'data-a'?: string;
    'data-b'?: string;
    'data-c'?: string;
    'data-d'?: string;
  }
}

to

expected.ts:
declare module '@mui/base/SwitchUnstyled' {
  interface SwitchUnstyledRootSlotOverrides {
    'data-a'?: string;
    'data-b'?: string;
    'data-c'?: string;
    'data-d'?: string;
  }

  interface SwitchUnstyledInputSlotOverrides {
    'data-a'?: string;
    'data-b'?: string;
    'data-c'?: string;
    'data-d'?: string;
  }

  interface SwitchUnstyledThumbSlotOverrides {
    'data-a'?: string;
    'data-b'?: string;
    'data-c'?: string;
    'data-d'?: string;
  }

  interface SwitchUnstyledTrackSlotOverrides {
    'data-a'?: string;
    'data-b'?: string;
    'data-c'?: string;
    'data-d'?: string;
  }
}

Jscodeshift supports something like root.find(j.DeclareInterface) or root.find(j.declareModule), so I thought it parses type declarations, but maybe not, because when I run the code above, it throws a syntax error saying semicolon is missing. I've been trying to figure this out. Do you have any clues?

@michaldudak
Copy link
Member

OK, it makes sense as it'll make the code run at least.
As for the error you're seeing - I see a similar one when the babel/eslint-parser is used (https://astexplorer.net/#/gist/ad6d997d4aa84bb76027304d5d23ab79/d86b107bf5fcb06c55c1603b1a808a55cb75af44). Changing the parser to typescript does solve the issue. See if changing jscodeshift config does help.

@hbjORbj
Copy link
Member Author

hbjORbj commented Feb 9, 2023

The codemod's taking way longer than I expected. I will drop it. I reverted codemod-related changes and added a note to the description of the PR, which should be added to the CHANGELOG of the upcoming release.

@michaldudak
Copy link
Member

In SelectUnstyled.spec.tsx and MultiSelectUnstyled.spec.tsx there are tests with names containing ComponentsPropsOverrides. Could you rename them as well? Aside from that, it's good to be merged.

@hbjORbj
Copy link
Member Author

hbjORbj commented Feb 13, 2023

Thanks. Done in this commit: Rename some functions in type tests.

@@ -6,7 +6,7 @@ import { SlotComponentProps } from '../utils';

export type PopperPlacementType = Options['placement'];

interface PopperUnstyledComponentsPropsOverrides {}
interface PopperUnstyledRootSlotPropsOverrides {}
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if it's related to this PR, but shouldn't this interface be exported?

We've encountered an issue when upgrading MUI Core packages in mui/mui-x#7905:
https://ci.codesandbox.io/status/mui/mui-x/pr/7905/builds/349844

cmd: 'yarn tsc -b /tmp/fad0ee40/packages/grid/x-data-grid-generator/tsconfig.build.json',
  stdout: '$ /tmp/fad0ee40/node_modules/.bin/tsc -b /tmp/fad0ee40/packages/grid/x-data-grid-generator/tsconfig.build.json\n' +
    `../x-data-grid/src/components/panel/GridPanel.tsx(38,7): error TS4023: Exported variable 'GridPanelRoot' has or is using name 'PopperUnstyledRootSlotPropsOverrides' from external module "/tmp/fad0ee40/node_modules/@mui/base/PopperUnstyled/PopperUnstyled.types" but cannot be named.\n` +

cc @michaldudak

Copy link
Member

Choose a reason for hiding this comment

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

Yes, absolutely. Thanks for letting me know. I'll review other cases and fix it right away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[Base] Improve the slotProps type overriding DX
4 participants