Floating text
Floating damage numbers for React: text thrown off something as it happens, popping, rising and fading; crits bigger and orange.
Install
# once per project: where @zeroui items come frompnpm dlx shadcn@latest registry add @zeroui=https://zeroui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zeroui/floating-textExamples
Hits, crits and repairs
import { useRef } from "react";import { Button } from "@/components/zero/button";import { FloatingTextLayer, useFloatingText,} from "@/components/zero/floating-text";import { CrateIcon } from "@/components/zero/icons/crate";export default function FloatingTextHits() { const floats = useFloatingText(); // a little scatter, so hits in a row do not stack on one spot const hits = useRef(0); const at = () => { hits.current += 1; return { x: 120 + ((hits.current * 37) % 70) - 35, y: 76 - (hits.current % 3) * 14, }; }; return ( <div className="grid justify-items-center gap-5"> <div className="relative grid h-36 w-60 place-items-center border-(length:--zero-stroke-thin) border-zero-line bg-zero-void"> <CrateIcon className="size-16 text-zero-text-2" /> <FloatingTextLayer floats={floats} /> </div> <div className="flex flex-wrap justify-center gap-3"> <Button size="sm" variant="secondary" onClick={() => floats.spawn({ text: "−18", ...at() })} > Hit </Button> <Button size="sm" variant="secondary" onClick={() => floats.spawn({ text: "−54", kind: "crit", ...at() })} > Critical </Button> <Button size="sm" variant="secondary" onClick={() => floats.spawn({ text: "+30", kind: "heal", ...at() })} > Repair </Button> <Button size="sm" variant="secondary" onClick={() => floats.spawn({ text: "Sealed!", kind: "info", ...at() }) } > Seal </Button> </div> </div> );}Behaviour
useFloatingText() keeps the list; FloatingTextLayer draws it over its positioned parent; spawn() throws one at a point. Each pops, rises and fades on the float transition, then removes itself. damage is plain, crit bigger in the legendary orange with a harder pop, heal green, info the accent.
The layer is decoration and hidden from screen readers: say the real value somewhere they can find it, such as a Gauge. Under reduced motion they fade where they are.
Props
useFloatingText().spawn
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | — | What to show. |
| x / y | number | — | In px from the layer's top-left. |
| kind | "damage" | "crit" | "heal" | "info" | "damage" | Its look. |
FloatingTextLayer
| Prop | Type | Default | Description |
|---|---|---|---|
| floats | ReturnType<typeof useFloatingText> | — | The list to draw. |