ball.mp4
A pinball-style reasoning effort picker implemented as a zero-dependency Web Component. A glowing ball moves through an elastic peg field, settles into one of six effort levels, and updates the read-only result meter only after landing.
This project recreates the interface shown in this original X post as an independently implemented Web Component.
The original concept and visual design belong to their respective creator(s). This repository contains only the independent implementation.
- Fixed-step gravity simulation at 240 Hz.
- Elastic circle collisions across 27 pegs.
- Contact-synchronous lavender peg halos and an SVG trail of the real ball trajectory.
- Preserved tangential momentum, repeat contacts, and side-wall rebounds.
- Six read-only result levels: Auto, Light, Medium, High, Extra High, and Ultra.
- Responsive layout with a
prefers-reduced-motionfallback. - No runtime dependencies and no build step.
Import the component module and add <ball-model-picker> to the page:
<script type="module" src="./src/ball-model-picker.js"></script>
<ball-model-picker open></ball-model-picker>The open boolean attribute controls whether the panel is expanded:
const picker = document.querySelector('ball-model-picker');
picker.toggleAttribute('open', true);
console.log(picker.value);
// { index: 2, id: 'medium', label: 'Medium' }| Attribute | Description |
|---|---|
open |
Boolean attribute that expands or collapses the picker panel. |
| Property | Description |
|---|---|
value |
Returns { index, id, label } for the committed result. |
The component dispatches a bubbling, composed change event after the ball settles:
picker.addEventListener('change', (event) => {
console.log(event.detail);
// { index, id, label, phase: 'landed' }
});- Press Again to release a new ball.
- The existing result remains committed while the ball is in play.
- Real peg contacts drive the ball path; the destination is not selected in advance.
- The close button collapses the panel, and the compact trigger reopens it.
- Native button semantics provide keyboard activation and focus treatment.
- Reduced-motion users receive an immediate weighted result without the traversal effects.
No dependencies or build step are required. Start any static file server from the repository root:
python3 -m http.server 4173Then open http://127.0.0.1:4173.
Run the automated physics and route checks before submitting changes:
npm test| Path | Purpose |
|---|---|
src/ball-model-picker.js |
Custom Element behavior and encapsulated Shadow DOM styles. |
src/pinball-physics.js |
Fixed-step gravity, circle collisions, and pocket settling. |
src/plinko-route.js |
Weighted result fallback used by reduced-motion mode. |
tests/ |
Deterministic physics and route tests. |
index.html |
Minimal local demo page. |
Issues and pull requests are welcome. Read CONTRIBUTING.md before contributing.
This is an unofficial, independent interface recreation. It is not affiliated with or endorsed by the original creator(s), X, or OpenAI. Names and labels in the component are used only to demonstrate the interaction.
MIT © 2026 zanwei