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

[ImageList] Migrate ImageListItem to emotion #24619

Merged
merged 10 commits into from
Jan 27, 2021
5 changes: 3 additions & 2 deletions docs/pages/api-docs/image-list-item.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"classes": { "type": { "name": "object" } },
"cols": { "type": { "name": "number" }, "default": "1" },
"component": { "type": { "name": "elementType" } },
"rows": { "type": { "name": "number" }, "default": "1" }
"rows": { "type": { "name": "number" }, "default": "1" },
"sx": { "type": { "name": "object" } }
},
"name": "ImageListItem",
"styles": {
Expand All @@ -17,6 +18,6 @@
"filename": "/packages/material-ui/src/ImageListItem/ImageListItem.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/image-list/\">Image List</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details.",
"cols": "Width of the item in number of grid columns.",
"component": "The component used for the root node. Either a string to use a HTML element or a component.",
"rows": "Height of the item in number of grid rows."
"rows": "Height of the item in number of grid rows.",
"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
20 changes: 19 additions & 1 deletion packages/material-ui/src/ImageListItem/ImageListItem.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { SxProps } from '@material-ui/system';
import * as React from 'react';
import { Theme } from '..';
import { OverridableComponent, OverrideProps } from '../OverridableComponent';

export interface ImageListItemTypeMap<P = {}, D extends React.ElementType = 'li'> {
Expand All @@ -7,6 +9,19 @@ export interface ImageListItemTypeMap<P = {}, D extends React.ElementType = 'li'
* The content of the component, normally an `<img>`.
*/
children?: React.ReactNode;
/**
* Override or extend the styles applied to the component.
*/
classes?: {
/** Styles applied to the root element. */
root?: string;
/* Styles applied to an `img` element to ensure it covers the item. */
img?: string;
/* Styles applied to the root element if `variant="standard"`. */
standard?: string;
/* Styles applied to the root element if `variant="woven"`. */
woven?: string;
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
}
/**
* Width of the item in number of grid columns.
* @default 1
Expand All @@ -17,9 +32,12 @@ export interface ImageListItemTypeMap<P = {}, D extends React.ElementType = 'li'
* @default 1
*/
rows?: number;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
};
defaultComponent: D;
classKey: ImageListItemClassKey;
}
/**
*
Expand Down
137 changes: 91 additions & 46 deletions packages/material-ui/src/ImageListItem/ImageListItem.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,91 @@
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import { deepmerge } from '@material-ui/utils';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import * as React from 'react';
import { isFragment } from 'react-is';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import withStyles from '../styles/withStyles';
import isMuiElement from '../utils/isMuiElement';
import ImageListContext from '../ImageList/ImageListContext';
import experimentalStyled from '../styles/experimentalStyled';
import useThemeProps from '../styles/useThemeProps';
import isMuiElement from '../utils/isMuiElement';
import imageListItemClasses, { getImageListItemUtilityClass } from './imageListItemClasses';

const overridesResolver = (props, styles) => {
const { styleProps } = props;

return deepmerge(styles.root || {}, {
...styles[styleProps.variant],
[`& .${imageListItemClasses.img}`]: styles.img,
});
};

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

const slots = {
root: ['root', variant],
img: ['img'],
};

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

export const styles = {
/* Styles applied to the root element. */
root: {
const ImageListItemRoot = experimentalStyled(
'li',
{},
{
name: 'MuiImageListItem',
slot: 'Root',
overridesResolver,
},
)(({ styleProps }) => {
return {
display: 'inline-block',
position: 'relative',
lineHeight: 0, // 🤷🏻‍♂️Fixes masonry item gap
/* Styles applied to the root element if `variant="standard"`. */
...(styleProps.variant === 'standard' && {
// For titlebar under list item
display: 'flex',
flexDirection: 'column',
'& $img': {
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
height: 'auto',
flexGrow: 1,
},
}),
/* Styles applied to the root element if `variant="woven"`. */
...(styleProps.variant === 'woven' && {
height: '100%',
alignSelf: 'center',
'&:nth-of-type(even)': {
height: '70%',
},
}),
};
});

experimentalStyled(
'img',
{},
{
name: 'MuiImageListItem',
slot: 'Img',
overridesResolver,
},
/* Styles applied to an `img` element to ensure it covers the item. */
img: {
objectFit: 'cover',
width: '100%',
height: '100%',
},
/* Styles applied to the root element if `variant="standard"`. */
standard: {
// For titlebar under list item
display: 'flex',
flexDirection: 'column',
'& $img': {
height: 'auto',
flexGrow: 1,
},
},
/* Styles applied to the root element if `variant="woven"`. */
woven: {
height: '100%',
alignSelf: 'center',
'&:nth-child(even)': {
height: '70%',
},
},
};
)(() => ({
objectFit: 'cover',
width: '100%',
height: '100%',
}));

const ImageListItem = React.forwardRef(function ImageListItem(inProps, ref) {
const props = useThemeProps({
props: inProps,
name: 'MuiImageListItem',
});

const ImageListItem = React.forwardRef(function ImageListItem(props, ref) {
// TODO: - Use jsdoc @default?: "cols rows default values are for docs only"
const {
children,
classes,
className,
cols = 1,
component: Component = 'li',
rows = 1,
style,
...other
} = props;
const { children, className, cols = 1, component = 'li', rows = 1, style, ...other } = props;

const { rowHeight = 'auto', gap, variant } = React.useContext(ImageListContext);

Expand All @@ -61,8 +96,13 @@ const ImageListItem = React.forwardRef(function ImageListItem(props, ref) {
height = rowHeight * rows + gap * (rows - 1);
}

const styleProps = { ...props, component, variant };
mnajdova marked this conversation as resolved.
Show resolved Hide resolved

const classes = useUtilityClasses(styleProps);

return (
<Component
<ImageListItemRoot
as={component}
className={clsx(classes.root, classes[variant], className)}
ref={ref}
style={{
Expand All @@ -72,6 +112,7 @@ const ImageListItem = React.forwardRef(function ImageListItem(props, ref) {
marginBottom: variant === 'masonry' ? gap : undefined,
...style,
}}
styleProps={styleProps}
{...other}
>
{React.Children.map(children, (child) => {
Expand All @@ -98,7 +139,7 @@ const ImageListItem = React.forwardRef(function ImageListItem(props, ref) {

return child;
})}
</Component>
</ImageListItemRoot>
);
});

Expand Down Expand Up @@ -138,6 +179,10 @@ ImageListItem.propTypes = {
* @ignore
*/
style: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.object,
};

export default withStyles(styles, { name: 'MuiImageListItem' })(ImageListItem);
export default ImageListItem;
15 changes: 7 additions & 8 deletions packages/material-ui/src/ImageListItem/ImageListItem.test.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import * as React from 'react';
import { expect } from 'chai';
import { createClientRender, getClasses, createMount, describeConformance } from 'test/utils';
import * as React from 'react';
import { createClientRender, createMount, describeConformanceV5 } from 'test/utils';
import ImageList from '../ImageList';
import ImageListItem from './ImageListItem';
import classes from './imageListItemClasses';

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

before(() => {
classes = getClasses(<ImageListItem />);
});

describeConformance(<ImageListItem />, () => ({
describeConformanceV5(<ImageListItem />, () => ({
classes,
inheritComponent: 'li',
mount,
refInstanceof: window.HTMLLIElement,
testComponentPropWith: 'div',
muiName: 'MuiImageListItem',
testVariantProps: { variant: 'standard' },
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
skip: ['componentProp', 'componentsProp'],
}));

const itemData = {
Expand Down
12 changes: 12 additions & 0 deletions packages/material-ui/src/ImageListItem/imageListItemClasses.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface ImageListItemClasses {
root: string;
img: string;
standard: string;
woven: string;
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
}

declare const imageListItemClasses: ImageListItemClasses;

export function getImageListItemUtilityClass(slot: string): string;

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

export function getImageListItemUtilityClass(slot) {
return generateUtilityClass('MuiImageListItem', slot);
}

const imageListItemClasses = generateUtilityClasses('MuiImageListItem', [
'root',
'img',
'standard',
'woven',
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
]);

export default imageListItemClasses;
4 changes: 3 additions & 1 deletion packages/material-ui/src/ImageListItem/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { default } from './ImageListItem';
export * from './ImageListItem';
export { default } from './ImageListItem';
export * from './imageListItemClasses';
export { default as imageListItemClasses } from './imageListItemClasses';
2 changes: 2 additions & 0 deletions packages/material-ui/src/ImageListItem/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default } from './ImageListItem';
export * from './imageListItemClasses';
export { default as imageListItemClasses } from './imageListItemClasses';