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.
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.