Composition

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.

Prop name

Type

Description

inline

boolean

Renders composition with display: inline-grid.

Composition supports all Prop aliases.

Usage

Define templates

Composition begins by defining a template string that consists of layout (grid) areas.

const areasMobile = `
logo
menu
`

Template string is just an alias for grid-template-areas.

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.

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:

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

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

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

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.