Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Masonry] Add new component #27439

Merged
merged 59 commits into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
0a0888e
Initial implementation of responsive Masonry component
hbjORbj Jul 25, 2021
caa08c5
Receive columnSpan prop for MasonryItem and use ResizeObserver
hbjORbj Jul 27, 2021
b066279
Provide SSR via height prop and optimise images in demo
hbjORbj Jul 27, 2021
da50621
Correct translation doc and use resize-observer-polyfill package
hbjORbj Jul 28, 2021
23c2318
Handle negative heights and set default value of height to undefined
hbjORbj Jul 28, 2021
0c1b293
Properly use ResizeObserver and remove other event listeners
hbjORbj Jul 28, 2021
8184f92
Refactor codes and improve docs to explain props more clearly
hbjORbj Jul 29, 2021
5fdfb53
Use native ResizeObserver for component and pass tests
hbjORbj Jul 29, 2021
0c04aa1
Clean up resize observer in test and general refactoring
hbjORbj Aug 2, 2021
411bf2d
Improve demos and add more demos
hbjORbj Aug 2, 2021
82169f3
Explain difference from Masonry Image List
hbjORbj Aug 2, 2021
a1ce91e
Set width to demos and make image masonry ignored from regression test
hbjORbj Aug 2, 2021
95e8cbb
Describe limitation of Masonry with different column spanning
hbjORbj Aug 2, 2021
50f6b55
Add demo for broken column spanning masonry and fix border cut-off
hbjORbj Aug 3, 2021
b2fcabd
Edit demo styles and add regression tests
hbjORbj Aug 3, 2021
5c851d3
Fix lazy-loaded images to load perperly
hbjORbj Aug 4, 2021
67e66f6
Make masonry responsive to columnSpan, spacing and height
hbjORbj Aug 4, 2021
4047d88
header convention
oliviertassinari Aug 5, 2021
22295e6
isolate the dimensions element for simplicity
oliviertassinari Aug 5, 2021
d476925
prefer one sentence per line to ease review
oliviertassinari Aug 5, 2021
e1ec597
use relative links
oliviertassinari Aug 5, 2021
519d3d1
use demos as simple as possible
oliviertassinari Aug 5, 2021
6126e39
fix SSR layout shift
oliviertassinari Aug 5, 2021
7b3475e
demo should match filename
oliviertassinari Aug 5, 2021
b96b2e9
Refactor MasonryItem
hbjORbj Aug 6, 2021
05d2346
SSR works without setting height to content of MasonryItem
hbjORbj Aug 6, 2021
66d4d8d
Reload image if load fails
hbjORbj Aug 6, 2021
e1af1ca
Fix overlapping images
hbjORbj Aug 6, 2021
713074f
src is a required img attribute
oliviertassinari Aug 7, 2021
ede8750
Revert the incorrect fix for image overlapping on some browsers
hbjORbj Aug 7, 2021
33f5724
Refactor MasonryItem
hbjORbj Aug 9, 2021
3f36763
No need to handle prop updates in useEffect
hbjORbj Aug 9, 2021
0ec86fe
Remove image load error handler
hbjORbj Aug 9, 2021
b2e2747
Don't support change of height
eps1lon Aug 12, 2021
3617f06
Increase row height to 2px
hbjORbj Aug 12, 2021
375624b
Change to defaultHeight in SSR demo
hbjORbj Aug 12, 2021
be9cd99
Remove height from dependency array
hbjORbj Aug 12, 2021
3a8191f
Fix tests as we changed row height to 2px
hbjORbj Aug 12, 2021
157cd42
Remove polyfill package and use dummy resize observer instad
hbjORbj Aug 19, 2021
9cd1cb4
Change height to defaultHeight in regression test
hbjORbj Aug 19, 2021
872a350
Update packages/material-ui-lab/src/Masonry/Masonry.test.js
mnajdova Aug 19, 2021
7bb24f5
Update packages/material-ui-lab/src/Masonry/Masonry.test.js
mnajdova Aug 19, 2021
2f67414
Update docs/src/pages/components/masonry/masonry.md
mnajdova Aug 19, 2021
39bddd9
Update packages/material-ui-lab/src/MasonryItem/MasonryItem.test.js
mnajdova Aug 19, 2021
15a3236
Update packages/material-ui-lab/src/MasonryItem/MasonryItem.test.js
mnajdova Aug 19, 2021
bc4de1d
Update translations and change styleProps to ownerState
hbjORbj Aug 19, 2021
e8c0ae4
Add a comment explaining mock resize observer
hbjORbj Aug 19, 2021
60e1aa9
Delete regression tests as they are same as demos
hbjORbj Aug 19, 2021
ae41204
Change docs prop name to demoComponents
hbjORbj Aug 19, 2021
c61f7ec
Order components alphabetically in nav bar
hbjORbj Aug 19, 2021
33703f5
Put Masonry above timeline in translations doc
hbjORbj Aug 19, 2021
b1fc9f3
Bring constant variable to the top for some demos
hbjORbj Aug 23, 2021
a4f10c8
Prevent use of negative value for padding
hbjORbj Aug 24, 2021
b273cda
Display warning when masonry goess beyond 2000px
hbjORbj Aug 24, 2021
301638c
Use inline style when not dealing with responsive spacing values
hbjORbj Aug 24, 2021
c163bb2
Improve docs
hbjORbj Aug 24, 2021
b3daef0
Pass all tests
hbjORbj Aug 24, 2021
2339dd0
Improve docs' descriptions of props
hbjORbj Aug 25, 2021
3bfc972
Pass prettier test
hbjORbj Aug 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/pages/api-docs/masonry-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import ApiPage from 'docs/src/modules/components/ApiPage';
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations';
import jsonPageContent from './masonry-item.json';

export default function Page(props) {
const { descriptions, pageContent } = props;
return <ApiPage descriptions={descriptions} pageContent={pageContent} />;
}

Page.getInitialProps = () => {
const req = require.context(
'docs/translations/api-docs/masonry-item',
false,
/masonry-item.*.json$/,
);
const descriptions = mapApiPageTranslations(req);

return {
descriptions,
pageContent: jsonPageContent,
};
};
19 changes: 19 additions & 0 deletions docs/pages/api-docs/masonry-item.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"props": {
"children": { "type": { "name": "element" }, "required": true },
"classes": { "type": { "name": "object" } },
"columnSpan": { "type": { "name": "number" }, "default": "1" },
"component": { "type": { "name": "elementType" } },
"defaultHeight": { "type": { "name": "number" } },
"sx": { "type": { "name": "object" } }
},
"name": "MasonryItem",
"styles": { "classes": ["root"], "globalClasses": {}, "name": "MuiMasonryItem" },
"spread": true,
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/material-ui-lab/src/MasonryItem/MasonryItem.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/masonry/\">Masonry</a></li></ul>",
"styledComponent": true,
"cssComponent": false
}
19 changes: 19 additions & 0 deletions docs/pages/api-docs/masonry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import ApiPage from 'docs/src/modules/components/ApiPage';
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations';
import jsonPageContent from './masonry.json';

export default function Page(props) {
const { descriptions, pageContent } = props;
return <ApiPage descriptions={descriptions} pageContent={pageContent} />;
}

Page.getInitialProps = () => {
const req = require.context('docs/translations/api-docs/masonry', false, /masonry.*.json$/);
const descriptions = mapApiPageTranslations(req);

return {
descriptions,
pageContent: jsonPageContent,
};
};
31 changes: 31 additions & 0 deletions docs/pages/api-docs/masonry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"props": {
"children": { "type": { "name": "node" }, "required": true },
"classes": { "type": { "name": "object" } },
"columns": {
"type": {
"name": "union",
"description": "Array&lt;number<br>&#124;&nbsp;string&gt;<br>&#124;&nbsp;number<br>&#124;&nbsp;object<br>&#124;&nbsp;string"
},
"default": "4"
},
"component": { "type": { "name": "elementType" } },
"spacing": {
"type": {
"name": "union",
"description": "Array&lt;number<br>&#124;&nbsp;string&gt;<br>&#124;&nbsp;number<br>&#124;&nbsp;object<br>&#124;&nbsp;string"
},
"default": "1"
},
"sx": { "type": { "name": "object" } }
},
"name": "Masonry",
"styles": { "classes": ["root"], "globalClasses": {}, "name": "MuiMasonry" },
"spread": true,
"forwardsRefTo": "HTMLDivElement",
"filename": "/packages/material-ui-lab/src/Masonry/Masonry.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/masonry/\">Masonry</a></li></ul>",
"styledComponent": true,
"cssComponent": false
}
11 changes: 11 additions & 0 deletions docs/pages/components/masonry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import {
demos,
docs,
demoComponents,
} from 'docs/src/pages/components/masonry/masonry.md?@material-ui/markdown';

export default function Page() {
return <MarkdownDocs demos={demos} docs={docs} demoComponents={demoComponents} />;
}
1 change: 1 addition & 0 deletions docs/src/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ const pages: readonly MuiPage[] = [
{ pathname: '/components/time-picker' },
],
},
{ pathname: '/components/masonry' },
{ pathname: '/components/timeline' },
{ pathname: '/components/trap-focus' },
{ pathname: '/components/tree-view' },
Expand Down
29 changes: 29 additions & 0 deletions docs/src/pages/components/masonry/BasicMasonry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

const heights = [150, 30, 90, 70, 110, 150, 130, 80, 50, 90, 100, 150, 30, 50, 80];

export default function BasicMasonry() {
return (
<Box sx={{ width: 500, minHeight: 393 }}>
<Masonry columns={4} spacing={1}>
{heights.map((height, index) => (
<MasonryItem key={index}>
<Box
sx={{
textAlign: 'center',
height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}
29 changes: 29 additions & 0 deletions docs/src/pages/components/masonry/BasicMasonry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

const heights = [150, 30, 90, 70, 110, 150, 130, 80, 50, 90, 100, 150, 30, 50, 80];

export default function BasicMasonry() {
return (
<Box sx={{ width: 500, minHeight: 393 }}>
<Masonry columns={4} spacing={1}>
{heights.map((height, index) => (
<MasonryItem key={index}>
<Box
sx={{
textAlign: 'center',
height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}
46 changes: 46 additions & 0 deletions docs/src/pages/components/masonry/DiffColSizeMasonry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

export default function DiffColSizeMasonry() {
return (
<Box sx={{ width: 500, minHeight: 500 }}>
<Masonry columns={4} spacing={1}>
{itemData.map((item, index) => (
<MasonryItem key={index} columnSpan={item.span}>
<Box
sx={{
textAlign: 'center',
height: item.height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}

const itemData = [
{ height: 150 },
{ height: 30 },
{ height: 90, span: 2 },
{ height: 110 },
{ height: 150 },
{ height: 150 },
{ height: 130, span: 2 },
{ height: 80, span: 2 },
{ height: 50 },
{ height: 90 },
{ height: 100, span: 2 },
{ height: 150 },
{ height: 50 },
{ height: 50, span: 2 },
{ height: 50 },
];
46 changes: 46 additions & 0 deletions docs/src/pages/components/masonry/DiffColSizeMasonry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

export default function DiffColSizeMasonry() {
return (
<Box sx={{ width: 500, minHeight: 500 }}>
<Masonry columns={4} spacing={1}>
{itemData.map((item, index) => (
<MasonryItem key={index} columnSpan={item.span}>
<Box
sx={{
textAlign: 'center',
height: item.height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}

const itemData = [
{ height: 150 },
{ height: 30 },
{ height: 90, span: 2 },
{ height: 110 },
{ height: 150 },
{ height: 150 },
{ height: 130, span: 2 },
{ height: 80, span: 2 },
{ height: 50 },
{ height: 90 },
{ height: 100, span: 2 },
{ height: 150 },
{ height: 50 },
{ height: 50, span: 2 },
{ height: 50 },
];
46 changes: 46 additions & 0 deletions docs/src/pages/components/masonry/DiffColSizeMasonryBroken.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

export default function DiffColSizeMasonryBroken() {
return (
<Box sx={{ width: 500, minHeight: 503 }}>
<Masonry columns={4} spacing={1}>
{itemData.map((item, index) => (
<MasonryItem key={index} columnSpan={item.span}>
<Box
sx={{
textAlign: 'center',
height: item.height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}

const itemData = [
{ height: 150 },
{ height: 30 },
{ height: 90, span: 2 },
{ height: 70 },
{ height: 150 },
{ height: 120 },
{ height: 100, span: 2 },
{ height: 80, span: 2 },
{ height: 35 },
{ height: 70 },
{ height: 100, span: 2 },
{ height: 157 },
{ height: 50 },
{ height: 50, span: 2 },
{ height: 50 },
];
46 changes: 46 additions & 0 deletions docs/src/pages/components/masonry/DiffColSizeMasonryBroken.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

export default function DiffColSizeMasonryBroken() {
return (
<Box sx={{ width: 500, minHeight: 503 }}>
<Masonry columns={4} spacing={1}>
{itemData.map((item, index) => (
<MasonryItem key={index} columnSpan={item.span}>
<Box
sx={{
textAlign: 'center',
height: item.height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}

const itemData = [
{ height: 150 },
{ height: 30 },
{ height: 90, span: 2 },
{ height: 70 },
{ height: 150 },
{ height: 120 },
{ height: 100, span: 2 },
{ height: 80, span: 2 },
{ height: 35 },
{ height: 70 },
{ height: 100, span: 2 },
{ height: 157 },
{ height: 50 },
{ height: 50, span: 2 },
{ height: 50 },
];
29 changes: 29 additions & 0 deletions docs/src/pages/components/masonry/FixedColumns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Masonry from '@material-ui/lab/Masonry';
import MasonryItem from '@material-ui/lab/MasonryItem';

const heights = [150, 30, 90, 70, 90, 100, 150, 30, 50, 80];

export default function FixedColumns() {
return (
<Box sx={{ width: 500, minHeight: 253 }}>
<Masonry columns={4} spacing={1}>
{heights.map((height, index) => (
<MasonryItem key={index}>
<Box
sx={{
textAlign: 'center',
height,
border: 1,
bgcolor: 'background.paper',
}}
>
{index + 1}
</Box>
</MasonryItem>
))}
</Masonry>
</Box>
);
}
Loading