Skip to content

Commit

Permalink
feat: improve grid responsive
Browse files Browse the repository at this point in the history
  • Loading branch information
Wurielle committed Aug 29, 2024
1 parent 9593bd5 commit 9051b05
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 64 deletions.
16 changes: 8 additions & 8 deletions packages/react/src/components/layout/grid/grid.shared.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { ElementType, HTMLAttributes } from 'react'
import { defineProps, PropsDefinition } from '@/utils/component'
import { boxPropsDefinition } from '@/components/layout/box'
import { Screens, Spacing } from '@/tokens'
import { Spacing } from '@/tokens'
import { Properties } from 'csstype'

export const gridPropsDefinition = defineProps(({ optional }) => ({
export const gridPropsDefinition = defineProps(({ optional, responsive }) => ({
...boxPropsDefinition,
breakpoints: optional<Screens>(),
gap: optional<Spacing | Properties['gap'] | number>('3'),
columns: optional<number>(12),
rows: optional<number>(),
align: optional<Properties['alignItems']>(),
...responsive({
gap: optional<Spacing | Properties['gap'] | number>('3'),
columns: optional<number>(12),
rows: optional<number>(),
align: optional<Properties['alignItems']>(),
}),
}))

export const gridColPropsDefinition = defineProps(({ optional, responsive }) => ({
...boxPropsDefinition,
columns: gridPropsDefinition.columns,
...responsive({
span: optional<number>(),
start: optional<Properties['gridColumnStart'] | number>(),
Expand Down
26 changes: 13 additions & 13 deletions packages/react/src/components/layout/grid/grid.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,63 +13,63 @@ type Story = StoryObj<typeof meta>

const Template: StoryFn<typeof Grid> = (args) => (
<Box p={'5'} bg="slate.100">
<Grid {...args} h={500}>
<Grid.Col>
<Grid {...args} h={500} mdColumns={12} columns={6}>
<Grid.Col mdSpan={12} span={6}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
1
</Box>
</Grid.Col>
<Grid.Col span={4}>
<Grid.Col mdSpan={4} span={2}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
1
</Box>
</Grid.Col>
<Grid.Col span={4}>
<Grid.Col mdSpan={4} span={2}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
2
</Box>
</Grid.Col>
<Grid.Col span={4}>
<Grid.Col mdSpan={4} span={2}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
3
</Box>
</Grid.Col>
<Grid.Col mdSpan={8} lgSpan={4}>
<Grid.Col mdSpan={8} lgSpan={4} span={6}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
1
</Box>
</Grid.Col>
<Grid.Col mdSpan={4} lgSpan={4}>
<Grid.Col mdSpan={4} lgSpan={4} span={3}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
2
</Box>
</Grid.Col>
<Grid.Col mdSpan={6} mdStart={4} lgStart={'auto'} lgSpan={4}>
<Grid.Col mdSpan={6} mdStart={4} lgStart={'auto'} lgSpan={4} span={3}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
3
</Box>
</Grid.Col>
<Grid.Col span={12}>
<Grid.Col mdSpan={12} span={6}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
1
</Box>
</Grid.Col>
<Grid.Col span={2}>
<Grid.Col mdSpan={2} span={1}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
1
</Box>
</Grid.Col>
<Grid.Col span={2}>
<Grid.Col mdSpan={2} span={1}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
2
</Box>
</Grid.Col>
<Grid.Col span={2}>
<Grid.Col mdSpan={2} span={1}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
3
</Box>
</Grid.Col>
<Grid.Col span={2} start={9}>
<Grid.Col mdSpan={2} mdStart={9} span={1}>
<Box px={'5'} py={'3'} h={'full'} bg={'slate.200'} style={{ textAlign: 'center' }}>
4
</Box>
Expand Down
55 changes: 34 additions & 21 deletions packages/react/src/components/layout/grid/grid.styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,57 @@ import { PropsDefinitionWithDefaults } from '@/utils'
export const StGrid = styled(StBox)<StyledProps<PropsDefinitionWithDefaults<GridPropsDefinition>>>((context) => {
const {
theme: { spacing = _spacing },
styled: { align, columns, rows, gap },
} = context
const { getResponsive } = defineMixins(context)
return [
{
display: 'grid',
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
gap: getRemValue(gap, spacing),
},
!isUndefined(rows) && {
gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`,
},
align && {
alignItems: align,
},
getResponsive(
'rows',
(rows) =>
!isUndefined(rows) && {
gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`,
}
),
getResponsive(
'columns',
(columns) =>
!isUndefined(columns) && {
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
}
),
getResponsive(
'gap',
(gap) =>
!isUndefined(gap) && {
gap: getRemValue(gap, spacing),
}
),
getResponsive(
'align',
(align) =>
!isUndefined(align) && {
alignItems: align,
}
),
]
})

export const StGridCol = styled(StBox)<StyledProps<PropsDefinitionWithDefaults<GridColPropsDefinition>>>((context) => {
const { getResponsive } = defineMixins({
...context,
styled: {
...context.styled,
span: context.styled.span || context.styled.columns,
rowSpan: context.styled.rowSpan || null,
},
})
const { getResponsive } = defineMixins(context)
return [
{
minWidth: 0,
flexShrink: 0,
},
getResponsive(
'span',
(value) =>
getResponsive('span', (value) => {
return (
!isUndefined(value) && {
gridColumn: `span ${value} / span ${value}`,
}
),
)
}),
getResponsive(
'start',
(value) =>
Expand Down
29 changes: 9 additions & 20 deletions packages/react/src/components/layout/grid/grid.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import { Context, createContext, forwardRef, ForwardRefExoticComponent, PropsWithoutRef, RefAttributes, useContext, useMemo } from 'react'
import { forwardRef, ForwardRefExoticComponent, PropsWithoutRef, RefAttributes, useMemo } from 'react'
import { StGrid, StGridCol } from './grid.styled'
import { GridColProps, gridColPropsDefinition, GridProps, gridPropsDefinition } from './grid.shared'
import { Slot } from '@radix-ui/react-slot'
import { useDefinitionProps } from '@/utils/component'

const GridContext = createContext({}) as Context<Pick<GridProps, 'columns'>>

const GridCol = forwardRef<HTMLDivElement, GridColProps>(function GridCol(props, forwardedRef) {
const [gridColProps, { children, asChild, ...htmlProps }] = useDefinitionProps(props, gridColPropsDefinition)
const Comp = useMemo(() => (asChild ? StGridCol.withComponent(Slot) : StGridCol), [asChild])
const { columns } = useContext(GridContext)
return (
<Comp
data-grid-col
ref={forwardedRef}
{...htmlProps}
styled={{
...gridColProps,
columns: columns || gridColProps.columns,
}}
>
{children}
Expand All @@ -29,24 +25,17 @@ type GridType = ForwardRefExoticComponent<PropsWithoutRef<GridProps> & RefAttrib

export const Grid = forwardRef(function Grid({ children, ...props }, forwardedRef) {
const [gridProps, htmlProps] = useDefinitionProps(props, gridPropsDefinition)
const { columns } = gridProps
return (
<GridContext.Provider
value={{
columns,
<StGrid
data-grid
ref={forwardedRef}
{...htmlProps}
styled={{
...gridProps,
}}
>
<StGrid
data-grid
ref={forwardedRef}
{...htmlProps}
styled={{
...gridProps,
}}
>
{children}
</StGrid>
</GridContext.Provider>
{children}
</StGrid>
)
}) as GridType & { Col: typeof GridCol }

Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/utils/css-in-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ export const defineMixins = <
) => {
const getResponsive = <
Prop extends keyof Context['styled'],
Callback extends (value: Context['styled'][Prop], screen: Screen | '', prop: Prop) => InterpolationPrimitive,
Callback extends (value: Context['styled'][Prop], screen: Screen | null, prop: Prop) => InterpolationPrimitive,
>(
prop: Prop,
callback: Callback
) => {
const screens = context.theme?.screens || _screens
const props = context.styled || {}
return [
callback(props[prop as keyof typeof props] as Context['styled'][Prop], '', prop),
callback(props[prop as keyof typeof props] as Context['styled'][Prop], null, prop),
...(Object.entries(screens) as [Screen, Screens[keyof Screens]][]).map(([screen, { value, margin }]) => {
const responsiveProp = `${screen}${String(prop).charAt(0).toUpperCase() + String(prop).slice(1)}` as Prop
const responsiveValue = props[responsiveProp as keyof typeof props] as Context['styled'][Prop]
Expand Down

0 comments on commit 9051b05

Please sign in to comment.