Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/mui-material/src/Button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,9 @@ const Button = React.forwardRef(function Button(inProps, ref) {
</span>
) : null;

// Don't forward the 'root' classes to the ButtonBase, as they will get duplicated with the one passed to the className prop.
const { root, ...forwardedClasses } = classes;

return (
<ButtonRoot
ownerState={ownerState}
Expand All @@ -593,7 +596,7 @@ const Button = React.forwardRef(function Button(inProps, ref) {
type={type}
id={loading ? loadingId : idProp}
{...other}
classes={classes}
classes={forwardedClasses}
>
{startIcon}
{loadingPosition !== 'end' && loader}
Expand Down
8 changes: 8 additions & 0 deletions packages/mui-material/src/Button/Button.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ describe('<Button />', () => {
expect(button).not.to.have.attribute('aria-disabled');
});

it('does not pass classes.root to ButtonBase classes', () => {
render(<Button classes={{ root: 'my-root-class' }}>Hello</Button>);
const button = screen.getByRole('button');
const classList = button.className.split(' ');
// The root class is not duplicated, it should only be applied once via the className prop.
expect(classList.filter((c) => c === 'my-root-class')).to.have.length(1);
});

it('startIcon and endIcon should have icon class', () => {
render(
<Button startIcon={<span>start icon</span>} endIcon={<span>end icon</span>}>
Expand Down
5 changes: 4 additions & 1 deletion packages/mui-material/src/Fab/Fab.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ const Fab = React.forwardRef(function Fab(inProps, ref) {

const classes = useUtilityClasses(ownerState);

// Don't forward the 'root' class to the ButtonBase, as it will get duplicated with the one passed to the className prop.
const { root, ...forwardedClasses } = classes;

return (
<FabRoot
className={clsx(classes.root, className)}
Expand All @@ -201,7 +204,7 @@ const Fab = React.forwardRef(function Fab(inProps, ref) {
ownerState={ownerState}
ref={ref}
{...other}
classes={classes}
classes={forwardedClasses}
>
{children}
</FabRoot>
Expand Down
7 changes: 7 additions & 0 deletions packages/mui-material/src/Fab/Fab.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ describe('<Fab />', () => {
expect(container.querySelector('button')).to.have.class(disabledClassName);
});

it('does not pass classes.root to ButtonBase classes', () => {
render(<Fab classes={{ root: 'my-root-class' }}>Fab</Fab>);
const button = screen.getByRole('button');
const classList = button.className.split(' ');
expect(classList.filter((c) => c === 'my-root-class')).to.have.length(1);
});

it('should render Icon children with right classes', () => {
const childClassName = 'child-woof';
const iconChild = <Icon data-testid="icon" className={childClassName} />;
Expand Down
5 changes: 4 additions & 1 deletion packages/mui-material/src/ListItemButton/ListItemButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ const ListItemButton = React.forwardRef(function ListItemButton(inProps, ref) {

const classes = useUtilityClasses(ownerState);

// Don't forward the 'root' class to the ButtonBase, as it will get duplicated with the one passed to the className prop.
const { root, ...forwardedClasses } = classes;

const handleRef = useForkRef(listItemRef, ref);

return (
Expand All @@ -206,7 +209,7 @@ const ListItemButton = React.forwardRef(function ListItemButton(inProps, ref) {
ownerState={ownerState}
className={clsx(classes.root, className)}
{...other}
classes={classes}
classes={forwardedClasses}
>
{children}
</ListItemButtonRoot>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ describe('<ListItemButton />', () => {
expect(screen.getByRole('button')).not.to.have.class(classes.gutters);
});

it('does not pass classes.root to ButtonBase classes', () => {
render(<ListItemButton classes={{ root: 'my-root-class' }}>Item</ListItemButton>);
const button = screen.getByRole('button');
const classList = button.className.split(' ');
expect(classList.filter((c) => c === 'my-root-class')).to.have.length(1);
});

describe('context: dense', () => {
it('should forward the context', () => {
let context = null;
Expand Down
5 changes: 4 additions & 1 deletion packages/mui-material/src/MenuItem/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ const MenuItem = React.forwardRef(function MenuItem(inProps, ref) {

const classes = useUtilityClasses(props);

// Don't forward the 'root' class to the ButtonBase, as it will get duplicated with the one passed to the className prop.
const { root, ...forwardedClasses } = classes;

const rovingItemProps = useRovingTabIndexItem({
id: rovingItemId,
ref,
Expand Down Expand Up @@ -256,7 +259,7 @@ const MenuItem = React.forwardRef(function MenuItem(inProps, ref) {
className={clsx(classes.root, className)}
{...other}
ownerState={ownerState}
classes={classes}
classes={forwardedClasses}
/>
</ListContext.Provider>
);
Expand Down
11 changes: 11 additions & 0 deletions packages/mui-material/src/MenuItem/MenuItem.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ describe('<MenuItem />', () => {
expect(screen.queryByRole('option')).not.to.equal(null);
});

it('does not pass classes.root to ButtonBase classes', () => {
render(
<MenuList>
<MenuItem classes={{ root: 'my-root-class' }}>Item</MenuItem>
</MenuList>,
);
const menuitem = screen.getByRole('menuitem');
const classList = menuitem.className.split(' ');
expect(classList.filter((c) => c === 'my-root-class')).to.have.length(1);
});

describe('event callbacks', () => {
/**
* @type {Array<keyof typeof fireEvent>}
Expand Down
Loading