JSFiddle - React, Tailwind, and code Playground

by phloe

HTML

<main>
<h1>Front-end strategies</h1>
<output form="strategies">
	<figure>
		<svg viewBox="0 0 700 600" width="100%" height="100%">
			<defs>
				<mask id="mask_features">
					<rect x="100" y="100" width="500" height="800" fill="#FFF" />
					<rect x="100" y="100" width="500" height="400" fill="#404040" transform="translate(0 -100)" id="mask_features_active"/>
				</mask>
				<mask id="mask_polyfill">
					<rect x="100" y="100" width="500" height="800" fill="#000" />
					<rect x="100" y="100" width="500" height="400" fill="#404040" transform="translate(0 300)" id="mask_polyfill_active" />
				</mask>
			</defs>
			<text x="100" y="90" text-anchor="start">Features</text>
			<text x="600" y="520" text-anchor="end">Support</text>
			<text x="610" y="110" text-anchor="start" fill="#E8742D" id="baseline_text">Baseline</text>
			<text x="90" y="110" text-anchor="end" fill="#E8742D" id="polyfill_text">Polyfill</text>
			<rect x="100" y="100" width="500" height="400" fill="#E8742D" mask="url(#mask_polyfill)" id="polyfill" />
			<path d="M200,500 v-100 h100 v-100 h100 v-100 h100 v-100 h100 v400 z" fill="#333333" mask="url(#mask_features)" id="features" />
			<path d="M100.5,100 v399.5 h499.5" stroke-width="1" stroke="#000" fill="transparent" id="axes" />
			<path d="M100,499.5 h99.5 v-99 h100 v-100 h100 v-100 h100 v-100 h100" stroke-width="1" stroke="#E8742D" fill="transparent" id="baseline" />
		</svg>
		<figcpation>
			
		</figcpation>
	</figure>
</output>

<form id="strategies"></form>

</main>

SCSS

html {
	font-family: -apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande", sans-serif;
}

main {
	max-width: 700px;
	margin: 40px auto;
	padding: 0 20px;
}

h1 {
	text-transform: uppercase;
	font-weight: bold;
	text-align: center;
	font-size: 42px;
	@media (max-width: 720px) {
		font-size: calc((42/720) * 100vw);
	}
}

figure {
	margin: 0;
}

svg text {
	text-transform: uppercase;
	font-size: 14px;
}

form {
	padding: 0 100px;
	@media (max-width: 720px) {
		padding: 0 calc((100/720) * 100vw);
	}
}

label span {
	text-transform: uppercase;
	display: block;
	font-size: 14px;
	@media (max-width: 720px) {
		font-size: calc((14/720) * 100vw);
	}
}
label input[type="range"] {
	width: 100%;
}
label input + span {
	display: inline;
}

#mask_polyfill_active,
#mask_features_active,
#baseline_text,
#polyfill_text {
	_transition: .1s transform ease-in-out;
}

JavaScript

var levels = 4;

function updateGraph (baseValue, polyValue) {
	mask_features_active.setAttribute("transform", `translate(0 -${baseValue * 100})`);
	mask_polyfill_active.setAttribute("transform", `translate(0 ${(levels - polyValue) * 100})`);
	baseline_text.setAttribute("transform", `translate(0 ${((levels - baseValue) / levels) * (levels * 100 - 10) })`);
	polyfill_text.setAttribute("transform", `translate(0 ${((levels - polyValue) / levels) * (levels * 100 - 10) })`);
	baseline.setAttribute("d", `
		M100,${(levels - polyValue) * 100 + 100 - (polyValue ? 0 : 0.5)}
		h${(polyValue + 1 ) * 100 + (baseValue < levels ? 0.5 : 0)}
		${ "v-100 h100 ".repeat(baseValue - polyValue) }
		${ (baseValue < levels) ? `h${ (levels - baseValue) * 100 }` : "" }
	`);
}





var inputs = {
	baseline: { value: 2, min: 0, max: levels, step: 1, rel: { key: "polyfill", type: "max" } },
	polyfill: { value: 0, min: 0, max: levels, step: 1, rel: { key: "baseline", type: "min" } }
};

var form = document.querySelector("form");

Object.keys(inputs).forEach(function (key) {
	var data = inputs[key];
	var label = document.createElement("label");
	var span = document.createElement("span");
	span.textContent = `${key[0].toUpperCase()}${key.slice(1)}: `;
	var input = document.createElement("input");
	input.value = data.value;
	input.min = data.min;
	input.max = data.max;
	input.step = data.step;
	input.type = "range";
	
	input.oninput = inputUpdate;
	data.input = input;
	
	function inputUpdate (event) {
		var value = parseFloat(input.value, 10);
		if (data.value !== value) {
			data.value = value;
			const {
				rel: {
					key: relKey, type
				} = {}
			} = data;
			if (relKey) {
				var rel = inputs[relKey];
				var relVal = rel.value;
				if (type === "min") {
					relVal = Math.max(value, relVal);
				}
				else if (type === "max") {
					relVal = Math.min(value, relVal);
				}
				if (relVal !== rel.value) {
					rel.value = relVal;
					rel.input.value = relVal;
				}
			}
			if (event)...