Skip to content

Commit

Permalink
Add Grid component to pcln-design-system (#1303)
Browse files Browse the repository at this point in the history
* add Grid component to core pcln-design-system
* Disable color props for Grid
  • Loading branch information
trenaryja committed Jun 2, 2023
1 parent 2601785 commit ba327c4
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "pcln-design-system",
"comment": "Add Grid component",
"type": "minor"
}
],
"packageName": "pcln-design-system"
}
41 changes: 41 additions & 0 deletions packages/core/src/Grid/Grid.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { render } from '@testing-library/react'
import React from 'react'
import { Grid, IGridProps } from './Grid'

describe('Grid', () => {
const testProps: IGridProps = {
gap: '10px',
rowGap: '20px',
columnGap: '30px',
column: '1 / 3',
row: '1 / span 2',
area: 'header',
autoFlow: 'row dense',
autoRows: 'minmax(100px, auto)',
autoColumns: 'repeat(2, 1fr)',
templateRows: 'repeat(2, 1fr)',
templateColumns: 'repeat(3, 1fr)',
templateAreas: '"header header header" "main main sidebar"',
placeItems: 'center',
}

it('applies grid styles correctly', () => {
const { container } = render(<Grid {...testProps} />)
const gridElement = container.firstChild

expect(gridElement).toHaveStyleRule('display: grid')
expect(gridElement).toHaveStyleRule('grid-gap: 10px')
expect(gridElement).toHaveStyleRule('grid-row-gap: 20px')
expect(gridElement).toHaveStyleRule('grid-column-gap: 30px')
expect(gridElement).toHaveStyleRule('grid-column: 1 / 3')
expect(gridElement).toHaveStyleRule('grid-row: 1 / span 2')
expect(gridElement).toHaveStyleRule('grid-area: header')
expect(gridElement).toHaveStyleRule('grid-auto-flow: row dense')
expect(gridElement).toHaveStyleRule('grid-auto-rows: minmax(100px, auto)')
expect(gridElement).toHaveStyleRule('grid-auto-columns: repeat(2, 1fr)')
expect(gridElement).toHaveStyleRule('grid-template-rows: repeat(2, 1fr)')
expect(gridElement).toHaveStyleRule('grid-template-columns: repeat(3, 1fr)')
expect(gridElement).toHaveStyleRule('grid-template-areas: "header header header" "main main sidebar"')
expect(gridElement).toHaveStyleRule('place-items: center')
})
})
177 changes: 177 additions & 0 deletions packages/core/src/Grid/Grid.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { ArgsTable, PRIMARY_STORY, Primary } from '@storybook/addon-docs'
import { Meta, StoryObj } from '@storybook/react'
import {
Hero,
LiveDemo,
RelatedComponent,
RelatedComponentContainer,
Section,
StoryHeading,
TableOfContents,
} from 'pcln-docs-utils'
import React from 'react'
import { Box, Flex, Grid, IGridProps, Text, ThemeProvider } from '..'

type GridStory = StoryObj<IGridProps>

const GridItem = (props: IGridProps) => <Grid p={4} width={1} placeItems='center' {...props} />

export const Playground: GridStory = {
render: () => (
<Grid templateColumns={['1fr', '1fr 1fr', '1fr 1fr 1fr']} placeItems={'center'} gap={2}>
<GridItem style={{ background: '#00f8' }}>A</GridItem>
<GridItem style={{ background: '#0f08' }}>B</GridItem>
<GridItem style={{ background: '#0ff8' }}>C</GridItem>
<GridItem style={{ background: '#f008' }}>D</GridItem>
<GridItem style={{ background: '#f0f8' }}>E</GridItem>
<GridItem style={{ background: '#ff08' }}>F</GridItem>
</Grid>
),
}

export const TemplateAreas: GridStory = {
render: () => (
<Grid
templateAreas={`
'header header'
'sidebar content'
'footer footer'
`}
placeItems={'center'}
minHeight={'calc(100vh - 5rem)'}
templateRows={'auto 1fr auto'}
templateColumns={'15em 1fr'}
gap={2}
>
<GridItem gridArea='header' style={{ background: '#00f8' }}>
Header
</GridItem>
<GridItem gridArea='sidebar' height='100%' style={{ background: '#0f08' }}>
Sidebar
</GridItem>
<GridItem gridArea='content' height='100%' style={{ background: '#0ff8' }}>
Content
</GridItem>
<GridItem gridArea='footer' mt='auto' style={{ background: '#f008' }}>
Footer
</GridItem>
</Grid>
),
}

export const NestedGrids: GridStory = {
render: () => (
<Grid templateColumns='1fr 1fr' placeItems='center' gap={2}>
<GridItem style={{ background: '#00f8' }}>A</GridItem>
<GridItem style={{ background: '#0f08' }}>B</GridItem>
<GridItem style={{ background: '#0ff8' }}>C</GridItem>
<Grid width={1} templateColumns='1fr 1fr 1fr' placeItems='center' gap={2}>
<GridItem style={{ background: '#f008' }}>D</GridItem>
<GridItem style={{ background: '#f0f8' }}>E</GridItem>
<GridItem style={{ background: '#ff08' }}>F</GridItem>
</Grid>
</Grid>
),
}

export const ResponsiveLayout: GridStory = {
render: () => (
<Grid
templateColumns={[
'1fr',
'1fr 1fr',
'1fr 1fr 1fr',
'1fr 1fr 1fr 1fr',
'1fr 1fr 1fr 1fr 1fr',
'1fr 1fr 1fr 1fr 1fr 1fr',
]}
placeItems='center'
gap={2}
>
<GridItem style={{ background: '#00f8' }}>A</GridItem>
<GridItem style={{ background: '#0f08' }}>B</GridItem>
<GridItem style={{ background: '#0ff8' }}>C</GridItem>
<GridItem style={{ background: '#f008' }}>D</GridItem>
<GridItem style={{ background: '#f0f8' }}>E</GridItem>
<GridItem style={{ background: '#ff08' }}>F</GridItem>
</Grid>
),
}

const meta: Meta<typeof Grid> = {
title: 'Layout/Grid',
component: Grid,
parameters: {
docs: {
page: () => (
<ThemeProvider>
<Hero name='Grid' img={''}>
Grids divide a web page into rows and columns and offer comprehensive features for controlling the
sizing and positioning of grid items, including the ability to define grid areas, set grid gaps,
and control the alignment and distribution of grid items
</Hero>

<TableOfContents links={['Overview', 'Props', 'Examples', 'Related Components']} />

<Section heading='Overview'>
<Text textStyle='paragraph'>
Grid is based on the CSS Grid Layout Module, which provides a two-dimensional grid-based layout
system, with rows and columns, making it easier to design web pages and components.
</Text>
</Section>

<Section heading='Props'>
<Primary />
<ArgsTable story={PRIMARY_STORY} />
</Section>

<Section heading='Examples'>
<StoryHeading storyName='Template Areas' storyTitle={meta.title} />
<Text textStyle='paragraph'>
Using the <code>gridTemplateAreas</code> prop, you can define grid areas and assign grid items
to them. The grid areas are defined by using the <code>grid-area</code> property on the grid
items. The <code>grid-area</code> property can be used to assign a name to a grid item, which
can then be used as a value of the <code>grid-template-areas</code> property.
</Text>
<LiveDemo code={TemplateAreas} />

<StoryHeading storyName='Nested Grids' storyTitle={meta.title} />
<Text textStyle='paragraph'>
Grids can be nested inside other grids. This allows you to create more complex layouts.
</Text>
<LiveDemo code={NestedGrids} />

<StoryHeading storyName='Responsive Layout' storyTitle={meta.title} />
<Text textStyle='paragraph'>
Grids can be responsive. You can define the number of columns for each breakpoint using the
<code>templateColumns</code> prop.
</Text>
<LiveDemo code={ResponsiveLayout} />
</Section>

<Section heading='Related Components'>
<RelatedComponentContainer>
<RelatedComponent name='Box'>
<Box width='75%' height='75%' bg='background.lightest'>
Box
</Box>
</RelatedComponent>
<RelatedComponent name='Flex'>
<Flex
justifyContent='center'
alignItems='center'
width='75%'
height='75%'
bg='background.lightest'
>
Flex
</Flex>
</RelatedComponent>
</RelatedComponentContainer>
</Section>
</ThemeProvider>
),
},
},
}
export default meta
94 changes: 94 additions & 0 deletions packages/core/src/Grid/Grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react'
import styled from 'styled-components'
import {
background,
BackgroundProps,
border,
BorderProps,
// color,
// ColorProps,
compose,
flexbox,
FlexboxProps,
grid,
GridProps,
layout,
LayoutProps,
position,
PositionProps,
shadow,
ShadowProps,
space,
SpaceProps,
system,
typography,
TypographyProps,
} from 'styled-system'

export interface IStyledSystemProps
extends BackgroundProps,
BorderProps,
// ColorProps,
FlexboxProps,
GridProps,
LayoutProps,
PositionProps,
ShadowProps,
SpaceProps,
TypographyProps {
style?: React.CSSProperties
}

const ComposedStyleFns = compose(
background,
border,
// color,
flexbox,
grid,
layout,
position,
shadow,
space,
typography
)

export interface IGridProps extends IStyledSystemProps {
children?: React.ReactNode
gap?: GridProps['gridGap']
rowGap?: GridProps['gridRowGap']
columnGap?: GridProps['gridColumnGap']
column?: GridProps['gridColumn']
row?: GridProps['gridRow']
area?: GridProps['gridArea']
autoFlow?: GridProps['gridAutoFlow']
autoRows?: GridProps['gridAutoRows']
autoColumns?: GridProps['gridAutoColumns']
templateRows?: GridProps['gridTemplateRows']
templateColumns?: GridProps['gridTemplateColumns']
templateAreas?: GridProps['gridTemplateAreas']
placeItems?: FlexboxProps['alignItems']
}

const GridStyleFns = system({
gap: { property: 'gridGap', scale: 'space' },
rowGap: { property: 'gridRowGap', scale: 'space' },
columnGap: { property: 'gridColumnGap', scale: 'space' },
column: { property: 'gridColumn' },
row: { property: 'gridRow' },
area: { property: 'gridArea' },
autoFlow: { property: 'gridAutoFlow' },
autoRows: { property: 'gridAutoRows' },
autoColumns: { property: 'gridAutoColumns' },
templateRows: { property: 'gridTemplateRows' },
templateColumns: { property: 'gridTemplateColumns' },
templateAreas: { property: 'gridTemplateAreas' },
placeItems: { property: 'placeItems' },
})

const StyledGrid = styled.div<IGridProps>`
${ComposedStyleFns}
${GridStyleFns}
display: grid;
`

export const Grid = (props: IGridProps) => <StyledGrid {...props} />
1 change: 1 addition & 0 deletions packages/core/src/Grid/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Grid'
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { DotLoader } from './DotLoader'
export { Flag } from './Flag'
export { Flex } from './Flex'
export { GenericBanner } from './GenericBanner'
export * from './Grid'
export { Heading } from './Heading'
export { Hide } from './Hide'
export { Hug } from './Hug'
Expand Down

0 comments on commit ba327c4

Please sign in to comment.