Skip to content

Instantly share code, notes, and snippets.

@horaciosystem
Last active October 7, 2018 01:54
Show Gist options
  • Save horaciosystem/e348f7d8e9a254d6717a438d932af9b3 to your computer and use it in GitHub Desktop.
Save horaciosystem/e348f7d8e9a254d6717a438d932af9b3 to your computer and use it in GitHub Desktop.
React Grid component to render a specific amount of lines with cross screen width capability
import { withSize } from "react-sizeme"
import { take } from "lodash/fp"
import styled from "styled-components"
const CONTAINER_SIDE_PADDING = 20
const CONTAINER_TOTAL_PADDING = CONTAINER_SIDE_PADDING * 2
const ListContainer = styled.div`
display: flex;
flex-wrap: ${({ isMultiLine }) => (isMultiLine ? "wrap" : "nowrap")};
padding: ${CONTAINER_SIDE_PADDING}px;
justify-content: center;
`
export function Grid({
items,
gutterWidth,
gutterHeight,
cardComponent: Card,
cardWidth = 272,
lines = 1,
size
}) {
const columnWidth = cardWidth + gutterWidth
const amountToRenderPerLine = Math.floor(
(size.width - CONTAINER_TOTAL_PADDING) / columnWidth
)
const itemsToRender = take(amountToRenderPerLine * lines, items)
const isMultiLine = lines > 1
return (
<ListContainer isMultiLine={isMultiLine}>
{itemsToRender.map(item => (
<div
style={{
marginRight: gutterWidth,
marginBottom: gutterHeight
}}
key={item.id}
>
<Card item={item} />
</div>
))}
</ListContainer>
)
}
export default withSize()(Grid)
@horaciosystem
Copy link
Author

horaciosystem commented Oct 7, 2018

Tests:

import { shallow } from "enzyme"
import { Grid } from "./index"

describe("Grid", () => {
  const items = Array.from({ length: 90 }, (it, index) => ({
    id: index
  }))

  const Card = () => <div />

  const build = size => ({ gutterWidth = 18, ...props }) => {
    return shallow(
      <Grid
        size={size}
        items={items}
        gutterWidth={gutterWidth}
        cardComponent={Card}
        {...props}
      />
    )
  }

  describe("1024px", () => {
    const buildSmallDesktop = build({ width: 1024 })

    it("renders 3 cards with 272px width", () => {
      const wrapper = buildSmallDesktop({ cardWidth: 272 })
      expect(wrapper.find(Card)).toHaveLength(3)
    })

    it("renders 1 card with 480px", () => {
      const wrapper = buildSmallDesktop({ cardWidth: 480 })
      expect(wrapper.find(Card)).toHaveLength(1)
    })

    it("renders 4 cards with 200px width", () => {
      const wrapper = buildSmallDesktop({ cardWidth: 200 })
      expect(wrapper.find(Card)).toHaveLength(4)
    })

    it("renders 6 cards for a 2 lines Grid", () => {
      const wrapper = buildSmallDesktop({ cardWidth: 272, lines: 2 })
      expect(wrapper.find(Card)).toHaveLength(6)
    })
  })

  describe("1280px", () => {
    const buildMediumDesktop = build({ width: 1280 })

    it("renders 4 cards with 272px width", () => {
      const wrapper = buildMediumDesktop({ cardWidth: 272 })
      expect(wrapper.find(Card)).toHaveLength(4)
    })

    it("renders 2 card with 480px", () => {
      const wrapper = buildMediumDesktop({ cardWidth: 480 })
      expect(wrapper.find(Card)).toHaveLength(2)
    })

    it("renders 5 cards with 200px width", () => {
      const wrapper = buildMediumDesktop({ cardWidth: 200 })
      expect(wrapper.find(Card)).toHaveLength(5)
    })

    it("renders 8 cards for a 2 lines Grid", () => {
      const wrapper = buildMediumDesktop({ cardWidth: 272, lines: 2 })
      expect(wrapper.find(Card)).toHaveLength(8)
    })
  })

  describe("1440px", () => {
    const buildLargeDesktop = build({ width: 1440 })

    it("renders 4 cards with 272px width", () => {
      const wrapper = buildLargeDesktop({ cardWidth: 272 })
      expect(wrapper.find(Card)).toHaveLength(4)
    })

    it("renders 2 card with 480px", () => {
      const wrapper = buildLargeDesktop({ cardWidth: 480 })
      expect(wrapper.find(Card)).toHaveLength(2)
    })

    it("renders 6 cards with 200px width", () => {
      const wrapper = buildLargeDesktop({ cardWidth: 200 })
      expect(wrapper.find(Card)).toHaveLength(6)
    })

    it("renders 8 cards for a 2 lines Grid", () => {
      const wrapper = buildLargeDesktop({ cardWidth: 272, lines: 2 })
      expect(wrapper.find(Card)).toHaveLength(8)
    })
  })

  describe("1920px", () => {
    const buildFullHDDesktop = build({ width: 1920 })

    it("renders 6 cards with 272px width", () => {
      const wrapper = buildFullHDDesktop({ cardWidth: 272 })
      expect(wrapper.find(Card)).toHaveLength(6)
    })

    it("renders 6 card with 480px", () => {
      const wrapper = buildFullHDDesktop({ cardWidth: 480, lines: 2 })
      expect(wrapper.find(Card)).toHaveLength(6)
    })

    it("renders 8 cards with 200px width", () => {
      const wrapper = buildFullHDDesktop({ cardWidth: 200 })
      expect(wrapper.find(Card)).toHaveLength(8)
    })

    it("renders 12 cards for a 2 lines Grid", () => {
      const wrapper = buildFullHDDesktop({ cardWidth: 272, lines: 2 })
      expect(wrapper.find(Card)).toHaveLength(12)
    })
  })
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment