Pārlūkot izejas kodu

Add LayoutGrid component (#1145)

* wip

* wip

* getting there

* it works 🥳

* new grid api

* removing uneeded checks

* row features

* Grid helper

* non responsive rules

* Grid size
Diego Cardenas 3 gadi atpakaļ
vecāks
revīzija
52b8249604

+ 59 - 0
src/shared/components/LayoutGrid/LayoutGrid.tsx

@@ -0,0 +1,59 @@
+import { css } from '@emotion/react'
+import styled from '@emotion/styled'
+
+import { media } from '@/shared/theme'
+
+type ReponsivenessObject = Partial<Record<keyof typeof media, number>>
+
+export const LayoutGrid = styled.div<{ big?: boolean }>`
+  display: grid;
+  grid-template-columns: repeat(12, 1fr);
+  grid-gap: 16px;
+
+  ${media.medium} {
+    grid-gap: 24px;
+  }
+
+  max-width: ${({ big }) => (big ? '2284' : '1440')}px;
+  margin: 0 auto;
+`
+
+type GridItemProps = {
+  colStart?: number | 'initial' | ReponsivenessObject
+  colSpan?: number | ReponsivenessObject
+  rowStart?: number | 'initial' | ReponsivenessObject
+  rowSpan?: number | ReponsivenessObject
+}
+
+function isResponsivenessObject(prop?: number | 'initial' | ReponsivenessObject): prop is ReponsivenessObject {
+  return !!prop && typeof prop !== 'number' && prop !== 'initial'
+}
+
+const createBreakpointGridItemRules = (breakpointKey: keyof ReponsivenessObject) => ({
+  colStart,
+  colSpan,
+  rowStart,
+  rowSpan,
+}: GridItemProps) => css`
+  ${media[breakpointKey]} {
+    ${isResponsivenessObject(colStart) && colStart[breakpointKey] && `grid-column-start: ${colStart[breakpointKey]};`}
+    ${isResponsivenessObject(colSpan) && colSpan[breakpointKey] && `grid-column-end: span ${colSpan[breakpointKey]};`}
+    ${isResponsivenessObject(rowStart) && rowStart[breakpointKey] && `grid-row-start: ${rowStart[breakpointKey]};`}
+    ${isResponsivenessObject(rowSpan) && rowSpan[breakpointKey] && `grid-row-end: span ${rowSpan[breakpointKey]};`}
+  }
+`
+
+export const GridItem = styled.div<GridItemProps>`
+  ${({ colStart }) => !isResponsivenessObject(colStart) && colStart && `grid-column-start: ${colStart};`}
+  ${({ colSpan }) => !isResponsivenessObject(colSpan) && colSpan && `grid-column-end: span ${colSpan};`}
+  ${({ rowStart }) => !isResponsivenessObject(rowStart) && rowStart && `grid-row-start: ${rowStart};`}
+  ${({ rowSpan }) => !isResponsivenessObject(rowSpan) && rowSpan && `grid-row-end: span ${rowSpan};`}
+  
+  ${createBreakpointGridItemRules('base')}
+  ${createBreakpointGridItemRules('compact')}
+  ${createBreakpointGridItemRules('small')}
+  ${createBreakpointGridItemRules('medium')}
+  ${createBreakpointGridItemRules('large')}
+  ${createBreakpointGridItemRules('xlarge')}
+  ${createBreakpointGridItemRules('xxlarge')}
+`

+ 1 - 0
src/shared/components/index.ts

@@ -44,3 +44,4 @@ export * from './LegalText'
 export * from './Loader'
 export * from './AnimatedError'
 export * from './EmptyFallback'
+export * from './LayoutGrid/LayoutGrid'

+ 2 - 4
src/shared/theme/breakpoints.ts

@@ -1,6 +1,4 @@
-const breakpoints: {
-  [key: string]: string
-} = {
+export const breakpoints = {
   base: '320px',
   compact: '450px',
   small: '600px',
@@ -8,6 +6,6 @@ const breakpoints: {
   large: '1440px',
   xlarge: '1920px',
   xxlarge: '2560px',
-}
+} as const
 
 export default breakpoints

+ 2 - 0
src/views/playground/PlaygroundLayout.tsx

@@ -20,6 +20,7 @@ import {
   UploadFiles,
   VideoMetaData,
 } from './Playgrounds'
+import { GridTesting } from './Playgrounds/GridTesting'
 import OrionTesting from './Playgrounds/OrionTesting'
 
 const playgroundRoutes = [
@@ -36,6 +37,7 @@ const playgroundRoutes = [
   { path: 'dialogs', element: <Dialogs />, name: 'Dialogs' },
   { path: 'store', element: <PlaygroundCommonStore />, name: 'Store' },
   { path: 'orion-testing', element: <OrionTesting />, name: 'Orion testing' },
+  { path: 'grid', element: <GridTesting />, name: 'Grid testing' },
 ]
 
 export const PlaygroundLayout = () => {

+ 38 - 0
src/views/playground/Playgrounds/GridTesting.tsx

@@ -0,0 +1,38 @@
+import styled from '@emotion/styled'
+import React from 'react'
+
+import { GridItem, LayoutGrid } from '@/shared/components'
+
+export const GridTesting = () => {
+  return (
+    <div>
+      <LayoutGrid>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem
+          colStart={{ xlarge: 7 }}
+          colSpan={{ small: 2, medium: 3, large: 4, xlarge: 5, xxlarge: 6 }}
+        ></StyledGridItem>
+      </LayoutGrid>
+      <LayoutGrid big>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem></StyledGridItem>
+        <StyledGridItem
+          colStart={{ xlarge: 7 }}
+          colSpan={{ small: 2, medium: 3, large: 4, xlarge: 5, xxlarge: 6 }}
+        ></StyledGridItem>
+      </LayoutGrid>
+    </div>
+  )
+}
+
+const StyledGridItem = styled(GridItem)`
+  height: 600px;
+  background-color: red;
+`