diff --git a/docs/pages/api-docs/list-item-icon.json b/docs/pages/api-docs/list-item-icon.json index a0c1d355e79fa6..dac9ee8aba40dd 100644 --- a/docs/pages/api-docs/list-item-icon.json +++ b/docs/pages/api-docs/list-item-icon.json @@ -1,7 +1,8 @@ { "props": { "children": { "type": { "name": "node" } }, - "classes": { "type": { "name": "object" } } + "classes": { "type": { "name": "object" } }, + "sx": { "type": { "name": "object" } } }, "name": "ListItemIcon", "styles": { @@ -14,6 +15,6 @@ "filename": "/packages/material-ui/src/ListItemIcon/ListItemIcon.js", "inheritance": null, "demos": "", - "styledComponent": false, + "styledComponent": true, "cssComponent": false } diff --git a/docs/translations/api-docs/list-item-icon/list-item-icon.json b/docs/translations/api-docs/list-item-icon/list-item-icon.json index 9c1ef7a1b4f281..400c88d2d77e1a 100644 --- a/docs/translations/api-docs/list-item-icon/list-item-icon.json +++ b/docs/translations/api-docs/list-item-icon/list-item-icon.json @@ -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 Icon, SvgIcon, or a @material-ui/icons SVG icon element.", - "classes": "Override or extend the styles applied to the component. See CSS API below for more details." + "classes": "Override or extend the styles applied to the component. See CSS API below for more details.", + "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details." }, "classDescriptions": { "root": { "description": "Styles applied to the root element." }, diff --git a/packages/material-ui/src/ListItemIcon/ListItemIcon.d.ts b/packages/material-ui/src/ListItemIcon/ListItemIcon.d.ts index 80de403db229e2..23602c6a8228c0 100644 --- a/packages/material-ui/src/ListItemIcon/ListItemIcon.d.ts +++ b/packages/material-ui/src/ListItemIcon/ListItemIcon.d.ts @@ -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> { /** @@ -15,6 +16,10 @@ export interface ListItemIconProps extends StandardProps; } export type ListItemIconClassKey = keyof NonNullable; diff --git a/packages/material-ui/src/ListItemIcon/ListItemIcon.js b/packages/material-ui/src/ListItemIcon/ListItemIcon.js index 381da79d92ecd2..8aa3376010b569 100644 --- a/packages/material-ui/src/ListItemIcon/ListItemIcon.js +++ b/packages/material-ui/src/ListItemIcon/ListItemIcon.js @@ -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 ( -
@@ -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; diff --git a/packages/material-ui/src/ListItemIcon/ListItemIcon.test.js b/packages/material-ui/src/ListItemIcon/ListItemIcon.test.js index 1d9fba71d27c4c..c50852b8eb4024 100644 --- a/packages/material-ui/src/ListItemIcon/ListItemIcon.test.js +++ b/packages/material-ui/src/ListItemIcon/ListItemIcon.test.js @@ -1,20 +1,12 @@ 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('', () => { const mount = createMount(); - let classes; - before(() => { - classes = getClasses( - - - , - ); - }); - - describeConformance( + describeConformanceV5(
, @@ -22,8 +14,9 @@ describe('', () => { classes, inheritComponent: 'div', mount, + muiName: 'MuiListItemIcon', refInstanceof: window.HTMLDivElement, - skip: ['componentProp'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], }), ); }); diff --git a/packages/material-ui/src/ListItemIcon/index.d.ts b/packages/material-ui/src/ListItemIcon/index.d.ts index 0adcbd950b46ea..befa5c4b06fce5 100644 --- a/packages/material-ui/src/ListItemIcon/index.d.ts +++ b/packages/material-ui/src/ListItemIcon/index.d.ts @@ -1,2 +1,4 @@ export { default } from './ListItemIcon'; export * from './ListItemIcon'; +export { default as listItemIconClasses } from './listItemIconClasses'; +export * from './listItemIconClasses'; diff --git a/packages/material-ui/src/ListItemIcon/index.js b/packages/material-ui/src/ListItemIcon/index.js index 0bcbf23ba29322..01174ef3d39b49 100644 --- a/packages/material-ui/src/ListItemIcon/index.js +++ b/packages/material-ui/src/ListItemIcon/index.js @@ -1 +1,3 @@ export { default } from './ListItemIcon'; +export { default as listItemIconClasses } from './listItemIconClasses'; +export * from './listItemIconClasses'; diff --git a/packages/material-ui/src/ListItemIcon/listItemIconClasses.d.ts b/packages/material-ui/src/ListItemIcon/listItemIconClasses.d.ts new file mode 100644 index 00000000000000..7e6f52417590f5 --- /dev/null +++ b/packages/material-ui/src/ListItemIcon/listItemIconClasses.d.ts @@ -0,0 +1,10 @@ +export interface ListItemIconClasses { + root: string; + alignItemsFlexStart: string; +} + +declare const listItemIconClasses: ListItemIconClasses; + +export function getListItemIconUtilityClass(slot: string): string; + +export default listItemIconClasses; diff --git a/packages/material-ui/src/ListItemIcon/listItemIconClasses.js b/packages/material-ui/src/ListItemIcon/listItemIconClasses.js new file mode 100644 index 00000000000000..973b8a0403d741 --- /dev/null +++ b/packages/material-ui/src/ListItemIcon/listItemIconClasses.js @@ -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;