# Composition laws

Source: https://plumeria.dev/docs/composition-laws



A `classStyle` array merges its styles property by property. Written as an
operation, where $\oplus$ merges the style on its right into the one on its left,
that merge obeys four laws. Each one is something you can rely on when you
restructure styles.

## Associativity [#associativity]

$(A \oplus B) \oplus C = A \oplus (B \oplus C)$

Grouping does not change the result. Arrays can be nested, so these are the
same:

```tsx
<div classStyle={[[styles.a, styles.b], styles.c]} />
<div classStyle={[styles.a, [styles.b, styles.c]]} />
```

That is what lets you pull part of an array into a variable, or a prop, and put
it back anywhere in the same position.

## Identity [#identity]

$A \oplus I = I \oplus A = A$

`false`, `null` and `undefined` merge into nothing, so each of them is the
identity $I$. That is why a condition can sit in the array:

```tsx
<div classStyle={[styles.base, isActive && styles.active]} />
```

When `isActive` is false, the array is `styles.base` alone.

## Idempotency [#idempotency]

$A \oplus A = A$

Merging a style with itself changes nothing, so a style that reaches an element
twice, through a shared base and a prop, say, does no harm.

## No commutativity [#no-commutativity]

$A \oplus B \neq B \oplus A$

Order is the one thing that does matter. When two styles set the same property,
the one on the right wins, so swapping them swaps the winner. Styles that set
different properties never compete, and their order makes no difference.

A shorthand against its longhand is the exception: the longhand wins in either
order. See [Specificity](/docs/specificity).

## What the laws add up to [#what-the-laws-add-up-to]

Together, associativity and identity make the merge a **monoid**: any array,
however it is nested or wherever its conditions fall, reduces to one style. The
compiler does that reduction at build time, so the element receives a single
class list:

$parse(A \oplus B \oplus C) \to \text{"classA classB classC"}$

Here `classA` and the rest are not each style's classes laid side by side. The
reduction is a merge, so a property overridden from the right leaves no class
behind:

```tsx
const styles = css.create({
  a: { color: 'red', padding: 4 },
  b: { color: 'blue' },
});

<div classStyle={[styles.a, styles.b]} />
```

The element receives two classes, `padding: 4px` and `color: blue`; the class
for `color: red` is not among them. Two classes for the same property never
reach one element, so the cascade is never left to pick the winner.
