AnimationDirectiveCSSAdded in v15.7

Click Sparks

A ring of short spark strokes bursts out from the point a button or link is clicked, flies a short way, shrinks and fades, all within half a second. The click itself is never touched: a routerLink or a plain href navigates as it did.

Installation

Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.

import { Component } from '@angular/core';
import { WrClickSparks } from 'ngwr/animations/click-sparks';

@Component({ imports: [WrClickSparks] })
export class MyComponent {}

Basic

Put wrClickSparks on the element that takes the click. A burst is one aria-hidden layer of zero size in document.body, fixed at the click's client coordinates, so no ancestor clips it and a button inside a transformed hero measures from the viewport all the same. Several quick clicks make several bursts; at most four are alive at once, and the ring turns a golden angle from one burst to the next, so no two consecutive bursts put a stroke in the same place.

<a wr-btn outlined size="lg" routerLink="/docs" wrClickSparks>Get started</a>

Strokes

The directive's own value is how many strokes a burst has, spread evenly round the ring. Unset, eight. The strokes scale with the host's font size: a large hero button throws longer, farther sparks than a small one.

<button wr-btn outlined type="button" wrClickSparks="12">Twelve strokes</button>

Colour

The strokes paint in the host's own text colour, read at the click. On a filled button that colour is the fill's -contrast, unreadable off the button: set --wr-click-sparks-color on the host to a role instead, and the layer takes it. The length, distance and width of a stroke are the layer's own hooks, in em of the host.

<button wr-btn type="button" wrClickSparks style="--wr-click-sparks-color: var(--wr-color-primary)">
  Filled
</button>

Accessibility

PartBehaviour
Keyboard An activation from Enter or Space is a click with detail === 0: the burst comes from the host's centre. The listener is passive and prevents nothing.
Screen readersEach burst's layer is aria-hidden, holds no text and takes no pointer.
Reduced motion Under prefers-reduced-motion: reduce nothing plays; under forced-colors: active nothing listens, since the stylesheet paints no stroke. A preference that flips mid-burst leaves an invisible layer, which a timer takes out.
ServerNothing runs: the listener is added after the first render, in the browser only.

API

NameDescriptionTypeDefault
wrClickSparksHow many strokes one burst has. Written as the directive's own value: wrClickSparks="10". Unset or empty, {@link CLICK_SPARKS_COUNT}.numberCLICK_SPARKS_COUNT

CSS variables

Set these on the element itself, with a rule more specific than its Declared on selector. In a global stylesheet, put a class of yours on an ancestor it really has: <body> for an overlay panel, which renders outside your markup. In a component stylesheet the selector alone works, but only for an element in that component's own template. A value on a wrapper or :root is shadowed, because ngwr/animations/click-sparks declares each default on its own element.

VariableDefaultDeclared on
--wr-click-sparks-duration480ms.wr-click-sparks and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes
--wr-click-sparks-easevar(--wr-ease-out).wr-click-sparks
--wr-click-sparks-from0.3em.wr-click-sparks
--wr-click-sparks-length0.55em.wr-click-sparks
--wr-click-sparks-to1.7em.wr-click-sparks
--wr-click-sparks-widthmax(2px, 0.12em).wr-click-sparks
--wr-click-sparks-x0px.wr-click-sparks and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes
--wr-click-sparks-y0px.wr-click-sparks and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes

See also