1import { LoaderCircleIcon } from "lucide-react";
2import { cva, type VariantProps } from "class-variance-authority";
3import { observeVisibleAnimation } from "~/lib/visibleAnimation";
4import { cn } from "~/lib/utils";
5
6// No default size: inside a Button the parent's svg rule sizes the glyph.
7const spinnerVariants = cva("motion-safe:visible-animate-spin", {
8 variants: {
9 size: {
10 xs: "size-3",
11 sm: "size-3.5",
12 md: "size-4",
13 lg: "size-5",
14 },
15 tone: {
16 current: "",
17 muted: "text-muted-foreground",
18 },
19 },
20 defaultVariants: { tone: "current" },
21});
22
23function Spinner({
24 className,
25 size,
26 tone,
27 ...props
28}: React.ComponentPropsWithoutRef<typeof LoaderCircleIcon> & VariantProps<typeof spinnerVariants>) {
29 return (
30 <LoaderCircleIcon
31 aria-label="Loading"
32 ref={observeVisibleAnimation}
33 className={cn(spinnerVariants({ size, tone }), className)}
34 role="status"
35 {...props}
36 />
37 );
38}
39
40export { Spinner };