JSFiddle - React, Tailwind, and code Playground

by Chris Ball

HTML

<div id="test">KLIK DIS</div>

CSS

#test {
	background-color: yellow;
	height: 50px;
	width: 50px;
}

TypeScript

type ruleset = { [key: string]: string }
type rulesets = ruleset[]

let rulesets: rulesets = [
	{
		duration: "2000ms",
		backgroundColor: "red",
		height: "100px",
		width: "100px",
	},
	{
		duration: "200ms",
		backgroundColor: "blue",
		height: "50px",
		width: "200px",
	},
]

function prepareToAnimate(el: HTMLElement, ruleset: ruleset) {
	let properties = Object.keys(ruleset)
		.filter((rule) => rule !== "duration")
		.map((rule) => rule.replace(/([A-Z])/g, "-$1").toLowerCase())
		.join(", ")
	el.style.transitionDuration = ruleset.duration
	el.style.transitionProperty = properties
}

function animate(el: HTMLElement, ruleset: ruleset) {
	let { duration: _, ...styles } = ruleset
	Object.assign(el.style, styles)
}

function doThing(selector: string, rulesets: rulesets) {
	let el = document.querySelector(selector) as HTMLElement
	function doTheNextOne() {
		el.removeEventListener("transitionend", doTheNextOne)
		rulesets.push(rulesets.shift()!)
		prepareToAnimate(el, rulesets[0])
		animate(el, rulesets[0])
	}
	el.addEventListener("transitionend", doTheNextOne)

	requestAnimationFrame(() => prepareToAnimate(el, rulesets[0]))
	requestAnimationFrame(() => animate(el, rulesets[0]))
}

let test = document.querySelector("#test") as HTMLElement
test.addEventListener("click", () => doThing("#test", rulesets))