Vanilla Disintegratev1.6.1
EN
On this page

remove() and restore() are two separate operations. The library plays the animation. Where the element goes, and what that means for your app, is yours to decide.

Remove an element

Removal measures the element while it is still on the page, then detaches it. The animation plays in its own overlay, by which point the real node is already out of the layout.

const operation = effects.remove(element, {
  retain: false,
  layout: true,
});

const result = await operation.finished;

retain defaults to false, so the library keeps no DOM reference after removal. layout optionally animates affected siblings into their new positions.

Restore an inserted element

Restoration means “animate this connected element into view.” Insert the node first, in the exact destination chosen by the application.

container.append(element);

const operation = effects.restore(element);

await operation.finished;

The element must be connected and have non-zero geometry. The library hides it synchronously, measures its new final position, captures it there, runs the restore phase, and then reveals the original node.

Concealment uses a paused Web Animation rather than an inline style, so it survives class and style changes during the effect. One consequence follows from the CSS cascade: an !important author declaration outranks animations, so a rule such as .card { opacity: 1 !important } on a restore target leaves the live element visible under the particle layer. Removing the !important from the target avoids it, as does restoring a wrapper that does not carry the declaration.

Animate a new element appearing

You can use restore() to animate a new element appearing. Add it to the DOM first, then call restore(); there is no need to call remove() beforehand.

const message = document.createElement('aside');
message.textContent = 'Created just now';

notifications.append(message);
effects.restore(message, { preset: 'vapor' });

Operation handle

Both methods return a synchronous handle:

const operation = effects.remove(element);

operation.operation; // 'remove'
operation.removalId; // RemovalId | null
operation.cancel();

const result = await operation.finished;
result.status; // 'completed' | 'cancelled' | 'skipped' | 'rejected'

The handle does not retain the DOM element after the operation settles.

Cancellation is visual only

cancel() stops animation and sound. It does not reverse the content action: a removed element stays removed, and a restoring element becomes visible.

That way a cancel button, or a view that unmounts mid-animation, cannot quietly undo a change your app already made.

A second operation requested for the same element while the first is active does not change the DOM or allocate a retention ID. Its finished promise waits for the current owner to settle and then resolves as rejected, so awaiting the handle cannot end the element’s active lifecycle early.

Errors do not block content

If capture, audio, or a custom effect fails, removal still detaches the node and restoration still reveals it. The error reaches onError, and the result status is skipped when no visual could run.

const effects = new Disintegrator({
  preset: 'dust',
  onError(error, context) {
    console.error(context.operation, error);
  },
});
Edit this page on GitHub