# Body

## About

As `body` and `html` elements are concerns that are handled external to a template, our convention is to use `Body` as
the root-most component of a template.

The element that `Body` renders has an inline style of `display: contents` which causes it to have no affect on layout.
Its children behave like children of the closest parent to `Body` that does not also have `display: contents`, ie. the
native `body` element. As `body` is hardcoded to be `display: flex; flex-direction: column;`, this makes any `Body`
children flex items for styling purposes. Similarly, note also that passing `background-color:some-color` classes via
`Body`’s `className` prop will have no affect, as the `Body` element has no width or height. This is why that class
should instead be passed to the background layer proxy (which is a CenteredLayer component) via `backdropClassName`.

The only reason we have `Body` outputting a wrapping element at all is to provide the opportunity to add global font
styling classes that cascades to the rest of the template.

## Properties

| prop                    | value type                  |
| :---------------------- | :-------------------------- |
| **`className`**         | `string` \| `undefined`     |
| **`animation`**         | result of useAnimation hook |
| **`backdropClassName`** | `string` \| `undefined`     |
| **`backdropStyle`**     | `object` \| `undefined`     |
| **`bleed`**             | `boolean` \| `undefined`    |
| **`popup`**             | `ReactNode` \| `undefined`  |
| **`children`**          | `ReactNode` \| `undefined`  |

## Basic usage

```jsx
<Body>template JSX goes here</Body>
```

## With global classes and background colour

Use `backdropClassName` to apply global `background-color` styling. These are applied to an overlay child layer (via the
CenteredLayer component).

Use `backdropStyle` to apply inline styles to the backdrop.

Use `className` to add other global styles.

```jsx
  <Body
    className={`
      color:neutral-1000
      font-family:default
      font-size:400
      font-weight:700
      line-height:200
    `}
    backdropClassName={`
      background-color:neutral-0
    `}
    backdropStyle={{
      backgroundColor: `var(--some-special-color)`,
    }}
  >
    template JSX goes here
  </Body>
`
```

## Bleed and crops

Templates intended to produce print media outputs should be created with extra bleed. Passing the boolean `bleed` prop
will add the required slug area and crop marks.

Note that you will need to manually add extra bleed columns and rows to surround your main grid layout in order to
control which elements should stretch into those areas. A nice conventions is to use the following grid area names for
the bleed rows and columns `—— ll ▍▍ ▂▂` with liberal space to better isolate the more unique parts of your template
grid.

```jsx
  <Body
    bleed
  >
    <div
      className={`
        ${className}
        display:grid
        grid-template-areas:var-1
        grid-template-columns:var-1
        grid-template-rows:var-1
        width:100%
        height:100%
      `}
      style={{
        // LEGEND
        // bleed:  ——   ll   ▍▍   ▂▂

        // NOTE
        // these — are en-rules because hyphens don't work as grid area names

        '--grid-template-areas-var-1': `

          "——       ——   ——   ——       ——  "


          "ll        ◤    —   ◥        ▍▍ "
          "ll        l   📝    ▍       ▍▍ "
          "ll        l   🐄    ▍       ▍▍ "
          "ll        ◣    ▂   ◢        ▍▍ "


          "▂▂       ▂▂   ▂▂   ▂▂      ▂▂  "

        `,
        '--grid-template-columns-var-1': `var(--bleed) var(--sacred-space) 1fr var(--sacred-space) var(--bleed)`,
        '--grid-template-rows-var-1': `var(--bleed) var(--sacred-space) auto 1fr min-content var(--bleed)`,
      }}
    >

      template JSX goes here

    </div>
  </Body>
`
```

## Passing in an animation

When a template is animated, the object returned from `useAnimation` must be passed to the `Body` component via its
`animation` prop. This allows the animation script tags to be automatically added, along with other helpers. For
example, the `is-static` class is conditionally applied to the `Body`’s DOM element, enabling a templater to adjust
styling depending on whether an export type is animated or static.

```jsx
import useAnimation from '@/hooks/useAnimation'
import {Body} from '@myadbox/exoplanet-toolkit'

const Template = (props) => {
  // store the result of useAnimation and pass it to `Body`
  const animation = useAnimation(props)
  // `is-static` class is added to the DOM element of `Body` if either
  // `props.cancelAnimation` or `props.content.cancelAnimation` is true.
  // This enables `is-static__visibility:visible` to override `visibility:hidden`
  // when static/non-animated output is requested.
  return (
    <Body animation={animation}>
      <p
        className={`
          visibility:hidden
        `}
      >
        Initially hidden when output is animated
      </p>

      <p
        className={`
          visibility:hidden
          is-static__visibility:visible
        `}
      >
        Initially hidden when output is animated, but always visible when output is static.
      </p>
    </Body>
  )
}
```
