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.

pageBox

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.

Last updated