Specification
Component that represents a layout composition.
Props
Composition inherits from Box component, thus is accepts the same props and CSS Grid props on top.
Renders composition with display: inline-grid
.
Usage
Define templates
Composition begins by defining a template string that consists of layout (grid) areas.
Copy const areasMobile = `
logo
menu
`
Since Atomic layout comes with responsive built-in, you can define multiple layout templates for a single composition based on the breakpoints of your layout.
Copy const areasTablet = `
logo menu
search search
`
Render Composition
Once layout templates are defined, pass them as the respective areas
props of the Composition. Each area in the template is turned into a React component and being exposed as an argument property of the children function:
Copy <Composition
areas={areasMobile}
areasMd={areasTablet}>
{(Areas) => (
<>
<Areas.Logo>...</Areas.Logo>
<Areas.Search>...</Areas.Search>
<Areas.Menu>...</Areas.Menu>
</>
)}
</Composition>
Generated area components are exposed as unique capitalized keys of the children function.
Configuration
Composition is meant to be configurable. There is a set of Prop aliases you can apply to make composition suit your needs. For example, we can specify a templateCols
prop to control the behavior of our columns on different breakpoints:
Copy <Composition
areas={areasMobile}
areasMd={areasTablet}
templateCols="1fr auto"
templateColsMd="1fr 1fr" />
Examples
Template-less composition
Composition can be used without any templates. In that case it serves as a display: grid
wrapper for its children elements. All Prop aliases still apply.
Copy import React from 'react'
import { Composition } from 'atomic-layout'
export const Header = () => (
<Composition templateCols="repeat(3, 1fr)">
<Logo />
<Menu />
<Actions />
</Composition>
)
Note that using the Box component is recommended when you don't wish to control elements composition, but want to distribute spacial relation of the parent element.
Simple composition
src/components/ArtistCard/index.jsx
Copy import React from 'react'
import { Composition } from 'atomic-layout'
const areasMobile = `
thumbnail
heading
content
`
const areasDesktop = `
thumbnail heading
thumbnail content
`
export const ArtistCard = ({ title, imageUrl, description }) => (
<Composition
areas={areasMobile}
areasMd={areasDesktop}
gap={10}
gapMd={20}
padding={10}>
{(Areas) => (
<>
<Areas.Thumbnail>
<img src={imageUrl} alt={title} />
</Areas.Thumbail>
<Areas.Heading>
<h3>{title}</h3>
</Areas.Heading>
<Areas.Content>
<p>{description}</p>
</Areas.Content>
</>
)}
</Composition>
)
Nested composition
components/ArtistCard/index.jsx
Copy import React from 'react'
import { Composition } from 'atomic-layout'
import ArtistContent from './ArtistContent'
const areasMobile = `
thumbnail
content
`
export const ArtistCard = ({
title,
description,
publishDate,
imageUrl,
onShareClick
}) => (
<Composition areas={areasMobile}>
{(Areas) => (
<>
<Areas.Thumbnail>
<img src={imageUrl} alt={title} />
</Areas.Thumbnail>
<Areas.Content>
<ArtistContent
description={description}
publishDate={publishDate}
onShareClick={onShareClick} />
</Areas.Content>
</>
)}
</Composition>
)
components/ArtistCard/ArtistContent.jsx
Copy import React from 'react'
import { Composition } from 'atomic-layout'
const areasMobile = `
meta
actions
text
`
const areasTablet = `
meta actions
text text
`
export const ArtistContent = ({ description, publishDate, onShareClick }) => (
<Composition
areas={areasMobile}
areasMd={areasTablet}
gap={10}
gapMd={20}>
{({ Meta, Actions, Text }) => (
<>
<Meta>
{publishDate}
</Meta>
<Actions>
<button onClick={onShareClick}>Share</button>
</Actions>
<Text>
{description}
</Text>
</>
)}
</Composition>
)
Using areas templates
It is possible to describe the size of each column/row using a shorthand grid-template
syntax.
To specify a row size put its numeric value right after the row areas declaration.
To specify a column size put a trailing slash (/
) and provide each column's dimensions after it.
Copy import React from 'react'
import { Composition } from 'atomic-layout'
const templateTablet = `
meta actions 250px
text text 1fr
/ 500px auto
`
export const ArtistContent = ({ description, publishDate, onShareClick }) => (
<Composition template={templateTablet}>
{(Areas) => (
<>
<Areas.Meta>{publishDate}</Areas.Meta>
<Areas.Actions>
<button onClick={onShareClick}>Share</button>
</Areas.Actions>
<Areas.Text>
{description}
</Areas.Text>
</>
)}
</Composition>
)
Note that in order to use grid-template
syntax you must provide the template string as a value of the template
prop of the Composition component.