feat: Simplification of UI and icons creation
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// Quick feedback animations (0.15 to 0.25 s), so buying feels immediate.
|
||||
// All of them are plain CSS animations restarted from here; users who prefer
|
||||
// reduced motion get none (see components.css).
|
||||
|
||||
const FALLBACK_MS = 400; // clean-up if the browser never fires animationend
|
||||
|
||||
/** Restart a one-shot CSS animation class on an element. */
|
||||
function play(el, className) {
|
||||
if (!el) return;
|
||||
el.classList.remove(className);
|
||||
void el.offsetWidth; // let the browser notice the class was removed
|
||||
el.classList.add(className);
|
||||
const done = () => el.classList.remove(className);
|
||||
el.addEventListener('animationend', done, { once: true });
|
||||
setTimeout(done, FALLBACK_MS);
|
||||
}
|
||||
|
||||
/** A block that was just bought: a quick pop and an accent glow. */
|
||||
export const pop = (el) => play(el, 'fx-pop');
|
||||
|
||||
/** A number that just changed: a quick bump. */
|
||||
export const bump = (el) => play(el, 'fx-bump');
|
||||
|
||||
/** A resource that was just spent: a quick flash. */
|
||||
export const spend = (el) => play(el, 'fx-spend');
|
||||
|
||||
/**
|
||||
* A short "+3" that rises from the middle of `anchor` (or from a point) and fades.
|
||||
* `at` = { x, y } in viewport coordinates, used when given instead of an element.
|
||||
* `tone` ('good' | 'bad') colours it green or red; by default it takes the accent colour.
|
||||
*/
|
||||
export function floater(anchor, text, at, tone) {
|
||||
const rect = at ? { left: at.x, top: at.y, width: 0 } : anchor?.getBoundingClientRect();
|
||||
if (!rect) return;
|
||||
const el = document.createElement('span');
|
||||
el.className = tone ? `floater floater--${tone}` : 'floater';
|
||||
el.textContent = text;
|
||||
el.style.left = `${rect.left + rect.width / 2}px`;
|
||||
el.style.top = `${rect.top}px`;
|
||||
document.body.append(el);
|
||||
el.addEventListener('animationend', () => el.remove(), { once: true });
|
||||
setTimeout(() => el.remove(), FALLBACK_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop a bought block, float a label above it and flash what was spent (the funds
|
||||
* in the top bar unless `spentId` says otherwise, or is null for no flash).
|
||||
*/
|
||||
export function purchased(el, label, spentId = 'v-funds') {
|
||||
pop(el);
|
||||
floater(el, label);
|
||||
if (spentId) spend(document.getElementById(spentId));
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user