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 ImageListItemBar to emotion #24632

Merged
merged 5 commits into from
Jan 27, 2021
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
3 changes: 2 additions & 1 deletion docs/pages/api-docs/image-list-item-bar.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"default": "'bottom'"
},
"subtitle": { "type": { "name": "node" } },
"sx": { "type": { "name": "object" } },
"title": { "type": { "name": "node" } }
},
"name": "ImageListItemBar",
Expand All @@ -40,6 +41,6 @@
"filename": "/packages/material-ui/src/ImageListItemBar/ImageListItemBar.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 @@ -6,6 +6,7 @@
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details.",
"position": "Position of the title bar.",
"subtitle": "String or element serving as subtitle (support text).",
"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.",
"title": "Title to be displayed."
},
"classDescriptions": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SxProps } from '@material-ui/system';
import * as React from 'react';
import { InternalStandardProps as StandardProps } from '..';
import { InternalStandardProps as StandardProps, Theme } from '..';

export interface ImageListItemBarProps
extends StandardProps<React.HTMLAttributes<HTMLDivElement>, 'title'> {
Expand Down Expand Up @@ -51,6 +52,10 @@ export interface ImageListItemBarProps
* String or element serving as subtitle (support text).
*/
subtitle?: React.ReactNode;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
/**
* Title to be displayed.
*/
Expand Down
244 changes: 168 additions & 76 deletions packages/material-ui/src/ImageListItemBar/ImageListItemBar.js
Original file line number Diff line number Diff line change
@@ -1,125 +1,213 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import { deepmerge } from '@material-ui/utils';
import clsx from 'clsx';
import withStyles from '../styles/withStyles';
import PropTypes from 'prop-types';
import * as React from 'react';
import experimentalStyled from '../styles/experimentalStyled';
import useThemeProps from '../styles/useThemeProps';
import capitalize from '../utils/capitalize';
import imageListItemBarClasses, {
getImageListItemBarUtilityClass,
} from './imageListItemBarClasses';

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

return deepmerge(styles.root || {}, {
...styles[`position${capitalize(styleProps.position)}`],
[`& .${imageListItemBarClasses.titleWrap}`]: {
...styles.titleWrap,
...styles[`titleWrap${capitalize(styleProps.position)}`],
...(styleProps.actionIcon &&
styles[`titleWrapActionPos${capitalize(styleProps.actionPosition)}`]),
},
[`& .${imageListItemBarClasses.title}`]: styles.title,
[`& .${imageListItemBarClasses.subtitle}`]: styles.subtitle,
[`& .${imageListItemBarClasses.actionIcon}`]: {
...styles.actionIcon,
...styles[`actionIconActionPos${capitalize(styleProps.actionPosition)}`],
},
});
};

const useUtilityClasses = (styleProps) => {
const { classes, position, actionIcon, actionPosition } = styleProps;

export const styles = (theme) => ({
/* Styles applied to the root element. */
root: {
const slots = {
root: ['root', `position${capitalize(position)}`],
titleWrap: [
'titleWrap',
`titleWrap${capitalize(position)}`,
actionIcon && `titleWrapActionPos${capitalize(actionPosition)}`,
],
title: ['title'],
subtitle: ['subtitle'],
actionIcon: ['actionIcon', `actionIconActionPos${capitalize(actionPosition)}`],
};

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

const ImageListItemBarRoot = experimentalStyled(
'div',
{},
{
name: 'MuiImageListItemBar',
slot: 'Root',
overridesResolver,
},
)(({ theme, styleProps }) => {
return {
/* Styles applied to the root element. */
position: 'absolute',
left: 0,
right: 0,
background: 'rgba(0, 0, 0, 0.5)',
display: 'flex',
alignItems: 'center',
fontFamily: theme.typography.fontFamily,
/* Styles applied to the root element if `position="bottom"`. */
...(styleProps.position === 'bottom' && {
bottom: 0,
}),
/* Styles applied to the root element if `position="top"`. */
...(styleProps.position === 'top' && {
top: 0,
}),
/* Styles applied to the root element if `position="below"`. */
...(styleProps.position === 'below' && {
position: 'relative',
background: 'transparent',
alignItems: 'normal',
}),
};
});

const ImageListItemBarTitleWrap = experimentalStyled(
'div',
{},
{
name: 'MuiImageListItemBar',
slot: 'TitleWrap',
},
/* Styles applied to the root element if `position="bottom"`. */
positionBottom: {
bottom: 0,
},
/* Styles applied to the root element if `position="top"`. */
positionTop: {
top: 0,
},
/* Styles applied to the root element if `position="below"`. */
positionBelow: {
position: 'relative',
background: 'transparent',
alignItems: 'normal',
},
/* Styles applied to the title and subtitle container element. */
titleWrap: {
)(({ theme, styleProps }) => {
return {
/* Styles applied to the title and subtitle container element. */
flexGrow: 1,
padding: '12px 16px',
color: theme.palette.common.white,
overflow: 'hidden',
/* Styles applied to the title and subtitle container element if `position="below"`. */
...(styleProps.position === 'below' && {
padding: '6px 0 12px',
color: 'inherit',
}),
/* Styles applied to the container element if `actionPosition="left"`. */
...(styleProps.actionIcon &&
styleProps.actionPosition === 'left' && {
paddingLeft: 0,
}),
/* Styles applied to the container element if `actionPosition="right"`. */
...(styleProps.actionIcon &&
styleProps.actionPosition === 'right' && {
paddingRight: 0,
}),
};
});

const ImageListItemBarTitle = experimentalStyled(
'div',
{},
{
name: 'MuiImageListItemBar',
slot: 'Title',
},
/* Styles applied to the title and subtitle container element if `position="below"`. */
titleWrapBelow: {
padding: '6px 0 12px',
color: 'inherit',
},
/* Styles applied to the container element if `actionPosition="left"`. */
titleWrapActionPosLeft: {
paddingLeft: 0,
},
/* Styles applied to the container element if `actionPosition="right"`. */
titleWrapActionPosRight: {
paddingRight: 0,
},
/* Styles applied to the title container element. */
title: {
)(({ theme }) => {
return {
/* Styles applied to the title container element. */
fontSize: theme.typography.pxToRem(16),
lineHeight: '24px',
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
};
});

const ImageListItemBarSubtitle = experimentalStyled(
'div',
{},
{
name: 'MuiImageListItemBar',
slot: 'Subtitle',
},
/* Styles applied to the subtitle container element. */
subtitle: {
)(({ theme }) => {
return {
/* Styles applied to the subtitle container element. */
fontSize: theme.typography.pxToRem(12),
lineHeight: 1,
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
};
});

const ImageListItemBarActionIcon = experimentalStyled(
'div',
{},
{
name: 'MuiImageListItemBar',
slot: 'ActionIcon',
},
/* Styles applied to the actionIcon if supplied. */
actionIcon: {},
/* Styles applied to the actionIcon if `actionPosition="left"`. */
actionIconActionPosLeft: {
order: -1,
},
)(({ styleProps }) => {
return {
/* Styles applied to the actionIcon if `actionPosition="left"`. */
...(styleProps.actionPosition === 'left' && {
order: -1,
}),
};
});

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

const {
actionIcon,
actionPosition = 'right',
classes,
className,
subtitle,
title,
position = 'bottom',
...other
} = props;

const actionPos = actionIcon && actionPosition;
const styleProps = { ...props, position, actionPosition };

const classes = useUtilityClasses(styleProps);

return (
<div
className={clsx(
classes.root,
{
[classes.positionBelow]: position === 'below',
[classes.positionBottom]: position === 'bottom',
[classes.positionTop]: position === 'top',
},
className,
)}
<ImageListItemBarRoot
styleProps={styleProps}
className={clsx(classes.root, className)}
ref={ref}
{...other}
>
<div
className={clsx(classes.titleWrap, {
[classes.titleWrapBelow]: position === 'below',
[classes.titleWrapActionPosLeft]: actionPos === 'left',
[classes.titleWrapActionPosRight]: actionPos === 'right',
})}
>
<div className={classes.title}>{title}</div>
{subtitle ? <div className={classes.subtitle}>{subtitle}</div> : null}
</div>
<ImageListItemBarTitleWrap styleProps={styleProps} className={classes.titleWrap}>
<ImageListItemBarTitle className={classes.title}>{title}</ImageListItemBarTitle>
{subtitle ? (
<ImageListItemBarSubtitle className={classes.subtitle}>
{subtitle}
</ImageListItemBarSubtitle>
) : null}
</ImageListItemBarTitleWrap>
{actionIcon ? (
<div
className={clsx(classes.actionIcon, {
[classes.actionIconActionPosLeft]: actionPos === 'left',
})}
>
<ImageListItemBarActionIcon styleProps={styleProps} className={classes.actionIcon}>
{actionIcon}
</div>
</ImageListItemBarActionIcon>
) : null}
</div>
</ImageListItemBarRoot>
);
});

Expand Down Expand Up @@ -159,10 +247,14 @@ ImageListItemBar.propTypes = {
* String or element serving as subtitle (support text).
*/
subtitle: PropTypes.node,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.object,
/**
* Title to be displayed.
*/
title: PropTypes.node,
};

export default withStyles(styles, { name: 'MuiImageListItemBar' })(ImageListItemBar);
export default ImageListItemBar;
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
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 ImageListItemBar from './ImageListItemBar';
import classes from './imageListItemBarClasses';

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

before(() => {
classes = getClasses(<ImageListItemBar title="classes" />);
});

describeConformance(<ImageListItemBar title="conform?" />, () => ({
describeConformanceV5(<ImageListItemBar title="conform?" />, () => ({
classes,
inheritComponent: 'div',
mount,
refInstanceof: window.HTMLDivElement,
skip: ['componentProp'],
muiName: 'MuiImageListItemBar',
testDeepOverrides: { slotName: 'titleWrap', slotClassName: classes.titleWrap },
testVariantProps: { position: 'top', actionPosition: 'left' },
skip: ['componentProp', 'componentsProp'],
}));

const itemData = {
Expand Down
Loading