{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"loader","type":"registry:ui","title":"Loader","description":"A small indeterminate indicator in four shapes.","dependencies":["clsx","tailwind-merge"],"registryDependencies":["https://caliperui.site/r/styles.json"],"files":[{"path":"ui/lib/cn.ts","type":"registry:ui","target":"components/ui/lib/cn.ts","content":"import { clsx, type ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n  extend: { theme: { radius: [\"control\", \"surface\", \"overlay\"], shadow: [\"overlay\"] } },\n});\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"},{"path":"ui/loader.tsx","type":"registry:ui","target":"components/ui/loader.tsx","content":"import type { ComponentProps } from \"react\";\nimport { cn } from \"./lib/cn\";\nimport \"./loader.css\";\n\nexport type LoaderVariant = \"spinner\" | \"dots\" | \"bars\" | \"morph\";\n\nconst marks = {\n  dots: 3,\n  bars: 3,\n} as const;\n\nexport function Loader({\n  variant = \"spinner\",\n  size = 20,\n  label = \"Loading\",\n  className,\n  ...props\n}: Omit<ComponentProps<\"span\">, \"children\"> & {\n  variant?: LoaderVariant;\n  size?: number;\n  label?: string;\n}) {\n  const count = variant === \"dots\" || variant === \"bars\" ? marks[variant] : 0;\n  return (\n    <span\n      role=\"status\"\n      aria-label={label}\n      data-slot=\"loader\"\n      data-variant={variant}\n      className={cn(\"inline-flex items-center justify-center text-foreground\", className)}\n      style={{ width: size, height: size }}\n      {...props}\n    >\n      {variant === \"spinner\" && <span data-slot=\"loader-spinner\" />}\n      {variant === \"morph\" && <span data-slot=\"loader-morph\" />}\n      {count > 0 &&\n        Array.from({ length: count }, (_, index) => (\n          <span\n            key={index}\n            data-slot={variant === \"dots\" ? \"loader-dot\" : \"loader-bar\"}\n            style={{ animationDelay: `calc(${index} * var(--delay-stagger))` }}\n          />\n        ))}\n    </span>\n  );\n}\n"},{"path":"ui/loader.css","type":"registry:file","target":"components/ui/loader.css","content":"/* loader.tsx's styles; it imports this file. Edit freely. */\n@layer theme, base, components, utilities;\n\n@layer components {\n  [data-slot=\"loader\"][data-variant=\"dots\"],\n  [data-slot=\"loader\"][data-variant=\"bars\"] {\n    gap: 12%;\n  }\n  [data-slot=\"loader-spinner\"] {\n    width: 100%;\n    height: 100%;\n    border: 2px solid color-mix(in srgb, currentColor 28%, transparent);\n    border-top-color: currentColor;\n    border-radius: 50%;\n    animation: caliper-spin var(--duration-loading) var(--ease-linear) infinite;\n  }\n  [data-slot=\"loader-dot\"] {\n    width: 22%;\n    height: 22%;\n    border-radius: 50%;\n    background: currentColor;\n    animation: caliper-loader-dot var(--duration-loading) var(--ease-in-out) infinite;\n  }\n  [data-slot=\"loader-bar\"] {\n    width: 18%;\n    height: 100%;\n    transform-origin: center bottom;\n    border-radius: var(--radius-control);\n    background: currentColor;\n    animation: caliper-loader-bar var(--duration-loading) var(--ease-in-out) infinite;\n  }\n  [data-slot=\"loader-morph\"] {\n    width: 68%;\n    height: 68%;\n    background: currentColor;\n    animation: caliper-loader-morph var(--duration-loading) var(--ease-settle) infinite;\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    [data-slot=\"loader-spinner\"],\n    [data-slot=\"loader-dot\"],\n    [data-slot=\"loader-bar\"],\n    [data-slot=\"loader-morph\"] {\n      animation: none;\n      transition: none;\n      transform: none;\n    }\n  }\n}\n\n@keyframes caliper-loader-dot {\n  0%,\n  80%,\n  100% {\n    opacity: 0.3;\n    transform: translateY(0);\n  }\n  40% {\n    opacity: 1;\n    transform: translateY(-25%);\n  }\n}\n\n@keyframes caliper-loader-bar {\n  0%,\n  100% {\n    transform: scaleY(0.35);\n  }\n  50% {\n    transform: scaleY(1);\n  }\n}\n\n@keyframes caliper-loader-morph {\n  0%,\n  100% {\n    border-radius: 50%;\n    transform: scale(0.72);\n  }\n  50% {\n    border-radius: var(--radius-control);\n    transform: scale(1);\n  }\n}\n"}],"categories":["feedback"],"meta":{"tier":"free","license":"MIT","family":"feedback","docs":"/docs/components/loader"}}