# EffectLayer

`EffectLayer` is where effects are played. It is a sheet over its nearest positioned parent that lets every press through. The openers play their [plans](https://bettertyped.github.io/react-cards-opening/docs/effects/plans/) on one. Take its handle and the whole [library of effects](https://bettertyped.github.io/react-cards-opening/docs/effects/library/) works anywhere: a level-up, a purchase, a streak.

> Live preview: see it play at https://bettertyped.github.io/react-cards-opening/docs/components/effect-layer/
>
> One layer, one card. Every button is one call to play.

## Usage

```tsx
import { EffectLayer, type EffectLayerHandle } from "@react-cards-opening/effects";
import "@react-cards-opening/effects/styles.css";

function Reward() {
  const layer = useRef<EffectLayerHandle>(null);
  const prize = useRef<HTMLDivElement>(null);

  return (
    <div style={{ position: "relative" }}>
      <EffectLayer handle={layer} />
      <div ref={prize}>...</div>
      <button
        onClick={() =>
          layer.current?.play(["flash", "shockwave", "confetti"], { at: prize.current, tone: "#f5c451" })
        }
      >
        Claim
      </button>
    </div>
  );
}
```

The layer comes first in its parent, so what follows it is drawn over the effects: a burst comes out from behind the prize. Put the layer last to play in front instead.

> `EffectLayer` comes from `@react-cards-opening/effects`, which the ui package brings along and re-exports. Import it from either. On its own, the effects package needs only GSAP.

## play

`play` takes one effect or a list to play at once, and where to play it. It answers the GSAP timeline, so a show can be paused, sped up, or put inside a timeline of your own.

| Option | Type | What it does |
| --- | --- | --- |
| `at?` | `Element \| { x, y } \| null` | Where the effect is centred. The layer's middle when left out. |
| `size?` | `number` | The width of what is celebrated, in pixels. An element given as `at` answers this itself. |
| `ratio?` | `number` | Height over width of what is celebrated: the outline `rim` and `echo` draw. 4/3 when left out. |
| `tone?` | `string` | The colour, as a plain hex. The layer's own `--rco-tone` when left out. |
| `accent?` | `string` | A second colour, for effects that use two. A tint of the tone when left out. |
| `subject?` | `HTMLElement \| null` | What `shake`, `quake`, `punch` and `glitch` move. The layer's parent when left out. |
| `delay?` | `number` | Seconds to wait first. |
| `random?` | `() => number` | The dice. A seeded one plays an effect the same way every time. |
| `blend?` | `"add" \| "normal"` | How lights are laid on the page. `EffectLayer` picks from its theme. |

## Props

| Prop | Type | What it does |
| --- | --- | --- |
| `handle?` | `Ref<EffectLayerHandle>` | `play(effects, options)`, `clear()` and `element()`. |
| `theme?` | `{ bg: string }` | The ground the layer is on: a theme, or just its `bg`. On a light one the lights are painted instead of added up. |
| `tone?` | `string` | The colour effects wear when a play does not name one. |
| `className?` | `string` | A class for the layer. |
| `style?` | `CSSProperties` | Inline styles for the layer. |

## Without React

`playEffects(layer, effects, options)` is the same call on any element with the class `rco-fx-layer`. `clearEffects(layer)` takes everything off and gives the canvas back: call it when the layer goes away.

```ts
import { clearEffects, playEffects } from "@react-cards-opening/effects";

const timeline = playEffects(layer, "nova", { at: button, tone: "#22d3ee" });
timeline.timeScale(0.5);
```

## Good manners

- **Reduced motion plays nothing.** The timeline comes back empty and the page stays still.
- **Particles share one canvas a layer**, stepped by GSAP's ticker. When the last one is gone the canvas stops drawing.
- **A play cleans up after itself.** Its elements are removed when it ends or is interrupted, and a stage that was shaken is put back.

## Related

- [Effects library](https://bettertyped.github.io/react-cards-opening/docs/effects/library/)
- [Effect plans](https://bettertyped.github.io/react-cards-opening/docs/effects/plans/)
- [CardOpening](https://bettertyped.github.io/react-cards-opening/docs/components/card-opening/)
- [Reduced motion](https://bettertyped.github.io/react-cards-opening/docs/core/reduced-motion/)

Source: https://bettertyped.github.io/react-cards-opening/docs/components/effect-layer/
