Code — how this page is built

Under the hood

The actual source of the components on this page, read straight from the repo. Copy it, read it, or open it on GitHub.


ColorTestGameview on GitHub ↗

Generates an HSL base + one lightness-shifted tile per round; the shift narrows and the grid grows with the level. Best level persisted to localStorage.

'use client';

import * as React from 'react';

import { Win98Button } from '@/components/ui/win-98-button';

const KEY = 'kaspirius:color-test:best';

function makeRound(level: number) {
  const size = Math.min(2 + Math.floor(level / 2), 6); // 2x2 → 6x6
  const n = size * size;
  const odd = Math.floor(Math.random() * n);
  const h = Math.floor(Math.random() * 360);
  const s = 55 + Math.floor(Math.random() * 25);
  const l = 45 + Math.floor(Math.random() * 20);
  const delta = Math.max(3, 42 - level * 3); // lightness gap shrinks
  const base = `hsl(${h} ${s}% ${l}%)`;
  const odds = `hsl(${h} ${s}% ${l + (Math.random() < 0.5 ? delta : -delta)}%)`;
  return { size, n, odd, base, odds };
}

export function ColorTestGame() {
  const [level, setLevel] = React.useState(1);
  const [round, setRound] = React.useState(() => makeRound(1));
  const [over, setOver] = React.useState(false);
  const [best, setBest] = React.useState(0);

  React.useEffect(() => {
    setBest(Number(localStorage.getItem(KEY)) || 0);
    setRound(makeRound(1));
  }, []);

  const pick = (i: number) => {
    if (over) return;
    if (i === round.odd) {
      const nl = level + 1;
      setLevel(nl);
      setRound(makeRound(nl));
    } else {
      setOver(true);
      setBest((b) => {
        const nb = Math.max(b, level);
        localStorage.setItem(KEY, String(nb));
        return nb;
      });
    }
  };

  const restart = () => {
    setLevel(1);
    setRound(makeRound(1));
    setOver(false);
  };

  return (
    <div className="flex flex-col items-center gap-6">
      <div className="font-mono text-sm tracking-wide opacity-75">
        {over ? `spotted ${level - 1} — your eyes gave out` : `level ${level}`}
      </div>

      <div
        className="grid gap-1.5"
        style={{ gridTemplateColumns: `repeat(${round.size}, 1fr)`, width: 'min(86vw, 420px)' }}
      >
        {Array.from({ length: round.n }, (_, i) => (
          <button
            key={i}
            type="button"
            onClick={() => pick(i)}
            disabled={over}
            aria-label={i === round.odd ? 'odd one' : 'swatch'}
            className="aspect-square rounded-md transition-transform active:scale-95"
            style={{ background: i === round.odd ? round.odds : round.base }}
          />
        ))}
      </div>

      {over ? (
        <Win98Button onClick={restart} className="h-10 min-w-32 px-7 text-sm">
          Try again
        </Win98Button>
      ) : (
        <div className="font-mono text-[11px] uppercase tracking-[0.12em] opacity-50">
          tap the odd colour out
        </div>
      )}
      <div className="font-mono text-[11px] uppercase tracking-[0.12em] opacity-50">best level {best}</div>
    </div>
  );
}
↖ kaspirius