2.5 KiB
Spinner Variants
Purpose
spinnerVariants is the cva config that powers the <Spinner> chassis component. It exposes a size axis (sm / default / lg) using Tailwind's size-* shorthand so the rendered diameter changes in lockstep with width and height. The base classes establish the circular shape, the transparent top-edge that creates the "spinning arc" illusion, and the motion-safe:animate-spin gating that disables the rotation for users with prefers-reduced-motion: reduce.
The variants module sits in its own file so an ejected source copy under npx shadcn@latest add @suaveplan/spinner keeps the cva config separate from the component logic, matching the upstream shadcn convention and easing per-project customisation without touching the JSX.
Features
- Single
sizeaxis with three rungs (sm16px,default20px,lg32px) using Tailwindsize-*. - Border thickness scales with size — 2px for
sm/default, 3px forlg— keeping the arc visually proportional. motion-safe:animate-spin+motion-reduce:animate-noneso reduced-motion users see a static circle.- Border colour inherits via
border-currentso consumers can recolour the spinner with a singletext-*utility.
Usage: Basic Example
import { spinnerVariants } from "@suaveplan/react-ui";
const small = spinnerVariants({ size: "sm" });
const large = spinnerVariants({ size: "lg" });
Usage: Advanced Example
import { cva } from "class-variance-authority";
import { spinnerVariants } from "@suaveplan/react-ui";
const customSpinner = cva(
[spinnerVariants({ size: "default" }), "text-emerald-500"].join(" ")
);
API Reference
spinnerVariants(opts?)
| Option | Type | Default | Description |
|---|---|---|---|
size |
"sm" | "default" | "lg" |
"default" |
Diameter — uses Tailwind size-* to set width and height together. |
Returns the merged class string.
Implementation Notes
- The
border-t-transparentrule is what creates the "missing arc" illusion that reads as motion when the element rotates. Without it the spinner would be a solid ring with no visual rotation. text-foreground/60is applied at the cva level so the spinner renders with a subtle muted colour by default. Consumers override with anytext-*utility (text-primary,text-emerald-500, etc.).- The spinner deliberately does not register
display-related classes —inline-blockis hard-coded so the spinner sits inline with adjacent text inside a Button without being affected by the Button'sflexcontext.