diff --git a/docs/pages/api-docs/icon-button.md b/docs/pages/api-docs/icon-button.md index ac17db2d44c0ae..0a945cc6941980 100644 --- a/docs/pages/api-docs/icon-button.md +++ b/docs/pages/api-docs/icon-button.md @@ -72,5 +72,4 @@ You can take advantage of this behavior to [target nested components](/guides/ap ## Demos - [Buttons](/components/buttons/) -- [Image List](/components/image-list/) diff --git a/docs/pages/api-docs/image-list-item-bar.md b/docs/pages/api-docs/image-list-item-bar.md index ec585176ead262..82318fe88f4b44 100644 --- a/docs/pages/api-docs/image-list-item-bar.md +++ b/docs/pages/api-docs/image-list-item-bar.md @@ -28,12 +28,12 @@ The `MuiImageListItemBar` name can be used for providing [default props](/custom | Name | Type | Default | Description | |:-----|:-----|:--------|:------------| -| actionIcon | node | | An IconButton element to be used as secondary action target (primary action target is the tile itself). | +| actionIcon | node | | An IconButton element to be used as secondary action target (primary action target is the item itself). | | actionPosition | 'left'
| 'right'
| 'right' | Position of secondary action IconButton. | | classes | object | | Override or extend the styles applied to the component. See [CSS API](#css) below for more details. | +| position | 'below'
| 'bottom'
| 'top'
| 'bottom' | Position of the title bar. | | subtitle | node | | String or element serving as subtitle (support text). | -| title | node | | Title to be displayed on tile. | -| titlePosition | 'bottom'
| 'top'
| 'bottom' | Position of the title bar. | +| title | node | | Title to be displayed. | The `ref` is forwarded to the root element. @@ -44,10 +44,11 @@ Any other props supplied will be provided to the root element (native element). | Rule name | Global class | Description | |:-----|:-------------|:------------| | root | .MuiImageListItemBar-root | Styles applied to the root element. -| titlePositionBottom | .MuiImageListItemBar-titlePositionBottom | Styles applied to the root element if `titlePosition="bottom"`. -| titlePositionTop | .MuiImageListItemBar-titlePositionTop | Styles applied to the root element if `titlePosition="top"`. -| rootSubtitle | .MuiImageListItemBar-rootSubtitle | Styles applied to the root element if a `subtitle` is provided. +| positionBottom | .MuiImageListItemBar-positionBottom | Styles applied to the root element if `position="bottom"`. +| positionTop | .MuiImageListItemBar-positionTop | Styles applied to the root element if `position="top"`. +| positionBelow | .MuiImageListItemBar-positionBelow | Styles applied to the root element if `position="below"`. | titleWrap | .MuiImageListItemBar-titleWrap | Styles applied to the title and subtitle container element. +| titleWrapBelow | .MuiImageListItemBar-titleWrapBelow | Styles applied to the title and subtitle container element if `position="below"`. | titleWrapActionPosLeft | .MuiImageListItemBar-titleWrapActionPosLeft | Styles applied to the container element if `actionPosition="left"`. | titleWrapActionPosRight | .MuiImageListItemBar-titleWrapActionPosRight | Styles applied to the container element if `actionPosition="right"`. | title | .MuiImageListItemBar-title | Styles applied to the title container element. diff --git a/docs/pages/api-docs/image-list-item.md b/docs/pages/api-docs/image-list-item.md index 86f7d8a50ab646..58455e4a657b78 100644 --- a/docs/pages/api-docs/image-list-item.md +++ b/docs/pages/api-docs/image-list-item.md @@ -28,11 +28,11 @@ The `MuiImageListItem` name can be used for providing [default props](/customiza | Name | Type | Default | Description | |:-----|:-----|:--------|:------------| -| children | node | | Theoretically you can pass any node as children, but the main use case is to pass an img, in which case ImageListItem takes care of making the image "cover" available space (similar to `background-size: cover` or to `object-fit: cover`). | +| children | node | | While you can pass any node as children, the main use case is for an img. | | classes | object | | Override or extend the styles applied to the component. See [CSS API](#css) below for more details. | -| cols | number | 1 | Width of the tile in number of grid cells. | +| cols | number | 1 | Width of the item in number of grid columns. | | component | elementType | 'li' | The component used for the root node. Either a string to use a HTML element or a component. | -| rows | number | 1 | Height of the tile in number of grid cells. | +| rows | number | 1 | Height of the item in number of grid rows. | The `ref` is forwarded to the root element. @@ -43,9 +43,9 @@ Any other props supplied will be provided to the root element (native element). | Rule name | Global class | Description | |:-----|:-------------|:------------| | root | .MuiImageListItem-root | Styles applied to the root element. -| tile | .MuiImageListItem-tile | Styles applied to the `div` element that wraps the children. -| imgFullHeight | .MuiImageListItem-imgFullHeight | Styles applied to an `img` element child, if needed to ensure it covers the tile. -| imgFullWidth | .MuiImageListItem-imgFullWidth | Styles applied to an `img` element child, if needed to ensure it covers the tile. +| img | .MuiImageListItem-img | Styles applied to an `img` element to ensure it covers the item. +| standard | .MuiImageListItem-standard | Styles applied to the root element if `variant="standard"`. +| woven | .MuiImageListItem-woven | Styles applied to the root element if `variant="woven"`. You can override the style of the component thanks to one of these customization points: diff --git a/docs/pages/api-docs/image-list.md b/docs/pages/api-docs/image-list.md index a3efa736c73b84..5b13bfbd6b8a74 100644 --- a/docs/pages/api-docs/image-list.md +++ b/docs/pages/api-docs/image-list.md @@ -28,12 +28,13 @@ The `MuiImageList` name can be used for providing [default props](/customization | Name | Type | Default | Description | |:-----|:-----|:--------|:------------| -| cellHeight | 'auto'
| number
| 180 | Number of px for one cell height. You can set `'auto'` if you want to let the children determine the height. | -| children* | node | | Image Tiles that will be in Image List. | +| children* | node | | Items that will be in the image list. | | classes | object | | Override or extend the styles applied to the component. See [CSS API](#css) below for more details. | | cols | number | 2 | Number of columns. | | component | elementType | 'ul' | The component used for the root node. Either a string to use a HTML element or a component. | -| spacing | number | 4 | Number of px for the spacing between tiles. | +| gap | number | 4 | The gap between items in px. | +| rowHeight | 'auto'
| number
| 'auto' | The height of one row in px. | +| variant | 'masonry'
| 'quilted'
| 'standard'
| 'woven'
| string
| 'standard' | The variant to use. | The `ref` is forwarded to the root element. @@ -44,6 +45,10 @@ Any other props supplied will be provided to the root element (native element). | Rule name | Global class | Description | |:-----|:-------------|:------------| | root | .MuiImageList-root | Styles applied to the root element. +| masonry | .MuiImageList-masonry | Styles applied to the root element if `variant="masonry"`. +| quilted | .MuiImageList-quilted | Styles applied to the root element if `variant="quilted"`. +| standard | .MuiImageList-standard | Styles applied to the root element if `variant="standard"`. +| woven | .MuiImageList-woven | Styles applied to the root element if `variant="woven"`. You can override the style of the component thanks to one of these customization points: diff --git a/docs/pages/api-docs/list-subheader.md b/docs/pages/api-docs/list-subheader.md index 3f1f62ae4e78cf..b07944c23d5c6b 100644 --- a/docs/pages/api-docs/list-subheader.md +++ b/docs/pages/api-docs/list-subheader.md @@ -61,6 +61,5 @@ If that's not sufficient, you can check the [implementation of the component](ht ## Demos -- [Image List](/components/image-list/) - [Lists](/components/lists/) diff --git a/docs/public/static/images/image-list/bike.jpg b/docs/public/static/images/image-list/bike.jpg deleted file mode 100644 index 0646f5154ab25b..00000000000000 Binary files a/docs/public/static/images/image-list/bike.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/breakfast.jpg b/docs/public/static/images/image-list/breakfast.jpg deleted file mode 100644 index 9af6842ff31262..00000000000000 Binary files a/docs/public/static/images/image-list/breakfast.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/burgers.jpg b/docs/public/static/images/image-list/burgers.jpg deleted file mode 100644 index a293a33dacd4f1..00000000000000 Binary files a/docs/public/static/images/image-list/burgers.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/camera.jpg b/docs/public/static/images/image-list/camera.jpg deleted file mode 100644 index f870b196490b00..00000000000000 Binary files a/docs/public/static/images/image-list/camera.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/hats.jpg b/docs/public/static/images/image-list/hats.jpg deleted file mode 100644 index 51e7c3cdd6f6c9..00000000000000 Binary files a/docs/public/static/images/image-list/hats.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/honey.jpg b/docs/public/static/images/image-list/honey.jpg deleted file mode 100644 index 29fb65474a50ed..00000000000000 Binary files a/docs/public/static/images/image-list/honey.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/morning.jpg b/docs/public/static/images/image-list/morning.jpg deleted file mode 100644 index 0e2530e5cd0a0a..00000000000000 Binary files a/docs/public/static/images/image-list/morning.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/mushroom.jpg b/docs/public/static/images/image-list/mushroom.jpg deleted file mode 100644 index 1bcd0495750a96..00000000000000 Binary files a/docs/public/static/images/image-list/mushroom.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/olive.jpg b/docs/public/static/images/image-list/olive.jpg deleted file mode 100644 index 6260d2d53484b0..00000000000000 Binary files a/docs/public/static/images/image-list/olive.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/plant.jpg b/docs/public/static/images/image-list/plant.jpg deleted file mode 100644 index e0550cf2b37976..00000000000000 Binary files a/docs/public/static/images/image-list/plant.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/star.jpg b/docs/public/static/images/image-list/star.jpg deleted file mode 100644 index 411a865ebcaef8..00000000000000 Binary files a/docs/public/static/images/image-list/star.jpg and /dev/null differ diff --git a/docs/public/static/images/image-list/vegetables.jpg b/docs/public/static/images/image-list/vegetables.jpg deleted file mode 100644 index f2c082ba711b5f..00000000000000 Binary files a/docs/public/static/images/image-list/vegetables.jpg and /dev/null differ diff --git a/docs/src/pages/components/image-list/AdvancedImageList.js b/docs/src/pages/components/image-list/AdvancedImageList.js deleted file mode 100644 index 8b9cd852e8e651..00000000000000 --- a/docs/src/pages/components/image-list/AdvancedImageList.js +++ /dev/null @@ -1,84 +0,0 @@ -import * as React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import ImageList from '@material-ui/core/ImageList'; -import ImageListItem from '@material-ui/core/ImageListItem'; -import ImageListItemBar from '@material-ui/core/ImageListItemBar'; -import IconButton from '@material-ui/core/IconButton'; -import StarBorderIcon from '@material-ui/icons/StarBorder'; -import tileData from './tileData'; - -const useStyles = makeStyles((theme) => ({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - width: 500, - height: 450, - // Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS. - transform: 'translateZ(0)', - }, - titleBar: { - background: - 'linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, ' + - 'rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', - }, - icon: { - color: 'white', - }, -})); - -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * featured: true, - * }, - * { - * [etc...] - * }, - * ]; - */ -export default function AdvancedImageList() { - const classes = useStyles(); - - return ( -
- - {tileData.map((tile) => ( - - {tile.title} - - - - } - actionPosition="left" - className={classes.titleBar} - /> - - ))} - -
- ); -} diff --git a/docs/src/pages/components/image-list/AdvancedImageList.tsx b/docs/src/pages/components/image-list/AdvancedImageList.tsx deleted file mode 100644 index 0286d62b90c0e6..00000000000000 --- a/docs/src/pages/components/image-list/AdvancedImageList.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import * as React from 'react'; -import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'; -import ImageList from '@material-ui/core/ImageList'; -import ImageListItem from '@material-ui/core/ImageListItem'; -import ImageListItemBar from '@material-ui/core/ImageListItemBar'; -import IconButton from '@material-ui/core/IconButton'; -import StarBorderIcon from '@material-ui/icons/StarBorder'; -import tileData from './tileData'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - width: 500, - height: 450, - // Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS. - transform: 'translateZ(0)', - }, - titleBar: { - background: - 'linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, ' + - 'rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', - }, - icon: { - color: 'white', - }, - }), -); - -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * featured: true, - * }, - * { - * [etc...] - * }, - * ]; - */ -export default function AdvancedImageList() { - const classes = useStyles(); - - return ( -
- - {tileData.map((tile) => ( - - {tile.title} - - - - } - actionPosition="left" - className={classes.titleBar} - /> - - ))} - -
- ); -} diff --git a/docs/src/pages/components/image-list/BasicImageList.js b/docs/src/pages/components/image-list/BasicImageList.js deleted file mode 100644 index 1ae0783e599ece..00000000000000 --- a/docs/src/pages/components/image-list/BasicImageList.js +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import ImageList from '@material-ui/core/ImageList'; -import ImageListItem from '@material-ui/core/ImageListItem'; -import tileData from './tileData'; - -const useStyles = makeStyles((theme) => ({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - width: 500, - height: 450, - }, -})); - -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * cols: 2, - * }, - * { - * [etc...] - * }, - * ]; - */ -export default function BasicImageList() { - const classes = useStyles(); - - return ( -
- - {tileData.map((tile) => ( - - {tile.title} - - ))} - -
- ); -} diff --git a/docs/src/pages/components/image-list/BasicImageList.tsx b/docs/src/pages/components/image-list/BasicImageList.tsx deleted file mode 100644 index a8b81286732cff..00000000000000 --- a/docs/src/pages/components/image-list/BasicImageList.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import * as React from 'react'; -import { Theme, createStyles, makeStyles } from '@material-ui/core/styles'; -import ImageList from '@material-ui/core/ImageList'; -import ImageListItem from '@material-ui/core/ImageListItem'; -import tileData from './tileData'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - width: 500, - height: 450, - }, - }), -); - -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * cols: 2, - * }, - * { - * [etc...] - * }, - * ]; - */ -export default function BasicImageList() { - const classes = useStyles(); - - return ( -
- - {tileData.map((tile) => ( - - {tile.title} - - ))} - -
- ); -} diff --git a/docs/src/pages/components/image-list/CustomImageList.js b/docs/src/pages/components/image-list/CustomImageList.js new file mode 100644 index 00000000000000..b09418ac5df0be --- /dev/null +++ b/docs/src/pages/components/image-list/CustomImageList.js @@ -0,0 +1,131 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; +import IconButton from '@material-ui/core/IconButton'; +import StarBorderIcon from '@material-ui/icons/StarBorder'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + // Promote the list into its own layer in Chrome. This costs memory, but helps keeping high FPS. + transform: 'translateZ(0)', + }, + titleBar: { + background: + 'linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, ' + + 'rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', + }, + icon: { + color: 'white', + }, +}); + +function srcset(image, width, height, rows = 1, cols = 1) { + return `${image}?w=${width * cols}&h=${height * rows}&fit=crop&auto=format 1x, + ${image}?w=${width * cols}&h=${height * rows}&fit=crop&auto=format&dpr=2 2x`; +} + +export default function CustomImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => { + const cols = item.featured ? 2 : 1; + const rows = item.featured ? 2 : 1; + + return ( + + {item.title} + + + + } + actionPosition="left" + className={classes.titleBar} + /> + + ); + })} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + author: '@bkristastucchio', + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + author: '@rollelflex_graphy726', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + author: '@helloimnik', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + author: '@nolanissac', + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + author: '@hjrc33', + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + author: '@tjdragotta', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + author: '@katie_wasserman', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + author: '@silverdalex', + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + author: '@shelleypauls', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + author: '@peterlaster', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + author: '@southside_customs', + }, +]; diff --git a/docs/src/pages/components/image-list/CustomImageList.tsx b/docs/src/pages/components/image-list/CustomImageList.tsx new file mode 100644 index 00000000000000..4242d083123261 --- /dev/null +++ b/docs/src/pages/components/image-list/CustomImageList.tsx @@ -0,0 +1,137 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; +import IconButton from '@material-ui/core/IconButton'; +import StarBorderIcon from '@material-ui/icons/StarBorder'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + // Promote the list into its own layer in Chrome. This costs memory, but helps keeping high FPS. + transform: 'translateZ(0)', + }, + titleBar: { + background: + 'linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, ' + + 'rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', + }, + icon: { + color: 'white', + }, +}); + +function srcset( + image: string, + width: number, + height: number, + rows = 1, + cols = 1, +) { + return `${image}?w=${width * cols}&h=${height * rows}&fit=crop&auto=format 1x, + ${image}?w=${width * cols}&h=${height * rows}&fit=crop&auto=format&dpr=2 2x`; +} + +export default function CustomImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => { + const cols = item.featured ? 2 : 1; + const rows = item.featured ? 2 : 1; + + return ( + + {item.title} + + + + } + actionPosition="left" + className={classes.titleBar} + /> + + ); + })} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + author: '@bkristastucchio', + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + author: '@rollelflex_graphy726', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + author: '@helloimnik', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + author: '@nolanissac', + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + author: '@hjrc33', + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + author: '@tjdragotta', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + author: '@katie_wasserman', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + author: '@silverdalex', + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + author: '@shelleypauls', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + author: '@peterlaster', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + author: '@southside_customs', + }, +]; diff --git a/docs/src/pages/components/image-list/MasonryImageList.js b/docs/src/pages/components/image-list/MasonryImageList.js new file mode 100644 index 00000000000000..a6c2a74a032a37 --- /dev/null +++ b/docs/src/pages/components/image-list/MasonryImageList.js @@ -0,0 +1,84 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + overflowY: 'scroll', + }, +}); + +export default function MasonryImageList() { + const classes = useStyles(); + + return ( +
+ + {itemData.map((item) => ( + + {item.title} + + ))} + +
+ ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1549388604-817d15aa0110', + title: 'Bed', + }, + { + img: 'https://images.unsplash.com/photo-1525097487452-6278ff080c31', + title: 'Books', + }, + { + img: 'https://images.unsplash.com/photo-1523413651479-597eb2da0ad6', + title: 'Sink', + }, + { + img: 'https://images.unsplash.com/photo-1563298723-dcfebaa392e3', + title: 'Kitchen', + }, + { + img: 'https://images.unsplash.com/photo-1588436706487-9d55d73a39e3', + title: 'Blinds', + }, + { + img: 'https://images.unsplash.com/photo-1574180045827-681f8a1a9622', + title: 'Chairs', + }, + { + img: 'https://images.unsplash.com/photo-1530731141654-5993c3016c77', + title: 'Laptop', + }, + { + img: 'https://images.unsplash.com/photo-1481277542470-605612bd2d61', + title: 'Doors', + }, + { + img: 'https://images.unsplash.com/photo-1517487881594-2787fef5ebf7', + title: 'Coffee', + }, + { + img: 'https://images.unsplash.com/photo-1516455207990-7a41ce80f7ee', + title: 'Storage', + }, + { + img: 'https://images.unsplash.com/photo-1597262975002-c5c3b14bbd62', + title: 'Candle', + }, + { + img: 'https://images.unsplash.com/photo-1519710164239-da123dc03ef4', + title: 'Coffee table', + }, +]; diff --git a/docs/src/pages/components/image-list/MasonryImageList.tsx b/docs/src/pages/components/image-list/MasonryImageList.tsx new file mode 100644 index 00000000000000..a6c2a74a032a37 --- /dev/null +++ b/docs/src/pages/components/image-list/MasonryImageList.tsx @@ -0,0 +1,84 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + overflowY: 'scroll', + }, +}); + +export default function MasonryImageList() { + const classes = useStyles(); + + return ( +
+ + {itemData.map((item) => ( + + {item.title} + + ))} + +
+ ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1549388604-817d15aa0110', + title: 'Bed', + }, + { + img: 'https://images.unsplash.com/photo-1525097487452-6278ff080c31', + title: 'Books', + }, + { + img: 'https://images.unsplash.com/photo-1523413651479-597eb2da0ad6', + title: 'Sink', + }, + { + img: 'https://images.unsplash.com/photo-1563298723-dcfebaa392e3', + title: 'Kitchen', + }, + { + img: 'https://images.unsplash.com/photo-1588436706487-9d55d73a39e3', + title: 'Blinds', + }, + { + img: 'https://images.unsplash.com/photo-1574180045827-681f8a1a9622', + title: 'Chairs', + }, + { + img: 'https://images.unsplash.com/photo-1530731141654-5993c3016c77', + title: 'Laptop', + }, + { + img: 'https://images.unsplash.com/photo-1481277542470-605612bd2d61', + title: 'Doors', + }, + { + img: 'https://images.unsplash.com/photo-1517487881594-2787fef5ebf7', + title: 'Coffee', + }, + { + img: 'https://images.unsplash.com/photo-1516455207990-7a41ce80f7ee', + title: 'Storage', + }, + { + img: 'https://images.unsplash.com/photo-1597262975002-c5c3b14bbd62', + title: 'Candle', + }, + { + img: 'https://images.unsplash.com/photo-1519710164239-da123dc03ef4', + title: 'Coffee table', + }, +]; diff --git a/docs/src/pages/components/image-list/QuiltedImageList.js b/docs/src/pages/components/image-list/QuiltedImageList.js new file mode 100644 index 00000000000000..1ee883140c4bbe --- /dev/null +++ b/docs/src/pages/components/image-list/QuiltedImageList.js @@ -0,0 +1,104 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, +}); + +function srcset(image, size, rows = 1, cols = 1) { + return `${image}?w=${size * cols}&h=${size * rows}&fit=crop&auto=format 1x, + ${image}?w=${size * cols}&h=${size * rows}&fit=crop&auto=format&dpr=2 2x`; +} + +export default function QuiltedImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + cols: 2, + }, +]; diff --git a/docs/src/pages/components/image-list/QuiltedImageList.tsx b/docs/src/pages/components/image-list/QuiltedImageList.tsx new file mode 100644 index 00000000000000..1687bda8dff81b --- /dev/null +++ b/docs/src/pages/components/image-list/QuiltedImageList.tsx @@ -0,0 +1,104 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, +}); + +function srcset(image: string, size: number, rows = 1, cols = 1) { + return `${image}?w=${size * cols}&h=${size * rows}&fit=crop&auto=format 1x, + ${image}?w=${size * cols}&h=${size * rows}&fit=crop&auto=format&dpr=2 2x`; +} + +export default function QuiltedImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + cols: 2, + }, +]; diff --git a/docs/src/pages/components/image-list/SingleLineImageList.js b/docs/src/pages/components/image-list/SingleLineImageList.js deleted file mode 100644 index 33a2a911add9db..00000000000000 --- a/docs/src/pages/components/image-list/SingleLineImageList.js +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import ImageList from '@material-ui/core/ImageList'; -import ImageListItem from '@material-ui/core/ImageListItem'; -import ImageListItemBar from '@material-ui/core/ImageListItemBar'; -import IconButton from '@material-ui/core/IconButton'; -import StarBorderIcon from '@material-ui/icons/StarBorder'; -import tileData from './tileData'; - -const useStyles = makeStyles((theme) => ({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - flexWrap: 'nowrap', - // Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS. - transform: 'translateZ(0)', - }, - title: { - color: theme.palette.primary.light, - }, - titleBar: { - background: - 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', - }, -})); - -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * }, - * { - * [etc...] - * }, - * ]; - */ -export default function SingleLineImageList() { - const classes = useStyles(); - - return ( -
- - {tileData.map((tile) => ( - - {tile.title} - - - - } - /> - - ))} - -
- ); -} diff --git a/docs/src/pages/components/image-list/SingleLineImageList.tsx b/docs/src/pages/components/image-list/SingleLineImageList.tsx deleted file mode 100644 index 9cde5d0c7ba770..00000000000000 --- a/docs/src/pages/components/image-list/SingleLineImageList.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from 'react'; -import { Theme, createStyles, makeStyles } from '@material-ui/core/styles'; -import ImageList from '@material-ui/core/ImageList'; -import ImageListItem from '@material-ui/core/ImageListItem'; -import ImageListItemBar from '@material-ui/core/ImageListItemBar'; -import IconButton from '@material-ui/core/IconButton'; -import StarBorderIcon from '@material-ui/icons/StarBorder'; -import tileData from './tileData'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - flexWrap: 'nowrap', - // Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS. - transform: 'translateZ(0)', - }, - title: { - color: theme.palette.primary.light, - }, - titleBar: { - background: - 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', - }, - }), -); - -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * }, - * { - * [etc...] - * }, - * ]; - */ -export default function SingleLineImageList() { - const classes = useStyles(); - - return ( -
- - {tileData.map((tile) => ( - - {tile.title} - - - - } - /> - - ))} - -
- ); -} diff --git a/docs/src/pages/components/image-list/StandardImageList.js b/docs/src/pages/components/image-list/StandardImageList.js new file mode 100644 index 00000000000000..f2138c2a2ffc7e --- /dev/null +++ b/docs/src/pages/components/image-list/StandardImageList.js @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, +}); + +export default function StandardImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + }, +]; diff --git a/docs/src/pages/components/image-list/StandardImageList.tsx b/docs/src/pages/components/image-list/StandardImageList.tsx new file mode 100644 index 00000000000000..f2138c2a2ffc7e --- /dev/null +++ b/docs/src/pages/components/image-list/StandardImageList.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, +}); + +export default function StandardImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + }, +]; diff --git a/docs/src/pages/components/image-list/TitlebarBelowImageList.js b/docs/src/pages/components/image-list/TitlebarBelowImageList.js new file mode 100644 index 00000000000000..3d2d0249332638 --- /dev/null +++ b/docs/src/pages/components/image-list/TitlebarBelowImageList.js @@ -0,0 +1,102 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, + icon: { + color: 'rgba(255, 255, 255, 0.54)', + }, +}); + +export default function TitlebarBelowImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + by: {item.author}} + position="below" + /> + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + author: '@bkristastucchio', + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + author: '@rollelflex_graphy726', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + author: '@helloimnik', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + author: '@nolanissac', + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + author: '@hjrc33', + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + author: '@tjdragotta', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + author: '@katie_wasserman', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + author: '@silverdalex', + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + author: '@shelleypauls', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + author: '@peterlaster', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + author: '@southside_customs', + }, +]; diff --git a/docs/src/pages/components/image-list/TitlebarBelowImageList.tsx b/docs/src/pages/components/image-list/TitlebarBelowImageList.tsx new file mode 100644 index 00000000000000..3d2d0249332638 --- /dev/null +++ b/docs/src/pages/components/image-list/TitlebarBelowImageList.tsx @@ -0,0 +1,102 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, + icon: { + color: 'rgba(255, 255, 255, 0.54)', + }, +}); + +export default function TitlebarBelowImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + by: {item.author}} + position="below" + /> + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + author: '@bkristastucchio', + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + author: '@rollelflex_graphy726', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + author: '@helloimnik', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + author: '@nolanissac', + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + author: '@hjrc33', + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + author: '@tjdragotta', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + author: '@katie_wasserman', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + author: '@silverdalex', + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + author: '@shelleypauls', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + author: '@peterlaster', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + author: '@southside_customs', + }, +]; diff --git a/docs/src/pages/components/image-list/TitlebarBelowMasonryImageList.js b/docs/src/pages/components/image-list/TitlebarBelowMasonryImageList.js new file mode 100644 index 00000000000000..8b8fdb23b9ac41 --- /dev/null +++ b/docs/src/pages/components/image-list/TitlebarBelowMasonryImageList.js @@ -0,0 +1,94 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + overflowY: 'scroll', + }, +}); + +export default function TitlebarBelowMasonryImageList() { + const classes = useStyles(); + + return ( +
+ + {itemData.map((item) => ( + + {item.title} + + + ))} + +
+ ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1549388604-817d15aa0110', + title: 'Bed', + author: 'swabdesign', + }, + { + img: 'https://images.unsplash.com/photo-1525097487452-6278ff080c31', + title: 'Books', + author: 'Pavel Nekoranec', + }, + { + img: 'https://images.unsplash.com/photo-1523413651479-597eb2da0ad6', + title: 'Sink', + author: 'Charles Deluvio', + }, + { + img: 'https://images.unsplash.com/photo-1563298723-dcfebaa392e3', + title: 'Kitchen', + author: 'Christian Mackie', + }, + { + img: 'https://images.unsplash.com/photo-1588436706487-9d55d73a39e3', + title: 'Blinds', + author: 'Darren Richardson', + }, + { + img: 'https://images.unsplash.com/photo-1574180045827-681f8a1a9622', + title: 'Chairs', + author: 'Taylor Simpson', + }, + { + img: 'https://images.unsplash.com/photo-1530731141654-5993c3016c77', + title: 'Laptop', + author: 'Ben Kolde', + }, + { + img: 'https://images.unsplash.com/photo-1481277542470-605612bd2d61', + title: 'Doors', + author: 'Philipp Berndt', + }, + { + img: 'https://images.unsplash.com/photo-1517487881594-2787fef5ebf7', + title: 'Coffee', + author: 'Jen P.', + }, + { + img: 'https://images.unsplash.com/photo-1516455207990-7a41ce80f7ee', + title: 'Storage', + author: 'Douglas Sheppard', + }, + { + img: 'https://images.unsplash.com/photo-1597262975002-c5c3b14bbd62', + title: 'Candle', + author: 'Fi Bell', + }, + { + img: 'https://images.unsplash.com/photo-1519710164239-da123dc03ef4', + title: 'Coffee table', + author: 'Hutomo Abrianto', + }, +]; diff --git a/docs/src/pages/components/image-list/TitlebarBelowMasonryImageList.tsx b/docs/src/pages/components/image-list/TitlebarBelowMasonryImageList.tsx new file mode 100644 index 00000000000000..8b8fdb23b9ac41 --- /dev/null +++ b/docs/src/pages/components/image-list/TitlebarBelowMasonryImageList.tsx @@ -0,0 +1,94 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + overflowY: 'scroll', + }, +}); + +export default function TitlebarBelowMasonryImageList() { + const classes = useStyles(); + + return ( +
+ + {itemData.map((item) => ( + + {item.title} + + + ))} + +
+ ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1549388604-817d15aa0110', + title: 'Bed', + author: 'swabdesign', + }, + { + img: 'https://images.unsplash.com/photo-1525097487452-6278ff080c31', + title: 'Books', + author: 'Pavel Nekoranec', + }, + { + img: 'https://images.unsplash.com/photo-1523413651479-597eb2da0ad6', + title: 'Sink', + author: 'Charles Deluvio', + }, + { + img: 'https://images.unsplash.com/photo-1563298723-dcfebaa392e3', + title: 'Kitchen', + author: 'Christian Mackie', + }, + { + img: 'https://images.unsplash.com/photo-1588436706487-9d55d73a39e3', + title: 'Blinds', + author: 'Darren Richardson', + }, + { + img: 'https://images.unsplash.com/photo-1574180045827-681f8a1a9622', + title: 'Chairs', + author: 'Taylor Simpson', + }, + { + img: 'https://images.unsplash.com/photo-1530731141654-5993c3016c77', + title: 'Laptop', + author: 'Ben Kolde', + }, + { + img: 'https://images.unsplash.com/photo-1481277542470-605612bd2d61', + title: 'Doors', + author: 'Philipp Berndt', + }, + { + img: 'https://images.unsplash.com/photo-1517487881594-2787fef5ebf7', + title: 'Coffee', + author: 'Jen P.', + }, + { + img: 'https://images.unsplash.com/photo-1516455207990-7a41ce80f7ee', + title: 'Storage', + author: 'Douglas Sheppard', + }, + { + img: 'https://images.unsplash.com/photo-1597262975002-c5c3b14bbd62', + title: 'Candle', + author: 'Fi Bell', + }, + { + img: 'https://images.unsplash.com/photo-1519710164239-da123dc03ef4', + title: 'Coffee table', + author: 'Hutomo Abrianto', + }, +]; diff --git a/docs/src/pages/components/image-list/TitlebarImageList.js b/docs/src/pages/components/image-list/TitlebarImageList.js index 7b9743418e9e8b..976da80500f698 100644 --- a/docs/src/pages/components/image-list/TitlebarImageList.js +++ b/docs/src/pages/components/image-list/TitlebarImageList.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import ImageList from '@material-ui/core/ImageList'; @@ -6,69 +7,120 @@ import ImageListItemBar from '@material-ui/core/ImageListItemBar'; import ListSubheader from '@material-ui/core/ListSubheader'; import IconButton from '@material-ui/core/IconButton'; import InfoIcon from '@material-ui/icons/Info'; -import tileData from './tileData'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles({ root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { width: 500, height: 450, }, icon: { color: 'rgba(255, 255, 255, 0.54)', }, -})); +}); -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * }, - * { - * [etc...] - * }, - * ]; - */ export default function TitlebarImageList() { const classes = useStyles(); return ( -
- - - December + + + December + + {itemData.map((item) => ( + + {item.title} + + + + } + /> - {tileData.map((tile) => ( - - {tile.title} - by: {tile.author}} - actionIcon={ - - - - } - /> - - ))} - -
+ ))} + ); } + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + author: '@bkristastucchio', + rows: 2, + cols: 2, + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + author: '@rollelflex_graphy726', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + author: '@helloimnik', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + author: '@nolanissac', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + author: '@hjrc33', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + rows: 2, + cols: 2, + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + author: '@tjdragotta', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + author: '@katie_wasserman', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + author: '@silverdalex', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + author: '@shelleypauls', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + author: '@peterlaster', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + author: '@southside_customs', + cols: 2, + }, +]; diff --git a/docs/src/pages/components/image-list/TitlebarImageList.tsx b/docs/src/pages/components/image-list/TitlebarImageList.tsx index cfa46dad09c3c5..976da80500f698 100644 --- a/docs/src/pages/components/image-list/TitlebarImageList.tsx +++ b/docs/src/pages/components/image-list/TitlebarImageList.tsx @@ -1,76 +1,126 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ import * as React from 'react'; -import { Theme, createStyles, makeStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/core/styles'; import ImageList from '@material-ui/core/ImageList'; import ImageListItem from '@material-ui/core/ImageListItem'; import ImageListItemBar from '@material-ui/core/ImageListItemBar'; import ListSubheader from '@material-ui/core/ListSubheader'; import IconButton from '@material-ui/core/IconButton'; import InfoIcon from '@material-ui/icons/Info'; -import tileData from './tileData'; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - display: 'flex', - flexWrap: 'wrap', - justifyContent: 'space-around', - overflow: 'hidden', - backgroundColor: theme.palette.background.paper, - }, - gridList: { - width: 500, - height: 450, - }, - icon: { - color: 'rgba(255, 255, 255, 0.54)', - }, - }), -); +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, + icon: { + color: 'rgba(255, 255, 255, 0.54)', + }, +}); -/** - * The example data is structured as follows: - * - * import image from 'path/to/image.jpg'; - * [etc...] - * - * const tileData = [ - * { - * img: image, - * title: 'Image', - * author: 'author', - * }, - * { - * [etc...] - * }, - * ]; - */ export default function TitlebarImageList() { const classes = useStyles(); return ( -
- - - December + + + December + + {itemData.map((item) => ( + + {item.title} + + + + } + /> - {tileData.map((tile) => ( - - {tile.title} - by: {tile.author}} - actionIcon={ - - - - } - /> - - ))} - -
+ ))} + ); } + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e', + title: 'Breakfast', + author: '@bkristastucchio', + rows: 2, + cols: 2, + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1551782450-a2132b4ba21d', + title: 'Burger', + author: '@rollelflex_graphy726', + }, + { + img: 'https://images.unsplash.com/photo-1522770179533-24471fcdba45', + title: 'Camera', + author: '@helloimnik', + }, + { + img: 'https://images.unsplash.com/photo-1444418776041-9c7e33cc5a9c', + title: 'Coffee', + author: '@nolanissac', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1533827432537-70133748f5c8', + title: 'Hats', + author: '@hjrc33', + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1558642452-9d2a7deb7f62', + title: 'Honey', + author: '@arwinneil', + rows: 2, + cols: 2, + featured: true, + }, + { + img: 'https://images.unsplash.com/photo-1516802273409-68526ee1bdd6', + title: 'Basketball', + author: '@tjdragotta', + }, + { + img: 'https://images.unsplash.com/photo-1518756131217-31eb79b20e8f', + title: 'Fern', + author: '@katie_wasserman', + }, + { + img: 'https://images.unsplash.com/photo-1597645587822-e99fa5d45d25', + title: 'Mushrooms', + author: '@silverdalex', + rows: 2, + cols: 2, + }, + { + img: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af', + title: 'Tomato basil', + author: '@shelleypauls', + }, + { + img: 'https://images.unsplash.com/photo-1471357674240-e1a485acb3e1', + title: 'Sea star', + author: '@peterlaster', + }, + { + img: 'https://images.unsplash.com/photo-1589118949245-7d38baf380d6', + title: 'Bike', + author: '@southside_customs', + cols: 2, + }, +]; diff --git a/docs/src/pages/components/image-list/WovenImageList.js b/docs/src/pages/components/image-list/WovenImageList.js new file mode 100644 index 00000000000000..ef2c8aadaa0b3a --- /dev/null +++ b/docs/src/pages/components/image-list/WovenImageList.js @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, +}); + +export default function WovenImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1549388604-817d15aa0110', + title: 'Bed', + }, + { + img: 'https://images.unsplash.com/photo-1563298723-dcfebaa392e3', + title: 'Kitchen', + }, + { + img: 'https://images.unsplash.com/photo-1523413651479-597eb2da0ad6', + title: 'Sink', + }, + { + img: 'https://images.unsplash.com/photo-1525097487452-6278ff080c31', + title: 'Books', + }, + { + img: 'https://images.unsplash.com/photo-1574180045827-681f8a1a9622', + title: 'Chairs', + }, + { + img: 'https://images.unsplash.com/photo-1597262975002-c5c3b14bbd62', + title: 'Candle', + }, + { + img: 'https://images.unsplash.com/photo-1530731141654-5993c3016c77', + title: 'Laptop', + }, + { + img: 'https://images.unsplash.com/photo-1481277542470-605612bd2d61', + title: 'Doors', + }, + { + img: 'https://images.unsplash.com/photo-1517487881594-2787fef5ebf7', + title: 'Coffee', + }, + { + img: 'https://images.unsplash.com/photo-1516455207990-7a41ce80f7ee', + title: 'Storage', + }, + { + img: 'https://images.unsplash.com/photo-1519710164239-da123dc03ef4', + title: 'Coffee table', + }, + { + img: 'https://images.unsplash.com/photo-1588436706487-9d55d73a39e3', + title: 'Blinds', + }, +]; diff --git a/docs/src/pages/components/image-list/WovenImageList.tsx b/docs/src/pages/components/image-list/WovenImageList.tsx new file mode 100644 index 00000000000000..ef2c8aadaa0b3a --- /dev/null +++ b/docs/src/pages/components/image-list/WovenImageList.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ImageList from '@material-ui/core/ImageList'; +import ImageListItem from '@material-ui/core/ImageListItem'; + +const useStyles = makeStyles({ + root: { + width: 500, + height: 450, + }, +}); + +export default function WovenImageList() { + const classes = useStyles(); + + return ( + + {itemData.map((item) => ( + + {item.title} + + ))} + + ); +} + +const itemData = [ + { + img: 'https://images.unsplash.com/photo-1549388604-817d15aa0110', + title: 'Bed', + }, + { + img: 'https://images.unsplash.com/photo-1563298723-dcfebaa392e3', + title: 'Kitchen', + }, + { + img: 'https://images.unsplash.com/photo-1523413651479-597eb2da0ad6', + title: 'Sink', + }, + { + img: 'https://images.unsplash.com/photo-1525097487452-6278ff080c31', + title: 'Books', + }, + { + img: 'https://images.unsplash.com/photo-1574180045827-681f8a1a9622', + title: 'Chairs', + }, + { + img: 'https://images.unsplash.com/photo-1597262975002-c5c3b14bbd62', + title: 'Candle', + }, + { + img: 'https://images.unsplash.com/photo-1530731141654-5993c3016c77', + title: 'Laptop', + }, + { + img: 'https://images.unsplash.com/photo-1481277542470-605612bd2d61', + title: 'Doors', + }, + { + img: 'https://images.unsplash.com/photo-1517487881594-2787fef5ebf7', + title: 'Coffee', + }, + { + img: 'https://images.unsplash.com/photo-1516455207990-7a41ce80f7ee', + title: 'Storage', + }, + { + img: 'https://images.unsplash.com/photo-1519710164239-da123dc03ef4', + title: 'Coffee table', + }, + { + img: 'https://images.unsplash.com/photo-1588436706487-9d55d73a39e3', + title: 'Blinds', + }, +]; diff --git a/docs/src/pages/components/image-list/image-list.md b/docs/src/pages/components/image-list/image-list.md index 0b476ea17b4064..8ebc17a55819c5 100644 --- a/docs/src/pages/components/image-list/image-list.md +++ b/docs/src/pages/components/image-list/image-list.md @@ -1,6 +1,6 @@ --- title: Image list React component -components: ImageList, ImageListItem, ImageListItemBar, ListSubheader, IconButton +components: ImageList, ImageListItem, ImageListItemBar materialDesign: https://material.io/components/image-lists githubLabel: component: ImageList --- @@ -13,31 +13,50 @@ Image lists represent a collection of items in a repeated pattern. They help imp {{"component": "modules/components/ComponentLinkHeader.js"}} -## Basic image list +## Standard image list -A simple example of a scrollable image `ImageList`. +Standard image lists are best for items of equal importance. They have a uniform container size, ratio, and spacing. -{{"demo": "pages/components/image-list/BasicImageList.js", "hideEditButton": true}} +{{"demo": "pages/components/image-list/StandardImageList.js"}} -## Image list with titlebars +## Quilted image list -This example demonstrates the use of the `ImageListItemBar` to add an overlay to each `ImageListItem`. +Quilted image lists emphasize certain items over others in a collection. They create hierarchy using varied container sizes and ratios. + +{{"demo": "pages/components/image-list/QuiltedImageList.js"}} + +## Woven image list + +Woven image lists use alternating container ratios to create a rhythmic layout. A woven image list is best for browsing peer content. + +{{"demo": "pages/components/image-list/WovenImageList.js"}} + +## Masonry image list + +Masonry image lists use dynamically sized container heights that reflect the aspect ratio of each image. This image list is best used for browsing uncropped peer content. + +{{"demo": "pages/components/image-list/MasonryImageList.js"}} + +## Image list with title bars + +This example demonstrates the use of the `ImageListItemBar` to add an overlay to each item. The overlay can accommodate a `title`, `subtitle` and secondary action - in this example an `IconButton`. -{{"demo": "pages/components/image-list/TitlebarImageList.js", "hideEditButton": true}} +{{"demo": "pages/components/image-list/TitlebarImageList.js"}} + +### Title bar below image (standard) + +The title bar can be placed below the image. -## Single line image list +{{"demo": "pages/components/image-list/TitlebarBelowImageList.js"}} -This example demonstrates a horizontal scrollable single-line image list of images. -Horizontally scrolling image lists are discouraged because the scrolling interferes with typical reading patterns, affecting comprehension. -One notable exception is a horizontally-scrolling, single-line image list of images, such as a gallery. +### Title bar below image (masonry) -{{"demo": "pages/components/image-list/SingleLineImageList.js", "hideEditButton": true}} +{{"demo": "pages/components/image-list/TitlebarBelowMasonryImageList.js"}} -## Advanced image list +## Custom image list -This example demonstrates "featured" tiles, using the `rows` and `cols` props to adjust the size of the tile, and the `padding` prop to adjust the spacing. -The tiles have a customized titlebar, positioned at the top and with a custom gradient `titleBackground`. -The secondary action `IconButton` is positioned on the left. +In this example the items have a customized titlebar, positioned at the top and with a custom gradient `titleBackground`. +The secondary action `IconButton` is positioned on the left. The `gap` prop is used to adjust the gap between items. -{{"demo": "pages/components/image-list/AdvancedImageList.js", "hideEditButton": true, "defaultCodeOpen": false}} +{{"demo": "pages/components/image-list/CustomImageList.js", "defaultCodeOpen": false}} diff --git a/docs/src/pages/components/image-list/tileData.d.ts b/docs/src/pages/components/image-list/tileData.d.ts deleted file mode 100644 index c4aecca665999f..00000000000000 --- a/docs/src/pages/components/image-list/tileData.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface TileDataItem { - img: string; - title: string; - author: string; - cols: number; - featured: boolean; -} - -declare const tileData: TileDataItem[]; - -export default tileData; diff --git a/docs/src/pages/components/image-list/tileData.js b/docs/src/pages/components/image-list/tileData.js deleted file mode 100644 index 4bd4f5614428f4..00000000000000 --- a/docs/src/pages/components/image-list/tileData.js +++ /dev/null @@ -1,69 +0,0 @@ -const tileData = [ - { - img: '/static/images/image-list/breakfast.jpg', - title: 'Breakfast', - author: 'jill111', - cols: 2, - featured: true, - }, - { - img: '/static/images/image-list/burgers.jpg', - title: 'Tasty burger', - author: 'director90', - }, - { - img: '/static/images/image-list/camera.jpg', - title: 'Camera', - author: 'Danson67', - }, - { - img: '/static/images/image-list/morning.jpg', - title: 'Morning', - author: 'fancycrave1', - featured: true, - }, - { - img: '/static/images/image-list/hats.jpg', - title: 'Hats', - author: 'Hans', - }, - { - img: '/static/images/image-list/honey.jpg', - title: 'Honey', - author: 'fancycravel', - }, - { - img: '/static/images/image-list/vegetables.jpg', - title: 'Vegetables', - author: 'jill111', - cols: 2, - }, - { - img: '/static/images/image-list/plant.jpg', - title: 'Water plant', - author: 'BkrmadtyaKarki', - }, - { - img: '/static/images/image-list/mushroom.jpg', - title: 'Mushrooms', - author: 'PublicDomainPictures', - }, - { - img: '/static/images/image-list/olive.jpg', - title: 'Olive oil', - author: 'congerdesign', - }, - { - img: '/static/images/image-list/star.jpg', - title: 'Sea star', - cols: 2, - author: '821292', - }, - { - img: '/static/images/image-list/bike.jpg', - title: 'Bike', - author: 'danfador', - }, -]; - -export default tileData; diff --git a/docs/src/pages/guides/migration-v4/migration-v4.md b/docs/src/pages/guides/migration-v4/migration-v4.md index 793653b4de0f67..b2c6b8b63cb191 100644 --- a/docs/src/pages/guides/migration-v4/migration-v4.md +++ b/docs/src/pages/guides/migration-v4/migration-v4.md @@ -315,6 +315,12 @@ const theme = createMuitheme({ ### GridList - Rename the `GridList` components to `ImageList` to align with the current Material Design naming. +- Rename the GridList `spacing` prop to `gap` to align with the CSS attribute. +- Rename the GridList `cellHeight` prop to `rowHieght`. +- Add the `variant` prop to GridList. +- Rename the GridListItemBar `actionPosition` prop to `position`. (Note also the related classname changes.) +- Use CSS object-fit. For IE11 support either use a polyfill such as + https://www.npmjs.com/package/object-fit-images, or continue to use the v4 component. ```diff -import GridList from '@material-ui/core/GridList'; @@ -324,9 +330,9 @@ const theme = createMuitheme({ +import ImageListItem from '@material-ui/core/ImageListItem'; +import ImageListItemBar from '@material-ui/core/ImageListItemBar'; -- +- - -+ ++ + Image title - ; export interface ImageListTypeMap

{ props: P & { /** - * Number of px for one cell height. - * You can set `'auto'` if you want to let the children determine the height. - * @default 180 - */ - cellHeight?: number | 'auto'; - /** - * Image Tiles that will be in Image List. + * Items that will be in the image list. */ children: NonNullable; /** @@ -19,6 +16,14 @@ export interface ImageListTypeMap

{ classes?: { /** Styles applied to the root element. */ root?: string; + /** Styles applied to the root element if `variant="masonry"`. */ + masonry?: string; + /** Styles applied to the root element if `variant="quilted"`. */ + quilted?: string; + /** Styles applied to the root element if `variant="standard"`. */ + standard?: string; + /** Styles applied to the root element if `variant="woven"`. */ + woven?: string; }; /** * Number of columns. @@ -26,10 +31,20 @@ export interface ImageListTypeMap

{ */ cols?: number; /** - * Number of px for the spacing between tiles. + * The gap between items in px. * @default 4 */ - spacing?: number; + gap?: number; + /** + * The height of one row in px. + * @default 'auto' + */ + rowHeight?: number | 'auto'; + /** + * The variant to use. + * @default 'standard' + */ + variant?: OverridableStringUnion; }; defaultComponent: D; } diff --git a/packages/material-ui/src/ImageList/ImageList.js b/packages/material-ui/src/ImageList/ImageList.js index b6f4dc91bd3749..c7ad11cb9f11ce 100644 --- a/packages/material-ui/src/ImageList/ImageList.js +++ b/packages/material-ui/src/ImageList/ImageList.js @@ -1,69 +1,77 @@ 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 ImageListContext from './ImageListContext'; export const styles = { /* Styles applied to the root element. */ root: { - display: 'flex', - flexWrap: 'wrap', + display: 'grid', overflowY: 'auto', listStyle: 'none', padding: 0, WebkitOverflowScrolling: 'touch', // Add iOS momentum scrolling. }, + /* Styles applied to the root element if `variant="masonry"`. */ + masonry: { + display: 'block', + }, + /* Styles applied to the root element if `variant="quilted"`. */ + quilted: {}, + /* Styles applied to the root element if `variant="standard"`. */ + standard: {}, + /* Styles applied to the root element if `variant="woven"`. */ + woven: {}, }; const ImageList = React.forwardRef(function ImageList(props, ref) { const { - cellHeight = 180, children, classes, className, cols = 2, component: Component = 'ul', - spacing = 4, - style, + rowHeight = 'auto', + gap = 4, + style: styleProp, + variant = 'standard', ...other } = props; + const contextValue = React.useMemo(() => ({ rowHeight, gap, variant }), [ + rowHeight, + gap, + variant, + ]); + + React.useEffect(() => { + if (process.env.NODE_ENV !== 'production') { + // Detect Internet Explorer 8+ + if (document !== undefined && 'objectFit' in document.documentElement.style === false) { + console.error( + [ + 'Material-UI: ImageList v5+ no longer natively supports Internet Explorer.', + 'Use v4 of this component instead, or polyfill CSS object-fit.', + ].join('\n'), + ); + } + } + }, []); + + const style = + variant === 'masonry' + ? { columnCount: cols, columnGap: gap, ...styleProp } + : { gridTemplateColumns: `repeat(${cols}, 1fr)`, gap, ...styleProp }; + return ( - {React.Children.map(children, (child) => { - if (!React.isValidElement(child)) { - return null; - } - - if (process.env.NODE_ENV !== 'production') { - if (isFragment(child)) { - console.error( - [ - "Material-UI: The ImageList component doesn't accept a Fragment as a child.", - 'Consider providing an array instead.', - ].join('\n'), - ); - } - } - - const childCols = child.props.cols || 1; - const childRows = child.props.rows || 1; - - return React.cloneElement(child, { - style: { - width: `${(100 / cols) * childCols}%`, - height: cellHeight === 'auto' ? 'auto' : cellHeight * childRows + spacing, - padding: spacing / 2, - ...child.props.style, - }, - }); - })} + {children} ); }); @@ -74,13 +82,7 @@ ImageList.propTypes = { // | To update them edit the d.ts file and run "yarn proptypes" | // ---------------------------------------------------------------------- /** - * Number of px for one cell height. - * You can set `'auto'` if you want to let the children determine the height. - * @default 180 - */ - cellHeight: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]), - /** - * Image Tiles that will be in Image List. + * Items that will be in the image list. */ children: PropTypes /* @typescript-to-proptypes-ignore */.node.isRequired, /** @@ -102,14 +104,27 @@ ImageList.propTypes = { */ component: PropTypes.elementType, /** - * Number of px for the spacing between tiles. + * The gap between items in px. * @default 4 */ - spacing: PropTypes.number, + gap: PropTypes.number, + /** + * The height of one row in px. + * @default 'auto' + */ + rowHeight: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]), /** * @ignore */ style: PropTypes.object, + /** + * The variant to use. + * @default 'standard' + */ + variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['masonry', 'quilted', 'standard', 'woven']), + PropTypes.string, + ]), }; export default withStyles(styles, { name: 'MuiImageList' })(ImageList); diff --git a/packages/material-ui/src/ImageList/ImageList.test.js b/packages/material-ui/src/ImageList/ImageList.test.js index 6a1d405ef647bf..fc52e4c72e533e 100644 --- a/packages/material-ui/src/ImageList/ImageList.test.js +++ b/packages/material-ui/src/ImageList/ImageList.test.js @@ -1,9 +1,9 @@ import * as React from 'react'; import { expect } from 'chai'; -import { createShallow, getClasses, createMount, describeConformance } from 'test/utils'; +import { createClientRender, getClasses, createMount, describeConformance } from 'test/utils'; import ImageList from './ImageList'; -const tilesData = [ +const itemsData = [ { img: 'images/image-list/00-52-29-429_640.jpg', title: 'Breakfast', @@ -19,11 +19,10 @@ const tilesData = [ describe('', () => { let classes; const mount = createMount(); - let shallow; + const render = createClientRender(); before(() => { classes = getClasses(); - shallow = createShallow({ dive: true }); }); describeConformance( @@ -39,128 +38,180 @@ describe('', () => { }), ); - it('should render children and change cellHeight', () => { - const cellHeight = 250; - const wrapper = shallow( - - {tilesData.map((tile) => ( - by: {tile.author}} - > - foo - - ))} - , - ); - - expect(wrapper.find('.grid-tile').length).to.equal(2); - expect(wrapper.children().at(0).props().style.height).to.equal(cellHeight + 4); + const children = itemsData.map((item) => ( + by: {item.author}} + data-testid="test-children" + > + foo + + )); + + it('should render children by default', () => { + const { getAllByTestId } = render({children}); + + expect(getAllByTestId('test-children').length).to.equal(2); }); - it('renders children by default', () => { - const wrapper = shallow( - - {tilesData.map((tile) => ( - by: {tile.author}} - > - foo - - ))} - {false && this is a null child} - , - ); - - expect(wrapper.find('.grid-tile').length).to.equal(2); - }); + describe('classes:', () => { + it('should render with the root and standard classes by default', () => { + const { getByTestId } = render({children}); - it('renders children and change cols', () => { - const wrapper = shallow( - - {tilesData.map((tile) => ( - by: {tile.author}} - > - foo - - ))} - , - ); - - expect(wrapper.find('.grid-tile').length).to.equal(2); - expect(wrapper.children().at(0).props().style.width).to.equal('25%'); - }); + expect(getByTestId('test-root')).to.have.class(classes.root); + expect(getByTestId('test-root')).to.have.class(classes.standard); + }); - it('renders children and change spacing', () => { - const spacing = 10; - const wrapper = shallow( - - {tilesData.map((tile) => ( - by: {tile.author}} - > - foo - - ))} - , - ); - - expect(wrapper.find('.grid-tile').length).to.equal(2); - expect(wrapper.children().at(0).props().style.padding).to.equal(spacing / 2); - }); + it('should render with the masonry class', () => { + const { getByTestId } = render( + + {children} + , + ); - it('should render children and overwrite style', () => { - const style = { backgroundColor: 'red' }; - const wrapper = shallow( - - {tilesData.map((tile) => ( - by: {tile.author}} - > - foo - - ))} - , - ); - - expect(wrapper.find('.grid-tile').length).to.equal(2); - expect(wrapper.props().style.backgroundColor).to.equal(style.backgroundColor); - }); + expect(getByTestId('test-root')).to.have.class(classes.root); + expect(getByTestId('test-root')).to.have.class(classes.masonry); + }); - describe('prop: cellHeight', () => { - it('should accept auto as a property', () => { - const wrapper = shallow( - -
+ it('should render with the quilted class', () => { + const { getByTestId } = render( + + {children} , ); - expect(wrapper.children().at(0).props().style.height).to.equal('auto'); + expect(getByTestId('test-root')).to.have.class(classes.root); + expect(getByTestId('test-root')).to.have.class(classes.woven); + }); + + it('should render with the woven class', () => { + const { getByTestId } = render( + + {children} + , + ); + + expect(getByTestId('test-root')).to.have.class(classes.root); + expect(getByTestId('test-root')).to.have.class(classes.woven); }); }); - it('warns a Fragment is passed as a child', () => { - expect(() => { - mount( - - + describe('style attribute:', () => { + it('should render with default grid-template-columns and gap styles', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + + const { getByTestId } = render({children}); + + expect(getByTestId('test-root').style['grid-template-columns']).to.equal('repeat(2, 1fr)'); + expect(getByTestId('test-root').style.gap).to.equal('4px'); + }); + + it('should overwrite style', () => { + const style = { backgroundColor: 'red' }; + const { getByTestId } = render( + + {children} , ); - }).toErrorDev("Material-UI: The ImageList component doesn't accept a Fragment as a child."); + + expect(getByTestId('test-root').style).to.have.property('backgroundColor', 'red'); + }); + }); + + describe('props:', () => { + describe('prop: component', () => { + it('should render a ul by default', () => { + const { container } = render({children}); + expect(container.firstChild).to.have.property('nodeName', 'UL'); + }); + + it('should render a different component', () => { + const { container } = render({children}); + expect(container.firstChild).to.have.property('nodeName', 'DIV'); + }); + }); + + describe('prop: className', () => { + it('should append the className to the root element', () => { + const { container } = render({children}); + expect(container.firstChild).to.have.class('foo'); + }); + }); + + describe('prop: variant', () => { + it('should render with column-count and column-gap styles', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + + const { getByTestId } = render( + + {children} + , + ); + + expect(getByTestId('test-root').style['column-count']).to.equal('2'); + expect(getByTestId('test-root').style['column-gap']).to.equal('4px'); + }); + }); + + describe('prop: cols', () => { + it('should render with modified grid-template-columns style', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + + const { getByTestId } = render( + + {children} + , + ); + + expect(getByTestId('test-root').style['grid-template-columns']).to.equal('repeat(4, 1fr)'); + }); + + it('should render with modified column-count style', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + + const { getByTestId } = render( + + {children} + , + ); + + expect(getByTestId('test-root').style['column-count']).to.equal('4'); + }); + }); + + describe('prop: gap', () => { + it('should render with modified grid-template-columns style', () => { + const { getByTestId } = render( + + {children} + , + ); + + expect(getByTestId('test-root').style.gap).to.equal('8px'); + }); + + it('should render with modified column-gap style', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + + const { getByTestId } = render( + + {children} + , + ); + + expect(getByTestId('test-root').style['column-gap']).to.equal('8px'); + }); + }); }); }); diff --git a/packages/material-ui/src/ImageList/ImageListContext.js b/packages/material-ui/src/ImageList/ImageListContext.js new file mode 100644 index 00000000000000..b745a7c3041cc4 --- /dev/null +++ b/packages/material-ui/src/ImageList/ImageListContext.js @@ -0,0 +1,13 @@ +import * as React from 'react'; + +/** + * @ignore - internal component. + * @type {React.Context<{} | {expanded: boolean, disabled: boolean, toggle: () => void}>} + */ +const ImageListContext = React.createContext({}); + +if (process.env.NODE_ENV !== 'production') { + ImageListContext.displayName = 'ImageListContext'; +} + +export default ImageListContext; diff --git a/packages/material-ui/src/ImageListItem/ImageListItem.d.ts b/packages/material-ui/src/ImageListItem/ImageListItem.d.ts index 63bef9b7ffac74..c040468c4651f6 100644 --- a/packages/material-ui/src/ImageListItem/ImageListItem.d.ts +++ b/packages/material-ui/src/ImageListItem/ImageListItem.d.ts @@ -4,18 +4,16 @@ import { OverridableComponent, OverrideProps } from '../OverridableComponent'; export interface ImageListItemTypeMap

{ props: P & { /** - * Theoretically you can pass any node as children, but the main use case is to pass an img, - * in which case ImageListItem takes care of making the image "cover" available space - * (similar to `background-size: cover` or to `object-fit: cover`). + * While you can pass any node as children, the main use case is for an img. */ children?: React.ReactNode; /** - * Width of the tile in number of grid cells. + * Width of the item in number of grid columns. * @default 1 */ cols?: number; /** - * Height of the tile in number of grid cells. + * Height of the item in number of grid rows. * @default 1 */ rows?: number; @@ -35,7 +33,7 @@ export interface ImageListItemTypeMap

; -export type ImageListItemClassKey = 'root' | 'tile' | 'imgFullHeight' | 'imgFullWidth'; +export type ImageListItemClassKey = keyof NonNullable; export type ImageListItemProps< D extends React.ElementType = ImageListItemTypeMap['defaultComponent'], diff --git a/packages/material-ui/src/ImageListItem/ImageListItem.js b/packages/material-ui/src/ImageListItem/ImageListItem.js index 9c3569029663dc..8e4f47b6f562d9 100644 --- a/packages/material-ui/src/ImageListItem/ImageListItem.js +++ b/packages/material-ui/src/ImageListItem/ImageListItem.js @@ -1,128 +1,103 @@ import * as React from 'react'; +import { isFragment } from 'react-is'; import PropTypes from 'prop-types'; import clsx from 'clsx'; -import debounce from '../utils/debounce'; import withStyles from '../styles/withStyles'; import isMuiElement from '../utils/isMuiElement'; -import { ownerWindow } from '../utils'; +import ImageListContext from '../ImageList/ImageListContext'; export const styles = { /* Styles applied to the root element. */ root: { - boxSizing: 'border-box', - flexShrink: 0, - }, - /* Styles applied to the `div` element that wraps the children. */ - tile: { + display: 'inline-block', position: 'relative', - display: 'block', // In case it's not rendered with a div. - height: '100%', - overflow: 'hidden', + lineHeight: 0, // 🤷🏻‍♂️Fixes masonry item gap }, - /* Styles applied to an `img` element child, if needed to ensure it covers the tile. */ - imgFullHeight: { + /* Styles applied to an `img` element to ensure it covers the item. */ + img: { + objectFit: 'cover', + width: '100%', height: '100%', - transform: 'translateX(-50%)', - position: 'relative', - left: '50%', }, - /* Styles applied to an `img` element child, if needed to ensure it covers the tile. */ - imgFullWidth: { - width: '100%', - position: 'relative', - transform: 'translateY(-50%)', - top: '50%', + /* 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%', + }, }, -}; - -const fit = (imgEl, classes) => { - if (!imgEl || !imgEl.complete) { - return; - } - - if ( - imgEl.width / imgEl.height > - imgEl.parentElement.offsetWidth / imgEl.parentElement.offsetHeight - ) { - imgEl.classList.remove(...classes.imgFullWidth.split(' ')); - imgEl.classList.add(...classes.imgFullHeight.split(' ')); - } else { - imgEl.classList.remove(...classes.imgFullHeight.split(' ')); - imgEl.classList.add(...classes.imgFullWidth.split(' ')); - } }; const ImageListItem = React.forwardRef(function ImageListItem(props, ref) { - // cols rows default values are for docs only + // TODO: - Use jsdoc @default?: "cols rows default values are for docs only" const { children, classes, className, - // eslint-disable-next-line @typescript-eslint/no-unused-vars cols = 1, component: Component = 'li', - // eslint-disable-next-line @typescript-eslint/no-unused-vars rows = 1, + style, ...other } = props; - const imgRef = React.useRef(null); - - React.useEffect(() => { - const img = imgRef.current; - - if (!img) { - return undefined; - } - - let listener; - - if (img.complete) { - fit(img, classes); - } else { - listener = () => { - fit(img, classes); - }; - img.addEventListener('load', listener); - } - - return () => { - if (listener) { - img.removeEventListener('load', listener); - } - }; - }); + const { rowHeight = 'auto', gap, variant } = React.useContext(ImageListContext); - React.useEffect(() => { - const handleResize = debounce(() => { - fit(imgRef.current, classes); - }); - - const containerWindow = ownerWindow(imgRef.current); - containerWindow.addEventListener('resize', handleResize); - return () => { - handleResize.clear(); - containerWindow.removeEventListener('resize', handleResize); - }; - }, [classes]); + let height = 'auto'; + if (variant === 'woven') { + height = undefined; + } else if (rowHeight !== 'auto') { + height = rowHeight * rows + gap * (rows - 1); + } return ( - -

- {React.Children.map(children, (child) => { - if (!React.isValidElement(child)) { - return null; + + {React.Children.map(children, (child) => { + if (!React.isValidElement(child)) { + return null; + } + + if (process.env.NODE_ENV !== 'production') { + if (isFragment(child)) { + console.error( + [ + "Material-UI: The ImageListItem component doesn't accept a Fragment as a child.", + 'Consider providing an array instead.', + ].join('\n'), + ); } + } - if (child.type === 'img' || isMuiElement(child, ['Image'])) { - return React.cloneElement(child, { - ref: imgRef, - }); - } + if (child.type === 'img' || isMuiElement(child, ['Image'])) { + return React.cloneElement(child, { + className: clsx(classes.img, child.props.className), + }); + } - return child; - })} -
+ return child; + })} ); }); @@ -133,9 +108,7 @@ ImageListItem.propTypes = { // | To update them edit the d.ts file and run "yarn proptypes" | // ---------------------------------------------------------------------- /** - * Theoretically you can pass any node as children, but the main use case is to pass an img, - * in which case ImageListItem takes care of making the image "cover" available space - * (similar to `background-size: cover` or to `object-fit: cover`). + * While you can pass any node as children, the main use case is for an img. */ children: PropTypes.node, /** @@ -147,7 +120,7 @@ ImageListItem.propTypes = { */ className: PropTypes.string, /** - * Width of the tile in number of grid cells. + * Width of the item in number of grid columns. * @default 1 */ cols: PropTypes.number, @@ -157,10 +130,14 @@ ImageListItem.propTypes = { */ component: PropTypes.elementType, /** - * Height of the tile in number of grid cells. + * Height of the item in number of grid rows. * @default 1 */ rows: PropTypes.number, + /** + * @ignore + */ + style: PropTypes.object, }; export default withStyles(styles, { name: 'MuiImageListItem' })(ImageListItem); diff --git a/packages/material-ui/src/ImageListItem/ImageListItem.test.js b/packages/material-ui/src/ImageListItem/ImageListItem.test.js index bb1d3bf90a200b..3bb842e1fc5010 100644 --- a/packages/material-ui/src/ImageListItem/ImageListItem.test.js +++ b/packages/material-ui/src/ImageListItem/ImageListItem.test.js @@ -1,12 +1,13 @@ import * as React from 'react'; import { expect } from 'chai'; -import { spy, useFakeTimers } from 'sinon'; -import { getClasses, createMount, describeConformance } from 'test/utils'; +import { createClientRender, getClasses, createMount, describeConformance } from 'test/utils'; +import ImageList from '../ImageList'; import ImageListItem from './ImageListItem'; describe('', () => { - const mount = createMount(); let classes; + const mount = createMount(); + const render = createClientRender(); before(() => { classes = getClasses(); @@ -20,27 +21,12 @@ describe('', () => { testComponentPropWith: 'div', })); - const tileData = { - img: 'images/image-list/00-52-29-429_640.jpg', + const itemData = { + img: 'images/image-list/breakfast.jpg', title: 'Breakfast', author: 'jill111', }; - describe('prop: children', () => { - it('should render children by default', () => { - const children = foo; - const wrapper = mount({children}); - - expect(wrapper.containsMatchingElement(children)).to.equal(true); - }); - - it('should not change non image child', () => { - const children =
; - const wrapper = mount({children}); - expect(wrapper.containsMatchingElement(children)).to.equal(true); - }); - }); - function mountMockImage(imgEl) { const Image = React.forwardRef((props, ref) => { React.useImperativeHandle(ref, () => imgEl, []); @@ -61,75 +47,66 @@ describe('', () => { it('should handle missing image', () => { mountMockImage(null); }); + }); + + const children = {itemData.title}; - it('should fit the height', () => { - const imgEl = { - complete: true, - width: 16, - height: 9, - parentElement: { offsetWidth: 4, offsetHeight: 3 }, - classList: { remove: spy(), add: spy() }, - removeEventListener: () => {}, - }; - mountMockImage(imgEl); - expect(imgEl.classList.remove.callCount).to.equal(1); - expect(imgEl.classList.remove.args[0][0]).to.equal(classes.imgFullWidth); - expect(imgEl.classList.add.callCount).to.equal(1); - expect(imgEl.classList.add.args[0][0]).to.equal(classes.imgFullHeight); + describe('props:', () => { + describe('prop: children', () => { + it('should render children by default', () => { + const { getByTestId } = render({children}); + + expect(getByTestId('test-children')).not.to.equal(null); + }); }); - it('should fit the width', () => { - const imgEl = { - complete: true, - width: 4, - height: 3, - parentElement: { offsetWidth: 16, offsetHeight: 9 }, - classList: { remove: spy(), add: spy() }, - removeEventListener: () => {}, - }; - mountMockImage(imgEl); - expect(imgEl.classList.remove.callCount).to.equal(1); - expect(imgEl.classList.remove.args[0][0]).to.equal(classes.imgFullHeight); - expect(imgEl.classList.add.callCount).to.equal(1); - expect(imgEl.classList.add.args[0][0]).to.equal(classes.imgFullWidth); + describe('prop: component', () => { + it('should render a different component', () => { + const { container } = render({children}); + expect(container.firstChild).to.have.property('nodeName', 'DIV'); + }); + }); + + describe('prop: variant', () => { + it('should render with the woven class', () => { + const { getByTestId } = render( + + + , + ); + + expect(getByTestId('test-children')).to.have.class(classes.root); + expect(getByTestId('test-children')).to.have.class(classes.woven); + }); }); }); - describe('resize', () => { - let clock; + describe('classes:', () => { + it('should render with the root and standard classes by default', () => { + const { getByTestId } = render( + + + , + ); - beforeEach(() => { - clock = useFakeTimers(); + expect(getByTestId('test-children')).to.have.class(classes.root); + expect(getByTestId('test-children')).to.have.class(classes.standard); }); - afterEach(() => { - clock.restore(); + it('should render img with the img class', () => { + const { getByTestId } = render({children}); + + expect(getByTestId('test-children')).to.have.class(classes.img); }); - it('should handle the resize event', () => { - const imgEl = { - complete: true, - width: 4, - height: 3, - parentElement: { offsetWidth: 16, offsetHeight: 9 }, - classList: { remove: spy(), add: spy() }, - removeEventListener: () => {}, - }; - mountMockImage(imgEl); - expect(imgEl.classList.remove.callCount).to.equal(1); - expect(imgEl.classList.remove.args[0][0]).to.equal(classes.imgFullHeight); - expect(imgEl.classList.add.callCount).to.equal(1); - expect(imgEl.classList.add.args[0][0]).to.equal(classes.imgFullWidth); - - window.dispatchEvent(new window.Event('resize', {})); - expect(imgEl.classList.remove.callCount).to.equal(1); - clock.tick(166); - - expect(imgEl.classList.remove.callCount).to.equal(2); - expect(imgEl.classList.remove.callCount).to.equal(2); - expect(imgEl.classList.remove.args[1][0]).to.equal(classes.imgFullHeight); - expect(imgEl.classList.add.callCount).to.equal(2); - expect(imgEl.classList.add.args[1][0]).to.equal(classes.imgFullWidth); + it('should not render a non-img with the img class', () => { + const { getByTestId } = render( + +
+ , + ); + + expect(getByTestId('test-children')).to.not.have.class(classes.img); }); }); }); diff --git a/packages/material-ui/src/ImageListItemBar/ImageListItemBar.d.ts b/packages/material-ui/src/ImageListItemBar/ImageListItemBar.d.ts index 3f69c864e433ca..7f049a27025b18 100644 --- a/packages/material-ui/src/ImageListItemBar/ImageListItemBar.d.ts +++ b/packages/material-ui/src/ImageListItemBar/ImageListItemBar.d.ts @@ -5,7 +5,7 @@ export interface ImageListItemBarProps extends StandardProps, 'title'> { /** * An IconButton element to be used as secondary action target - * (primary action target is the tile itself). + * (primary action target is the item itself). */ actionIcon?: React.ReactNode; /** @@ -19,14 +19,16 @@ export interface ImageListItemBarProps classes?: { /** Styles applied to the root element. */ root?: string; - /** Styles applied to the root element if `titlePosition="bottom"`. */ - titlePositionBottom?: string; - /** Styles applied to the root element if `titlePosition="top"`. */ - titlePositionTop?: string; - /** Styles applied to the root element if a `subtitle` is provided. */ - rootSubtitle?: string; + /** Styles applied to the root element if `position="bottom"`. */ + positionBottom?: string; + /** Styles applied to the root element if `position="top"`. */ + positionTop?: string; + /** Styles applied to the root element if `position="below"`. */ + positionBelow?: string; /** Styles applied to the title and subtitle container element. */ titleWrap?: string; + /** Styles applied to the title and subtitle container element if `position="below"`. */ + titleWrapBelow?: string; /** Styles applied to the container element if `actionPosition="left"`. */ titleWrapActionPosLeft?: string; /** Styles applied to the container element if `actionPosition="right"`. */ @@ -40,19 +42,19 @@ export interface ImageListItemBarProps /** Styles applied to the actionIcon if `actionPosition="left"`. */ actionIconActionPosLeft?: string; }; + /** + * Position of the title bar. + * @default 'bottom' + */ + position?: 'below' | 'top' | 'bottom'; /** * String or element serving as subtitle (support text). */ subtitle?: React.ReactNode; /** - * Title to be displayed on tile. + * Title to be displayed. */ title?: React.ReactNode; - /** - * Position of the title bar. - * @default 'bottom' - */ - titlePosition?: 'top' | 'bottom'; } export type ImageListItemBarClassKey = keyof NonNullable; diff --git a/packages/material-ui/src/ImageListItemBar/ImageListItemBar.js b/packages/material-ui/src/ImageListItemBar/ImageListItemBar.js index 3a2d81265a0480..60f9165d4f69ce 100644 --- a/packages/material-ui/src/ImageListItemBar/ImageListItemBar.js +++ b/packages/material-ui/src/ImageListItemBar/ImageListItemBar.js @@ -9,39 +9,44 @@ export const styles = (theme) => ({ position: 'absolute', left: 0, right: 0, - height: 48, background: 'rgba(0, 0, 0, 0.5)', display: 'flex', alignItems: 'center', fontFamily: theme.typography.fontFamily, }, - /* Styles applied to the root element if `titlePosition="bottom"`. */ - titlePositionBottom: { + /* Styles applied to the root element if `position="bottom"`. */ + positionBottom: { bottom: 0, }, - /* Styles applied to the root element if `titlePosition="top"`. */ - titlePositionTop: { + /* Styles applied to the root element if `position="top"`. */ + positionTop: { top: 0, }, - /* Styles applied to the root element if a `subtitle` is provided. */ - rootSubtitle: { - height: 68, + /* 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: { flexGrow: 1, - marginLeft: 16, - marginRight: 16, + padding: '12px 16px', color: theme.palette.common.white, overflow: 'hidden', }, + /* 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: { - marginLeft: 0, + paddingLeft: 0, }, /* Styles applied to the container element if `actionPosition="right"`. */ titleWrapActionPosRight: { - marginRight: 0, + paddingRight: 0, }, /* Styles applied to the title container element. */ title: { @@ -75,7 +80,7 @@ const ImageListItemBar = React.forwardRef(function ImageListItemBar(props, ref) className, subtitle, title, - titlePosition = 'bottom', + position = 'bottom', ...other } = props; @@ -86,9 +91,9 @@ const ImageListItemBar = React.forwardRef(function ImageListItemBar(props, ref) className={clsx( classes.root, { - [classes.titlePositionBottom]: titlePosition === 'bottom', - [classes.titlePositionTop]: titlePosition === 'top', - [classes.rootSubtitle]: subtitle, + [classes.positionBelow]: position === 'below', + [classes.positionBottom]: position === 'bottom', + [classes.positionTop]: position === 'top', }, className, )} @@ -97,6 +102,7 @@ const ImageListItemBar = React.forwardRef(function ImageListItemBar(props, ref) >
', () => { let classes; const mount = createMount(); - let shallow; + const render = createClientRender(); before(() => { classes = getClasses(); - shallow = createShallow({ dive: true }); }); describeConformance(, () => ({ @@ -21,17 +20,76 @@ describe('', () => { skip: ['componentProp'], })); - const tileData = { + const itemData = { img: 'images/image-list/00-52-29-429_640.jpg', title: 'Breakfast', author: 'jill111', }; - describe('prop: title', () => { - it('should renders title', () => { - const wrapper = shallow(); + describe('props:', () => { + describe('prop: title', () => { + it('should render a title', () => { + const { container } = render(); - expect(wrapper.children('div').text()).to.equal(tileData.title); + expect(container.querySelector('div')).to.have.text(itemData.title); + }); + }); + + describe('prop: subtitle', () => { + it('should render a subtitle', () => { + const { container } = render(); + + expect(container.querySelector('div')).to.have.text(itemData.author); + }); + }); + + describe('prop: position', () => { + describe('position="top"', () => { + it('should render the positionTop class', () => { + const { container } = render(); + + expect(container.querySelector('div')).to.have.class(classes.root); + expect(container.querySelector('div')).to.have.class(classes.positionTop); + }); + }); + + describe('position="below"', () => { + it('should render the positionBelow class', () => { + const { container } = render(); + + expect(container.querySelector('div')).to.have.class(classes.root); + expect(container.querySelector('div')).to.have.class(classes.positionBelow); + }); + + it('should render a child div with the titleWrapBelow class', () => { + const { container } = render(); + + expect(container.firstChild.querySelector('div')).to.have.class(classes.titleWrap); + expect(container.firstChild.querySelector('div')).to.have.class(classes.titleWrapBelow); + }); + }); + }); + + describe('prop: actionPosition', () => { + it('should render a child div with the titleWrapActionPosLeft class', () => { + const { container } = render( + } actionPosition="left" />, + ); + + expect(container.firstChild.querySelector('div')).to.have.class(classes.titleWrap); + expect(container.firstChild.querySelector('div')).to.have.class( + classes.titleWrapActionPosLeft, + ); + }); + }); + }); + + describe('classes:', () => { + it('should render with the root and positionBottom classes by default', () => { + const { container } = render(); + + expect(container.querySelector('div')).to.have.class(classes.root); + expect(container.querySelector('div')).to.have.class(classes.positionBottom); }); }); }); diff --git a/packages/material-ui/src/Modal/Modal.test.js b/packages/material-ui/src/Modal/Modal.test.js index 85e0fd50d70c50..ef0a2e81911668 100644 --- a/packages/material-ui/src/Modal/Modal.test.js +++ b/packages/material-ui/src/Modal/Modal.test.js @@ -47,7 +47,7 @@ describe('', () => { }), ); - describe('props', () => { + describe('props:', () => { let container; before(() => { diff --git a/packages/material-ui/src/styles/props.d.ts b/packages/material-ui/src/styles/props.d.ts index 839c77f80634e1..ee42fc215fc661 100644 --- a/packages/material-ui/src/styles/props.d.ts +++ b/packages/material-ui/src/styles/props.d.ts @@ -38,12 +38,12 @@ import { FormControlProps } from '../FormControl'; import { FormGroupProps } from '../FormGroup'; import { FormHelperTextProps } from '../FormHelperText'; import { FormLabelProps } from '../FormLabel'; -import { ImageListProps } from '../ImageList'; -import { ImageListItemBarProps } from '../ImageListItemBar'; -import { ImageListItemProps } from '../ImageListItem'; import { GridProps } from '../Grid'; import { IconButtonProps } from '../IconButton'; import { IconProps } from '../Icon'; +import { ImageListProps } from '../ImageList'; +import { ImageListItemBarProps } from '../ImageListItemBar'; +import { ImageListItemProps } from '../ImageListItem'; import { InputAdornmentProps } from '../InputAdornment'; import { InputBaseProps } from '../InputBase'; import { InputLabelProps } from '../InputLabel'; diff --git a/packages/material-ui/test/typescript/components.spec.tsx b/packages/material-ui/test/typescript/components.spec.tsx index d59d941acb28b6..7edf260e2b4ba5 100644 --- a/packages/material-ui/test/typescript/components.spec.tsx +++ b/packages/material-ui/test/typescript/components.spec.tsx @@ -530,7 +530,7 @@ const GridTest = () => ( ); const ImageListTest = () => ( - log(e)}> + log(e)}> log(e)}> alt text