---
title: "Fusion"
description: "A gooey effect that fuses two slots when active."
category: Effects
status: beta
since: 0.3.4
tags: [fusion, gooey, motion]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
Slots `a` and `b` move together and fuse when active; `gap` is their distance apart, and `trigger` sets what activates them.
:::TuffDemoWrapper{demo="FusionFusionDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'

  const active = ref(false)
  </script>

  <template>
    <TxButton @click="active = !active">Toggle</TxButton>
    <TxFusion v-model="active" trigger="hover" :gap="240">
      <template #a><div class="blob blob--large" /></template>
      <template #b><div class="blob blob--small" /></template>
    </TxFusion>
    <TxFusion trigger="click" direction="y" :gap="46">
      <template #a><div class="pill" /></template>
      <template #b><div class="pill" /></template>
    </TxFusion>
  </template>
---
:::

### Button and Tooltip Bubble
`direction="y"` fuses the two shapes vertically.
:::TuffDemoWrapper{demo="FusionFusionButtonTooltipDemo" code-lang="vue"}
---
code: |
  <template>
    <TxFusion v-model="active" trigger="hover" direction="y" :gap="44">
      <template #a><!-- Primary button: Save ⌘S --></template>
      <template #b><!-- Tooltip bubble: Saved to drafts --></template>
    </TxFusion>
  </template>
---
:::

### Avatar and Badge
:::TuffDemoWrapper{demo="FusionFusionAvatarBadgeDemo" code-lang="vue"}
---
code: |
  <template>
    <TxFusion trigger="hover" :gap="64">
      <template #a><!-- Avatar TA --></template>
      <template #b><!-- Badge 8 --></template>
    </TxFusion>
  </template>
---
:::

### Chip and Icon
:::TuffDemoWrapper{demo="FusionFusionChipIconDemo" code-lang="vue"}
---
code: |
  <template>
    <TxFusion trigger="hover" :gap="54">
      <template #a><!-- Status chip: Synced --></template>
      <template #b><!-- Circular badge: ✓ --></template>
    </TxFusion>
  </template>
---
:::

### Mini Card and FAB
:::TuffDemoWrapper{demo="FusionFusionMiniCardFabDemo" code-lang="vue"}
---
code: |
  <template>
    <TxFusion v-model="active" trigger="hover" :gap="92">
      <template #a><!-- Quick Note card --></template>
      <template #b><!-- Floating + button --></template>
    </TxFusion>
  </template>
---
:::

### Best Practices

- Use it as a decorative accent; never make it the only way critical state is shown.
- Use `trigger="manual"` when a parent state machine, form, or route needs deterministic control.
- Keep the two shapes similar in size, and tune `gap`, `blur`, `alpha`, and `alphaOffset` together.
- When the user prefers reduced motion, have the host set `disabled` or keep the effect inactive.
- Avoid `trigger="click"` when the slots contain buttons or links, so the interactions don't collide.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `modelValue` | `boolean \| undefined` | `undefined` | Controlled active state; when omitted, internal state is used. |
| `disabled` | `boolean` | `false` | Blocks state changes and shows the disabled look. |
| `trigger` | `'hover' \| 'click' \| 'manual'` | `'hover'` | What activates it; `manual` ignores the pointer and follows `v-model` only. |
| `direction` | `'x' \| 'y'` | `'x'` | Axis the two shapes separate along. |
| `gap` | `number` | `40` | Distance in px between the shapes while inactive. |
| `duration` | `number` | `260` | Transition duration in ms; negative values count as `0`. |
| `easing` | `string` | `'cubic-bezier(0.2, 0.8, 0.2, 1)'` | CSS easing of the transform transition. |
| `blur` | `number` | `19` | `feGaussianBlur.stdDeviation` of the gooey filter. |
| `alpha` | `number` | `29` | Alpha multiplier in the color matrix; higher feels stickier. |
| `alphaOffset` | `number` | `-10` | Alpha offset in the color matrix. |

### Events

| Event | Params | Description |
|------|------|------|
| `change` | `(v: boolean)` | Fires when a trigger requests a new active state; never while disabled. |
| `update:modelValue` | `(v: boolean)` | Fires with `change`; controlled consumers must write it back. |

### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `a` | - | First shape; sits on the negative side of `direction` while inactive. |
| `b` | - | Second shape; sits on the positive side of `direction` while inactive. |

## Overview

- A boolean `modelValue` makes it controlled; otherwise it keeps internal state. Both modes emit.
- `hover` activates on pointer enter and deactivates on leave; `click` toggles on a root click; `manual` ignores the pointer.
- With `trigger="click"`, the root has `role="button"`: it takes Tab focus, toggles on Enter / Space, and reflects state in `aria-pressed`.
- While `disabled`, the root is `pointer-events: none` and interactions emit nothing.
- Non-finite `alpha` / `alphaOffset` values fall back to safe color-matrix values.
- Slots render inside the filtered layer; slotted controls own their labels, focus, and keyboard semantics.

## Technologies

- Each shape moves by `transform`, and an SVG filter (`feGaussianBlur` + `feColorMatrix`) on the wrapper melts the overlap into one form.
- Source: `packages/tuffex/packages/components/src/fusion/`.

<TuffDocSourceLink />
