Skip to content

Instantly share code, notes, and snippets.

@h-jennings
Created November 30, 2022 00:08
Show Gist options
  • Save h-jennings/ce168e21ee2b2a30f9b24571c255005d to your computer and use it in GitHub Desktop.
Save h-jennings/ce168e21ee2b2a30f9b24571c255005d to your computer and use it in GitHub Desktop.
AutoGrid
import { createVar, style } from '@vanilla-extract/css';
import { calc } from '@vanilla-extract/css-utils';
export const gridColumnCount = createVar();
export const gridItemMinWidth = createVar();
export const gridLayoutGapX = createVar();
export const gridLayoutGapY = createVar();
export const gapCount = createVar();
export const totalGapWidth = createVar();
export const gridItemMaxWidth = createVar();
export const root = style({
vars: {
[gridColumnCount]: String(1),
[gridItemMinWidth]: '100%',
[gridLayoutGapX]: '0',
[gridLayoutGapY]: '0',
[gapCount]: calc(gridColumnCount).subtract(1).toString(),
[totalGapWidth]: calc(gapCount).multiply(gridLayoutGapX).toString(),
[gridItemMaxWidth]: calc('100%')
.subtract(totalGapWidth)
.divide(gridColumnCount)
.toString(),
},
display: 'grid',
gridTemplateColumns: `repeat(auto-fill, minmax(max(${gridItemMinWidth}, ${gridItemMaxWidth}), 1fr))`,
columnGap: gridLayoutGapX,
rowGap: gridLayoutGapY,
});
import { tokenVars } from '@styles/tokens.css';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import * as React from 'react';
import useMeasure from 'react-use-measure';
import {
gridColumnCount,
gridItemMinWidth,
gridLayoutGapX,
gridLayoutGapY,
root,
} from './AutoGrid.css';
type AutoGridProps = React.ComponentPropsWithoutRef<'div'> & {
count: number;
itemMinWidth: number;
gapX?: string;
gapY?: string;
};
export const AutoGrid = React.forwardRef<HTMLDivElement, AutoGridProps>(
(
{
count,
itemMinWidth,
gapX,
gapY = tokenVars.spaces[0],
className,
style,
children,
...rest
},
forwardedRef,
) => {
const noGapX = gapX == undefined;
const noGapXStyles = {
gridTemplateColumns: `repeat(auto-fill, minmax(max(${gridItemMinWidth}, calc(100% / ${count})), 1fr))`,
};
// Measuring if actual width of container is below the min width.
// if so, then we want to set gtc to 1fr
const [ref, { width }] = useMeasure({ debounce: 250 });
return (
<div ref={ref}>
<div
{...rest}
style={{
...style,
...assignInlineVars({
[gridColumnCount]: String(count),
[gridItemMinWidth]: `${itemMinWidth}px`,
[gridLayoutGapX]: gapX ?? '0',
[gridLayoutGapY]: gapY,
}),
...(noGapX ? noGapXStyles : {}),
...(width <= itemMinWidth ? { gridTemplateColumns: '1fr' } : {}),
}}
className={clsx(className, root)}
ref={forwardedRef}
>
{children}
</div>
</div>
);
},
);
AutoGrid.displayName = 'AutoGrid';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment