{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "spinner", "title": "Spinner", "description": "An inline loading spinner with semantic colour and size variants.", "dependencies": [ "clsx", "tailwind-merge" ], "registryDependencies": [ "https://ui.digital.nsw.gov.au/registry/r/theme.json" ], "files": [ { "path": "src/components/spinner.tsx", "content": "'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nconst theme = {\n size: {\n xs: 'h-3 w-3',\n sm: 'h-4 w-4',\n md: 'h-6 w-6',\n lg: 'h-8 w-8',\n xl: 'h-10 w-10',\n },\n color: {\n primary: 'fill-primary-800 text-grey-400',\n accent: 'fill-accent-600 text-grey-400',\n white: 'fill-white text-white/30',\n // Inherit the surrounding text colour (e.g. inside a Button, where the\n // text colour varies per variant/colour). The arc uses currentColor at\n // full strength; the track is the same colour dimmed via opacity on the\n // first , so the two-tone effect works from a single hue.\n current: 'fill-current text-current [&>path:first-child]:opacity-25',\n },\n}\n\ntype SpinnerProps = {\n /** Applied to the outer status element, like every other spread prop. */\n className?: string\n /** Applied to the inner svg (sizing/colour live there). */\n svgClassName?: string\n size?: keyof typeof theme.size\n color?: keyof typeof theme.color\n /**\n * Accessible name announced for the `role=\"status\"` element. Defaults to\n * \"Loading\"; pass an empty string to suppress when surrounding content\n * already conveys the busy state (e.g. inside a Button with a label).\n */\n label?: string\n} & React.HTMLAttributes & {\n ref?: React.Ref\n }\n\nfunction Spinner({\n className,\n svgClassName,\n size = 'md',\n color = 'primary',\n label = 'Loading',\n ref,\n ...props\n}: SpinnerProps) {\n // An empty label suppresses the live region entirely: a `role=\"status\"`\n // element with no text content is an empty, redundant live region (e.g. when\n // the Spinner sits inside a Button whose own `aria-busy` conveys the state).\n // A consumer-supplied `role` in `...props` still wins, as before.\n const labelled = label !== ''\n return (\n \n \n )\n}\n\nexport { Spinner }\nexport type { SpinnerProps }\n", "type": "registry:ui", "target": "components/spinner.tsx" }, { "path": "src/lib/utils.ts", "content": "import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n", "type": "registry:lib", "target": "lib/utils.ts" } ], "type": "registry:ui", "meta": { "nswdsVersion": "5.1.0" } }