Skip to content

Commit

Permalink
feat(HorizontalMosaic, VerticalMosaic): allow passing gridMode inform…
Browse files Browse the repository at this point in the history
…ation to each item (#1289)

Issue: [Link](https://jira.tid.es/browse/WEB-2092)
  • Loading branch information
marcoskolodny authored Nov 11, 2024
1 parent 007f4f8 commit bb8852c
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 16 deletions.
90 changes: 90 additions & 0 deletions src/__tests__/mosaic-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import * as React from 'react';
import {render, screen} from '@testing-library/react';
import ThemeContextProvider from '../theme-context-provider';
import {makeTheme} from './test-utils';
import {HorizontalMosaic, VerticalMosaic} from '../mosaic';
import {Text2} from '../text';

const ITEMS_COUNT = [1, 2, 3, 4, 5, 6];

const verticalMosaicItemsGridMode = [
// 1 item
['horizontal'],

// 2 items
['square', 'square'],

// 3 items
['vertical', 'square', 'square'],

// 4 items
['vertical', 'square', 'square', 'vertical'],

// 5 items
['vertical', 'square', 'square', 'vertical', 'horizontal'],

// 6 items
['vertical', 'square', 'square', 'vertical', 'square', 'square'],
];

const horizontalMosaicItemsGridMode = [
// 1 item
['horizontal'],

// 2 items
['horizontal', 'horizontal'],

// 3 items
['horizontal', 'square', 'square'],

// 4 items
['square', 'square', 'square', 'square'],

// 5 items
['horizontal', 'square', 'square', 'horizontal', 'horizontal'],

// 6 items
['horizontal', 'square', 'square', 'square', 'square', 'horizontal'],
];

test.each(ITEMS_COUNT)(
'VerticalMosaic - gridMode passed as a function is correct with %s items',
(itemsCount) => {
render(
<ThemeContextProvider theme={makeTheme()}>
<VerticalMosaic
items={Array.from({length: itemsCount}, (_, index) => ({gridMode}) => (
<Text2 regular>{`${index + 1}-${gridMode}`}</Text2>
))}
/>
</ThemeContextProvider>
);

const expectedGridModes = verticalMosaicItemsGridMode[itemsCount - 1];

expectedGridModes.forEach((gridMode, index) => {
expect(screen.getByText(`${index + 1}-${gridMode}`)).toBeInTheDocument();
});
}
);

test.each(ITEMS_COUNT)(
'HorizontalMosaic - gridMode passed as a function is correct with %s items',
(itemsCount) => {
render(
<ThemeContextProvider theme={makeTheme()}>
<HorizontalMosaic
items={Array.from({length: itemsCount}, (_, index) => ({gridMode}) => (
<Text2 regular>{`${index + 1}-${gridMode}`}</Text2>
))}
/>
</ThemeContextProvider>
);

const expectedGridModes = horizontalMosaicItemsGridMode[itemsCount - 1];

expectedGridModes.forEach((gridMode, index) => {
expect(screen.getByText(`${index + 1}-${gridMode}`)).toBeInTheDocument();
});
}
);
44 changes: 28 additions & 16 deletions src/mosaic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ import type {DataAttributes} from './utils/types';

const GRID_GAP = {mobile: 8, desktop: 16} as const;

type MosaicItemGridMode = 'horizontal' | 'square' | 'vertical';

type MosaicItem = React.ReactElement | ((config: {gridMode: MosaicItemGridMode}) => React.ReactElement);

type HorizontalMosaicPageProps = {
items: ReadonlyArray<React.ReactElement>;
items: ReadonlyArray<MosaicItem>;
isEven: boolean;
};

const renderItem = (item: MosaicItem, gridMode: MosaicItemGridMode) => {
return typeof item === 'function' ? item({gridMode}) : item;
};

const HorizontalMosaicPage = ({items, isEven}: HorizontalMosaicPageProps) => {
return (
<div className={items.length === 1 ? styles.singleItemRowContainer : styles.squareContainer}>
<Grid gap={GRID_GAP} rows={2} columns={2} height="100%">
{items.length === 3 ? (
<>
<GridItem columnSpan={isEven ? 2 : undefined}>{items[0]}</GridItem>
<GridItem>{items[1]}</GridItem>
<GridItem columnSpan={isEven ? undefined : 2}>{items[2]}</GridItem>
<GridItem columnSpan={isEven ? 2 : undefined}>
{renderItem(items[0], isEven ? 'horizontal' : 'square')}
</GridItem>
<GridItem>{renderItem(items[1], 'square')}</GridItem>
<GridItem columnSpan={isEven ? undefined : 2}>
{renderItem(items[2], isEven ? 'square' : 'horizontal')}
</GridItem>
</>
) : (
items.map((item, itemIndex) => (
Expand All @@ -29,7 +41,7 @@ const HorizontalMosaicPage = ({items, isEven}: HorizontalMosaicPageProps) => {
rowSpan={items.length === 1 ? 2 : undefined}
key={itemIndex}
>
{item}
{renderItem(item, items.length === 4 ? 'square' : 'horizontal')}
</GridItem>
))
)}
Expand All @@ -39,7 +51,7 @@ const HorizontalMosaicPage = ({items, isEven}: HorizontalMosaicPageProps) => {
};

type HorizontalMosaicProps = {
items: ReadonlyArray<React.ReactElement>;
items: ReadonlyArray<MosaicItem>;
withBullets?: boolean;
free?: boolean;
dataAttributes?: DataAttributes;
Expand All @@ -54,7 +66,7 @@ export const HorizontalMosaic = ({
const itemsCount = items.length;

const pagesCount = itemsCount < 5 ? Math.min(itemsCount, 1) : Math.floor((itemsCount + 1) / 3);
const pages = Array.from({length: pagesCount}, () => [] as Array<React.ReactElement>);
const pages = Array.from({length: pagesCount}, () => [] as Array<MosaicItem>);

items.forEach((item, index) => {
const itemPageIndex = Math.min(pagesCount - 1, Math.floor(index / 3));
Expand All @@ -76,7 +88,7 @@ export const HorizontalMosaic = ({
};

type VerticalMosaicPageProps = {
items: ReadonlyArray<React.ReactElement>;
items: ReadonlyArray<MosaicItem>;
};

const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => {
Expand All @@ -88,7 +100,7 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => {
<Grid gap={GRID_GAP} columns={2} height="100%">
{items.map((item, itemIndex) => (
<GridItem columnSpan={items.length === 2 ? undefined : 2} key={itemIndex}>
{item}
{renderItem(item, items.length === 2 ? 'square' : 'horizontal')}
</GridItem>
))}
</Grid>
Expand All @@ -101,7 +113,7 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => {
<Grid gap={GRID_GAP} columns={2} flow="column" height="100%">
{items.map((item, itemIndex) => (
<GridItem rowSpan={itemIndex === 0 ? 2 : undefined} key={itemIndex}>
{item}
{renderItem(item, itemIndex === 0 ? 'vertical' : 'square')}
</GridItem>
))}
</Grid>
Expand All @@ -113,26 +125,26 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => {
return (
<div className={styles.fourItemsContainer}>
<Grid gap={GRID_GAP} rows={3} columns={2} height="100%">
<GridItem rowSpan={2}>{items[0]}</GridItem>
<GridItem>{items[1]}</GridItem>
<GridItem rowSpan={2}>{items[3]}</GridItem>
<GridItem>{items[2]}</GridItem>
<GridItem rowSpan={2}>{renderItem(items[0], 'vertical')}</GridItem>
<GridItem>{renderItem(items[1], 'square')}</GridItem>
<GridItem rowSpan={2}>{renderItem(items[3], 'vertical')}</GridItem>
<GridItem>{renderItem(items[2], 'square')}</GridItem>
</Grid>
</div>
);
}
};

type VerticalMosaicProps = {
items: ReadonlyArray<React.ReactElement>;
items: ReadonlyArray<MosaicItem>;
dataAttributes?: DataAttributes;
};

export const VerticalMosaic = ({items, dataAttributes}: VerticalMosaicProps): JSX.Element => {
const itemsCount = items.length;

const pagesCount = Math.ceil(itemsCount / 4);
const pages = Array.from({length: pagesCount}, () => [] as Array<React.ReactElement<any>>);
const pages = Array.from({length: pagesCount}, () => [] as Array<MosaicItem>);

items.forEach((item, index) => {
const itemPageIndex = Math.floor(index / 4);
Expand Down

1 comment on commit bb8852c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for mistica-web ready!

✅ Preview
https://mistica-165ykx4zh-flows-projects-65bb050e.vercel.app

Built with commit bb8852c.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.