npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-wagon-wheel-picker

v0.1.7

Published

A playful, interactive radial selection component for React - perfect for kids' apps, games, and fun interfaces

Readme

Wagon Wheel Picker

A playful, interactive radial selection component for React. Perfect for kids' apps, game UIs, and fun, lighthearted interfaces. Display options in a circular wagon wheel layout with bouncy animations and delightful hover effects.

npm version npm downloads license

Storybook Demo

Wagon Wheel Picker in action

✨ Features

  • Playful radial layout - Options arranged in a circular wagon wheel pattern
  • Bouncy animations - Springy, playful transitions powered by Framer Motion
  • Fully customizable - Themeable colors, sizing, and behavior
  • Framework flexible - Works with Next.js Image or standard img tags
  • Responsive - Auto-detects mobile or accepts manual size control
  • TypeScript support - Full type definitions included
  • Lightweight - Minimal dependencies

Perfect For

  • Kids' apps and educational games
  • Playful e-commerce product pickers
  • Character or avatar selectors
  • Game lobbies and casual game UIs
  • Any interface that benefits from a fun, whimsical touch

📦 Installation

npm install react-wagon-wheel-picker framer-motion

Note: Framer Motion is required for the bouncy, playful animations that make this component fun

Bundle Size Optimization: This package uses Framer Motion's lightweight m component with LazyMotion and domAnimation features. When you use this package, framer-motion will only add approximately 15KB to your bundle (compared to ~50KB+ if you used the full framer-motion library directly).

🚀 Quick Start

Basic Usage

import { WagonWheelPicker } from 'react-wagon-wheel-picker';

function MyComponent() {
  const [selected, setSelected] = useState('option1');

  const options = [
    { key: 'option1', label: 'Option 1', image: '/images/option1.png' },
    { key: 'option2', label: 'Option 2', image: '/images/option2.png' },
    { key: 'option3', label: 'Option 3', image: '/images/option3.png' },
  ];

  return (
    <WagonWheelPicker
      options={options}
      value={selected}
      onClick={setSelected}
    />
  );
}

With Next.js Image Component

import Image from 'next/image';
import { WagonWheelPicker } from 'react-wagon-wheel-picker';

function MyComponent() {
  return (
    <WagonWheelPicker
      options={options}
      value={selected}
      onClick={setSelected}
      ImageComponent={Image}
    />
  );
}

Object Format (Alternative)

const options = {
  beef: { label: 'Beef', image: '/beef.png' },
  chicken: { label: 'Chicken', image: '/chicken.png' },
  pork: { label: 'Pork', image: '/pork.png' },
};

<WagonWheelPicker options={options} value="beef" onClick={handleClick} />

Simple String Format

const options = {
  option1: '/images/option1.png',
  option2: '/images/option2.png',
  option3: '/images/option3.png',
};

<WagonWheelPicker options={options} value="option1" onClick={handleClick} />

With Different Center Images

const options = [
  {
    key: 'beef',
    label: 'Beef',
    image: '/beef-small.png',      // Image shown in wedge
    centerImage: '/beef-large.png' // Different image shown in center when selected
  },
  {
    key: 'chicken',
    label: 'Chicken',
    image: '/chicken-small.png',
    centerImage: '/chicken-large.png'
  },
];

<WagonWheelPicker options={options} value="beef" onClick={handleClick} />

Interactive Examples

View Live Storybook Demo - Explore all features interactively!

Or run locally:

npm run storybook

This opens an interactive playground at http://localhost:6006 with:

  • 15+ example stories showcasing different use cases
  • Live controls to experiment with props and themes
  • Multiple themes (dark, colorful, pastel)
  • Different sizes and option counts
  • Mobile vs Desktop comparison
  • Documentation for all props and features

To build a static Storybook:

npm run build-storybook

🎨 Customization

Custom Theme

const customTheme = {
  tertiaryBackground: '#e3f2fd',  // Selected option background
  surfaceBackground: '#ffffff',    // Unselected option background
  tertiary: '#2196f3',             // Selected option border
  border: '#cccccc',               // Unselected option border
  background: '#fafafa',           // Center circle background
  text: '#333333',                 // Center text color
  divider: '#e0e0e0',              // Center circle border
};

<WagonWheelPicker
  options={options}
  theme={customTheme}
/>

Custom Sizing

<WagonWheelPicker
  options={options}
  size={500}              // Custom size in pixels
  innerPercent={0.35}     // Inner radius (35% of total)
  outerPercent={0.95}     // Outer radius (95% of total)
/>

Custom Center Text

<WagonWheelPicker
  options={options}
  centerText={['PICK', 'YOUR', 'FLAVOR']}
  fontFamily="'Arial', sans-serif"
/>

📖 API Reference

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | options | Array \| Object | required | Options to display (min 3, max 8 recommended) | | value | string | undefined | Currently selected option key | | onClick | function | undefined | Callback when option is clicked: (key: string) => void | | theme | object | Default theme | Theme object for colors | | size | number | 420 / 320 | Size in pixels (desktop/mobile) | | isMobile | boolean | Auto-detected | Force mobile sizing | | innerPercent | number | 0.4 | Inner radius (0-1) | | outerPercent | number | 0.9 | Outer radius (0-1) | | ImageComponent | Component | img | Custom image component | | centerText | string[] | ['SELECT', 'YOUR', 'OPTION'] | Center text lines | | fontFamily | string | 'serif' | Font for center text | | fallbackImage | string | '/fallback.png' | Image when none provided |

Option Format

Array format:

{
  key: string;          // Required: unique identifier
  label?: string;       // Optional: display label
  image?: string;       // Optional: image URL for wedge
  centerImage?: string; // Optional: different image for center circle when selected
}

Object format:

{
  [key: string]: {
    label?: string;
    image?: string;
    centerImage?: string;
  } | string  // or just image URL
}

Theme Format

{
  tertiaryBackground?: string;  // Selected option fill
  surfaceBackground?: string;   // Unselected option fill
  tertiary?: string;            // Selected option border
  border?: string;              // Unselected option border
  background?: string;          // Center circle fill
  text?: string;                // Center text color
  divider?: string;             // Center circle border
}

🎯 Best Practices

  • 3-8 options: The component works best with 3-8 options. Fewer than 3 or more than 8 may look cramped or sparse.
  • Square images: Use square images for best results in the circular layout.
  • Consistent sizing: Keep image dimensions consistent across all options.
  • High contrast: Ensure good contrast between theme colors for accessibility.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT © Reed Black

🐛 Issues

Found a bug? Open an issue

💡 Inspiration

Created for Taco Ninja - a playful recipe randomizer app.