Goal: Create a "Gravity" radio group animation.
Visual behavior: A radio group with 3 options. Each radio indicator is a 22×22px circle with an orange (#f97316) border. On selection, an orange ball drops from above (translateY -16px → 0) with a gravity ease-in, squishes on landing (scaleX 1.3, scaleY 0.7), bounces up slightly, then settles — all via a single CSS @keyframes animation over 600ms. The ball has an orange radial gradient and glow box-shadow. Each selection increments a dropKey counter to remount the ball div and restart the animation.
Technique: React useState tracks selected option and dropKey. The ball is conditionally rendered inside the selected indicator and uses the key prop (dropKey) to force remount and restart the CSS animation. Inline styles drive the outer ring border-color and label color transitions. No library dependencies.
Accessibility: Hidden native <input type="radio"> per option, shared name attribute. Keyboard-navigable. Drop animation skipped under prefers-reduced-motion.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
Return a single self-contained component. Do not introduce dependencies beyond what I've listed.
Paste into Claude, ChatGPT, or Cursor. Edit YOUR_STACK /
YOUR_STYLING / YOUR_CONSTRAINTS before sending.