WebberUI

Chinese Zodiac Wheel

A twelve-animal zodiac ring — rotate to select, and the chosen sign expands into a card of years and traits.

A twelve-animal Chinese zodiac SVG ring: drag or click to rotate it, and on release a spring snaps it to a sector. The sign the top pointer lands on expands an information card in the center (the three most recent years, its element, and personality keywords), and you can also enter a birth year to jump to the matching sign automatically.

Loading preview…
npx shadcn@latest add https://webberui.com/r/chinese-zodiac-wheel.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

0
300
<ChineseZodiacWheel />

Installation

npx shadcn@latest add https://webberui.com/r/chinese-zodiac-wheel.json

Or, once registries are configured in components.json, install it as @webberui/chinese-zodiac-wheel.

Usage

import { ChineseZodiacWheel } from "@/components/ui/chinese-zodiac-wheel";

// Uncontrolled: 「馬」 (Horse, index 6) selected by default
<ChineseZodiacWheel
  defaultValue={6}
  onChange={(index, zodiac) => console.log(index, zodiac.name)}
/>

The zodiac data (earthly branches, elements, personality keywords) and the year conversion table are both built into the component, so no external request is needed. The year conversion is based on 2020 (庚子, the Year of the Rat), and REFERENCE_YEAR = 2026 is the upper bound for "the three most recent years" — to show newer years later on, adjust that constant. The component also exports the helper function yearToZodiacIndex(year) for converting a Gregorian year into a zodiac index outside the component.

Note: the zodiac sign actually changes on the first day of the first lunar month, while the component approximates it with the Gregorian year (for demonstration purposes) — people born in January or February should correct for the lunar year.

Props

PropTypeDefaultDescription
valuenumberControlled selected zodiac index (0=Rat, 1=Ox … 11=Pig)
defaultValuenumber0Default index in uncontrolled mode
onChange(index: number, zodiac: ZodiacInfo) => voidCallback when the selected sign changes
sizenumber300Wheel diameter (px)
showYearInputbooleantrueWhether to show the birth year lookup input
classNamestringForwarded to the outer container

Accessibility

  • The wheel is a role="slider" and is keyboard focusable, with the arrow keys stepping between signs and aria-valuetext reading out the current sign, its earthly branch, and its element
  • When the user has "reduce motion" enabled at the system level, the spring rotation and the card transition are disabled and the switch completes immediately
  • The sector SVG is hidden from assistive technology (aria-hidden); the semantics are carried entirely by the slider attributes
  • The birth year field is a standard input; an invalid format sets aria-invalid and shows a hint through role="alert"

On this page