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

[List] Migrate ListItemIcon to emotion #24630

Merged
merged 9 commits into from
Jan 27, 2021
5 changes: 3 additions & 2 deletions docs/pages/api-docs/list-item-icon.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"props": {
"children": { "type": { "name": "node" } },
"classes": { "type": { "name": "object" } }
"classes": { "type": { "name": "object" } },
"sx": { "type": { "name": "object" } }
},
"name": "ListItemIcon",
"styles": {
Expand All @@ -14,6 +15,6 @@
"filename": "/packages/material-ui/src/ListItemIcon/ListItemIcon.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/lists/\">Lists</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"componentDescription": "A simple wrapper to apply `List` styles to an `Icon` or `SvgIcon`.",
"propDescriptions": {
"children": "The content of the component, normally <code>Icon</code>, <code>SvgIcon</code>, or a <code>@material-ui/icons</code> SVG icon element.",
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details."
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details.",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/basics/#the-sx-prop\">`sx` page</a> for more details."
},
"classDescriptions": {
"root": { "description": "Styles applied to the root element." },
Expand Down
7 changes: 6 additions & 1 deletion packages/material-ui/src/ListItemIcon/ListItemIcon.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { InternalStandardProps as StandardProps } from '..';
import { SxProps } from '@material-ui/system';
import { InternalStandardProps as StandardProps, Theme } from '..';

export interface ListItemIconProps extends StandardProps<React.HTMLAttributes<HTMLDivElement>> {
/**
Expand All @@ -15,6 +16,10 @@ export interface ListItemIconProps extends StandardProps<React.HTMLAttributes<HT
/** Styles applied to the root element when the parent `ListItem` uses `alignItems="flex-start"`. */
alignItemsFlexStart?: string;
};
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
}

export type ListItemIconClassKey = keyof NonNullable<ListItemIconProps['classes']>;
Expand Down
78 changes: 56 additions & 22 deletions packages/material-ui/src/ListItemIcon/ListItemIcon.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,69 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import withStyles from '../styles/withStyles';
import { deepmerge } from '@material-ui/utils';
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import experimentalStyled from '../styles/experimentalStyled';
import useThemeProps from '../styles/useThemeProps';
import { getListItemIconUtilityClass } from './listItemIconClasses';
import ListContext from '../List/ListContext';

export const styles = (theme) => ({
/* Styles applied to the root element. */
root: {
minWidth: 56,
color: theme.palette.action.active,
flexShrink: 0,
display: 'inline-flex',
const overridesResolver = (props, styles) => {
const { styleProps } = props;

return deepmerge(styles.root || {}, {
...(styleProps.alignItems === 'flex-start' && styles.alignItemsFlexStart),
});
};

const useUtilityClasses = (styleProps) => {
const { alignItems, classes } = styleProps;

const slots = {
root: ['root', alignItems === 'flex-start' && 'alignItemsFlexStart'],
};

return composeClasses(slots, getListItemIconUtilityClass, classes);
};

const ListItemIconRoot = experimentalStyled(
'div',
{},
{
name: 'MuiListItemIcon',
slot: 'Root',
overridesResolver,
},
)(({ theme, styleProps }) => ({
/* Styles applied to the root element. */
minWidth: 56,
color: theme.palette.action.active,
flexShrink: 0,
display: 'inline-flex',
/* Styles applied to the root element when the parent `ListItem` uses `alignItems="flex-start"`. */
alignItemsFlexStart: {
...(styleProps.alignItems === 'flex-start' && {
marginTop: 8,
},
});
}),
}));

/**
* A simple wrapper to apply `List` styles to an `Icon` or `SvgIcon`.
*/
const ListItemIcon = React.forwardRef(function ListItemIcon(props, ref) {
const { classes, className, ...other } = props;
const ListItemIcon = React.forwardRef(function ListItemIcon(inProps, ref) {
const props = useThemeProps({
props: inProps,
name: 'MuiListItemIcon',
});

const { className, ...other } = props;
const context = React.useContext(ListContext);
const styleProps = { ...props, alignItems: context.alignItems };
const classes = useUtilityClasses(styleProps);

return (
<div
className={clsx(
classes.root,
{
[classes.alignItemsFlexStart]: context.alignItems === 'flex-start',
},
className,
)}
<ListItemIconRoot
className={clsx(classes.root, className)}
styleProps={styleProps}
ref={ref}
{...other}
/>
Expand All @@ -58,6 +88,10 @@ ListItemIcon.propTypes = {
* @ignore
*/
className: PropTypes.string,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.object,
};

export default withStyles(styles, { name: 'MuiListItemIcon' })(ListItemIcon);
export default ListItemIcon;
17 changes: 5 additions & 12 deletions packages/material-ui/src/ListItemIcon/ListItemIcon.test.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
import * as React from 'react';
import { getClasses, createMount, describeConformance } from 'test/utils';
import { createMount, describeConformanceV5 } from 'test/utils';
import ListItemIcon from './ListItemIcon';
import classes from './listItemIconClasses';

describe('<ListItemIcon />', () => {
const mount = createMount();
let classes;

before(() => {
classes = getClasses(
<ListItemIcon>
<span />
</ListItemIcon>,
);
});

describeConformance(
describeConformanceV5(
<ListItemIcon>
<div />
</ListItemIcon>,
() => ({
classes,
inheritComponent: 'div',
mount,
muiName: 'MuiListItemIcon',
refInstanceof: window.HTMLDivElement,
skip: ['componentProp'],
skip: ['componentProp', 'componentsProp', 'themeVariants'],
}),
);
});
2 changes: 2 additions & 0 deletions packages/material-ui/src/ListItemIcon/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { default } from './ListItemIcon';
export * from './ListItemIcon';
export { default as listItemIconClasses } from './listItemIconClasses';
export * from './listItemIconClasses';
2 changes: 2 additions & 0 deletions packages/material-ui/src/ListItemIcon/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default } from './ListItemIcon';
export { default as listItemIconClasses } from './listItemIconClasses';
export * from './listItemIconClasses';
10 changes: 10 additions & 0 deletions packages/material-ui/src/ListItemIcon/listItemIconClasses.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface ListItemIconClasses {
root: string;
alignItemsFlexStart: string;
}

declare const listItemIconClasses: ListItemIconClasses;

export function getListItemIconUtilityClass(slot: string): string;

export default listItemIconClasses;
12 changes: 12 additions & 0 deletions packages/material-ui/src/ListItemIcon/listItemIconClasses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';

export function getListItemIconUtilityClass(slot) {
return generateUtilityClass('MuiListItemIcon', slot);
}

const listItemIconClasses = generateUtilityClasses('MuiListItemIcon', [
'root',
'alignItemsFlexStart',
]);

export default listItemIconClasses;