Skip to content

Commit

Permalink
Create a Grid component
Browse files Browse the repository at this point in the history
  • Loading branch information
jessepinho committed Jul 11, 2024
1 parent 08f2edd commit 69be946
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 0 deletions.
71 changes: 71 additions & 0 deletions packages/ui/src/Grid/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Grid } from '.';
import styled from 'styled-components';
import { Technical } from '../Typography';

const meta: Meta<typeof Grid> = {
component: Grid,
title: 'Grid',
tags: ['autodocs'],
};
export default meta;

type Story = StoryObj<typeof Grid>;

const Wrapper = styled.div`
color: white;
`;

const Item = styled.div`
background-color: ${props => props.theme.palette.neutral['700']};
display: flex;
align-items: center;
justify-content: center;
padding: ${props => props.theme.spacing(2)};
`;

export const Demo: Story = {
render: function Render() {
return (
<Wrapper>
<Grid container>
<Grid mobile={12}>
<Item>
<Technical>mobile=12</Technical>
</Item>
</Grid>

{Array(2)
.fill(null)
.map((_, index) => (
<Grid mobile={12} tablet={6} key={index}>
<Item>
<Technical>mobile=12 tablet=6</Technical>
</Item>
</Grid>
))}

{Array(4)
.fill(null)
.map((_, index) => (
<Grid mobile={6} tablet={6} desktop={3} key={index}>
<Item>
<Technical>mobile=6 tablet=6 desktop=3</Technical>
</Item>
</Grid>
))}

{Array(48)
.fill(null)
.map((_, index) => (
<Grid key={index} lg={1}>
<Item>
<Technical>lg=1</Technical>
</Item>
</Grid>
))}
</Grid>
</Wrapper>
);
},
};
84 changes: 84 additions & 0 deletions packages/ui/src/Grid/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { PropsWithChildren } from 'react';
import styled from 'styled-components';

interface GridContainerProps {
/** Whether this is a grid container, vs. an item. */
container: true;
}

interface GridItemProps {
/** Whether this is a grid container, vs. an item. */
container?: false;
/**
* The number of columns this grid item should span on mobile.
*
* The mobile grid layout can only be split in half, so you can only set a
* grid item to 6 or 12 columns on mobile.
*/
mobile?: 6 | 12;
/**
* The number of columns this grid item should span on tablet.
*
* The tablet grid layout can only be split into six columns.
*/
tablet?: 2 | 4 | 6 | 8 | 10 | 12;
/** The number of columns this grid item should span on desktop. */
desktop?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
/** The number of columns this grid item should span on large screens. */
lg?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
/** The number of columns this grid item should span on XL screens. */
xl?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
}

export type GridProps = PropsWithChildren<GridContainerProps | GridItemProps>;

const Container = styled.div<Omit<GridContainerProps, 'container'>>`
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: ${props => props.theme.spacing(4)};
`;

const Item = styled.div<GridItemProps>`
@media (min-width: ${props => props.theme.breakpoints.mobile}px) {
grid-column: span ${props => props.mobile || 12};
}
${props =>
props.tablet
? `
@media (min-width: ${props.theme.breakpoints.tablet}px) {
grid-column: span ${props.tablet};
}
`
: ''}
${props =>
props.desktop
? `
@media (min-width: ${props.theme.breakpoints.desktop}px) {
grid-column: span ${props.desktop};
}
`
: ''}
${props =>
props.lg
? `
@media (min-width: ${props.theme.breakpoints.lg}px) {
grid-column: span ${props.lg};
}
`
: ''}
${props =>
props.xl
? `
@media (min-width: ${props.theme.breakpoints.xl}px) {
grid-column: span ${props.xl};
}
`
: ''}
`;

export const Grid = ({ container, ...props }: GridProps) =>
container ? <Container {...props} /> : <Item {...props} />;

0 comments on commit 69be946

Please sign in to comment.