Frames

This is one TSX file and what it renders. Hover a row, a bar or a pill, and the lines that made it light up.

design/frames/beans/frame.tsx
1import { motion } from "motion/react"
2import { useState } from "react"
3
4const beans = [
5 { name: "yirgacheffe", kg: 2.4, cups: 210 },
6 { name: "huila", kg: 3.1, cups: 128 },
7 { name: "sidamo", kg: 1.6, cups: 174 },
8]
9
10export default function Beans() {
11 const [by, setBy] = useState("cups")
12 const of = (b) => (by === "per kg" ? b.cups / b.kg : b[by])
13 const max = Math.max(...beans.map(of))
14 return (
15 <div className="w-[460px] rounded-lg border p-6">
16 {["kg", "cups", "per kg"].map((f) => (
17 <button key={f} onClick={() => setBy(f)}>{f}</button>
18 ))}
19 {beans.map((b) => (
20 <div key={b.name} className="mt-6 flex items-center gap-4">
21 <span className="w-[120px] text-muted">{b.name}</span>
22 <span className="h-1.5 w-[200px] rounded-[2px] bg-raised">
23 <motion.span
24 className="block h-full origin-left rounded-[2px] bg-text"
25 animate={{ scaleX: of(b) / max }}
26 />
27 </span>
28 <span className="ml-auto tabular-nums">{+of(b).toFixed(1)}</span>
29 </div>
30 ))}
31 </div>
32 )
33}
beans
yirgacheffe210
huila128
sidamo174
Switch the pill and the bars resize against the new largest value.Privacy & cookiesState, motion and arithmetic, all running in the page you are reading.