oxen-website/components/cards/CardGrid.tsx

58 lines
1.7 KiB
TypeScript

import classNames from 'classnames';
import _ from 'lodash';
import React, { useContext } from 'react';
import { useMeasure } from 'react-use';
import { v4 as uuid } from 'uuid';
import { ScreenContext } from '../../contexts/screen';
import { Contained } from '../Contained';
import { HorizontalScrollable } from '../HorizontalScrollable';
interface Props {
rows?: number;
children: JSX.Element[];
}
export function CardGrid({ rows, children }: Props) {
const { isDesktop, isHuge } = useContext(ScreenContext);
const [ref, { width }] = useMeasure();
const widthOfCardPx = 200;
const grouping = Math.max(1, Math.min(4, Math.floor(width / widthOfCardPx)));
const numPaddingCards =
Math.ceil(children.length / grouping) * grouping - children.length;
const spacing = isHuge ? 3 : isDesktop ? 6 : 4;
const spacingY = `space-y-${spacing}`;
const spacingX = `space-x-${spacing}`;
const items =
rows && rows > 0 ? children.slice(0, grouping * rows) : children;
// Add cards to ensure we fill up each row. Hidden where the row is incomplete
// to keep even widths
const cards = [
...items,
...Array.from(Array(numPaddingCards).keys()).map(i => <div key={i}></div>),
];
return (
<>
{
<Contained>
<div ref={ref} className={classNames('flex flex-col', spacingY)}>
{_.chunk(cards, grouping).map(group => (
<div key={uuid()} className={classNames('flex w-full', spacingX)}>
{group.map(item => (
<div key={uuid()} className="flex-1">
{item}
</div>
))}
</div>
))}
</div>
</Contained>
}
</>
);
}