{"_id":"@agilek/cli-loaders","_rev":"4-4cf2fa4af775623c64cf7d38ce9a4acf","name":"@agilek/cli-loaders","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@agilek/cli-loaders","version":"1.0.0","keywords":["react","spinner","braille","unicode","animation","loading","loader","cli","terminal"],"author":{"name":"Mike Acler","email":"m@acler.cz"},"license":"MIT","_id":"@agilek/cli-loaders@1.0.0","maintainers":[{"name":"agilek","email":"michal.acler@gmail.com"}],"homepage":"https://github.com/agile/cli-loaders#readme","bugs":{"url":"https://github.com/agile/cli-loaders/issues"},"dist":{"shasum":"024c5b13b6567692ee1c0110cb86347be8d048ae","tarball":"https://registry.npmjs.org/@agilek/cli-loaders/-/cli-loaders-1.0.0.tgz","fileCount":6,"integrity":"sha512-cuoR8CseQND7U8vQXzKAsD3/9DzxOYIgZbLa3n32vCSTCtkzcXhqyky6et/BsfbKYyVLE6choOxvswbq7SDqZg==","signatures":[{"sig":"MEYCIQDIUNbJpm84wtnMKoZ6PQWL59yT/jKxmYI99HP2rubaKwIhAJSbQDlvU0DHuHqBnSZicdupI3Dw1Nu2wVEcP6ooh3JW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46104},"main":"./dist/cli-loaders.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/cli-loaders.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/cli-loaders.js","require":"./dist/cli-loaders.cjs"}},"gitHead":"e016b4ccf6d438dfa4ce2c63738382b5137f250d","scripts":{"dev":"vite","build":"vite build","gen:svgs":"node scripts/gen-svgs.mjs","build:demo":"vite build --config vite.demo.config.ts","prepublishOnly":"npm run build"},"_npmUser":{"name":"agilek","email":"michal.acler@gmail.com"},"repository":{"url":"git+https://github.com/agile/cli-loaders.git","type":"git"},"_npmVersion":"11.6.3","description":"Braille unicode spinners as React decorator components","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","react":"^19.2.4","react-dom":"^19.2.4","typescript":"^5.9.3","@types/react":"^19.2.14","vite-plugin-dts":"^4.5.4","@types/react-dom":"^19.2.3","unicode-animations":"^1.0.3","@vitejs/plugin-react":"^5.1.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cli-loaders_1.0.0_1774096815925_0.25554090633838267","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@agilek/cli-loaders","version":"1.0.1","keywords":["react","spinner","braille","unicode","animation","loading","loader","cli","terminal"],"author":{"name":"Mike Acler","email":"m@acler.cz"},"license":"MIT","_id":"@agilek/cli-loaders@1.0.1","maintainers":[{"name":"agilek","email":"michal.acler@gmail.com"}],"homepage":"https://github.com/agile/cli-loaders#readme","bugs":{"url":"https://github.com/agile/cli-loaders/issues"},"dist":{"shasum":"bf8478dfbd3e115ad7ac4743cd9ea5afe6642aae","tarball":"https://registry.npmjs.org/@agilek/cli-loaders/-/cli-loaders-1.0.1.tgz","fileCount":6,"integrity":"sha512-HydGpmP1NH+2/yDXwntIsuEctRNLhVbUSNMDiA/jN+Wjp9fB4dOiSPr2mFxQqJPUCSjDK0tIt9i9oLJ686Xopw==","signatures":[{"sig":"MEUCIQDFNUnRyQqGh1/ZrkYZotmcX7mEEkxcHwzR8NQS/kHa7AIgUmiWSpJPQ5c6oiavS/azWinMzYCX8pk3XDU/7wn/2p4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46104},"main":"./dist/cli-loaders.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/cli-loaders.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/cli-loaders.js","require":"./dist/cli-loaders.cjs"}},"gitHead":"2b668a5a30b6494d00b481a4c95541b94a23b367","scripts":{"dev":"vite","build":"vite build","gen:svgs":"node scripts/gen-svgs.mjs","build:demo":"vite build --config vite.demo.config.ts","prepublishOnly":"npm run build"},"_npmUser":{"name":"agilek","email":"michal.acler@gmail.com"},"repository":{"url":"git+https://github.com/agile/cli-loaders.git","type":"git"},"_npmVersion":"11.6.3","description":"Braille unicode spinners as React decorator components","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","react":"^19.2.4","react-dom":"^19.2.4","typescript":"^5.9.3","@types/react":"^19.2.14","vite-plugin-dts":"^4.5.4","@types/react-dom":"^19.2.3","unicode-animations":"^1.0.3","@vitejs/plugin-react":"^5.1.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cli-loaders_1.0.1_1774096955834_0.9905148835866535","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@agilek/cli-loaders","version":"1.0.2","keywords":["react","spinner","braille","unicode","animation","loading","loader","cli","terminal"],"author":{"name":"Mike Acler","email":"m@acler.cz"},"license":"MIT","_id":"@agilek/cli-loaders@1.0.2","maintainers":[{"name":"agilek","email":"michal.acler@gmail.com"}],"homepage":"https://github.com/agile/cli-loaders#readme","bugs":{"url":"https://github.com/agile/cli-loaders/issues"},"dist":{"shasum":"dea32ee7f8aed06f676c2ff794fea263bcef16de","tarball":"https://registry.npmjs.org/@agilek/cli-loaders/-/cli-loaders-1.0.2.tgz","fileCount":6,"integrity":"sha512-zBX3Wg7lq48q84Vd/oKSZeSlJLXwTG71Qkf3Qc+02XoXXr7hrXYLOLdU3/g5b3tRVEMtp4vw3ZxpnBNBOLkF2w==","signatures":[{"sig":"MEUCIBEMZcEoaK3+wE+XCFujs8/IIrtAa5XNRB0EGra8vabfAiEAvUr2dqi6gI4ZLGjGmH1gjrDa0SLGjKuTbXop6C7oknA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46104},"main":"./dist/cli-loaders.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/cli-loaders.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/cli-loaders.js","require":"./dist/cli-loaders.cjs"}},"gitHead":"3c0d4478293c288dc3787b345c093d3d5f9f83d0","scripts":{"dev":"vite","build":"vite build","gen:svgs":"node scripts/gen-svgs.mjs","build:demo":"vite build --config vite.demo.config.ts","prepublishOnly":"npm run build"},"_npmUser":{"name":"agilek","email":"michal.acler@gmail.com"},"repository":{"url":"git+https://github.com/agile/cli-loaders.git","type":"git"},"_npmVersion":"11.6.3","description":"Braille unicode spinners as React decorator components","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","react":"^19.2.4","react-dom":"^19.2.4","typescript":"^5.9.3","@types/react":"^19.2.14","vite-plugin-dts":"^4.5.4","@types/react-dom":"^19.2.3","unicode-animations":"^1.0.3","@vitejs/plugin-react":"^5.1.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cli-loaders_1.0.2_1774097101075_0.7755884913703999","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@agilek/cli-loaders","version":"1.1.0","description":"Braille unicode spinners as React decorator components","type":"module","sideEffects":false,"main":"./dist/cli-loaders.cjs","module":"./dist/cli-loaders.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/cli-loaders.js","require":"./dist/cli-loaders.cjs"}},"scripts":{"dev":"vite","build":"vite build","build:demo":"vite build --config vite.demo.config.ts","gen:svgs":"node scripts/gen-svgs.mjs","prepublishOnly":"npm run build"},"keywords":["react","spinner","braille","unicode","animation","loading","loader","cli","terminal"],"author":{"name":"Mike Acler","email":"m@acler.cz"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/agilek/cli-loaders.git"},"homepage":"https://github.com/agilek/cli-loaders#readme","bugs":{"url":"https://github.com/agilek/cli-loaders/issues"},"peerDependencies":{"react":">=18.0.0"},"devDependencies":{"@types/react":"^19.2.14","@types/react-dom":"^19.2.3","@vitejs/plugin-react":"^5.1.4","react":"^19.2.4","react-dom":"^19.2.4","typescript":"^5.9.3","unicode-animations":"^1.0.3","vite":"^7.3.1","vite-plugin-dts":"^4.5.4"},"gitHead":"ee6e9e8bc7508bdbdcd72351191fab24f99b8eb7","_id":"@agilek/cli-loaders@1.1.0","_nodeVersion":"22.18.0","_npmVersion":"11.6.3","dist":{"integrity":"sha512-aqTLMYO0VES9Fcmw15TdMt8/41P8auxdQuFOpJ5LGMX+QVSYcufIx20Ifs8hyuVLrSZbyI0jwMeuQNSC4vTjPg==","shasum":"f6fee2d333cfa1079502badbf56ee4dad89956cc","tarball":"https://registry.npmjs.org/@agilek/cli-loaders/-/cli-loaders-1.1.0.tgz","fileCount":6,"unpackedSize":52039,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHfKZPVrkz0Clnb8ue0I8tSqEzFj0Yy0u0YUAhjk4gOmAiEAy5hlqD4Tugr+oZMvF6cMmIYVV+AZIZCDtvcADEw8ymk="}]},"_npmUser":{"name":"agilek","email":"michal.acler@gmail.com"},"directories":{},"maintainers":[{"name":"agilek","email":"michal.acler@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cli-loaders_1.1.0_1774112060079_0.8178349647713077"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-21T12:40:15.873Z","modified":"2026-03-21T16:54:20.325Z","1.0.0":"2026-03-21T12:40:16.095Z","1.0.1":"2026-03-21T12:42:35.955Z","1.0.2":"2026-03-21T12:45:01.229Z","1.1.0":"2026-03-21T16:54:20.214Z"},"bugs":{"url":"https://github.com/agilek/cli-loaders/issues"},"author":{"name":"Mike Acler","email":"m@acler.cz"},"license":"MIT","homepage":"https://github.com/agilek/cli-loaders#readme","keywords":["react","spinner","braille","unicode","animation","loading","loader","cli","terminal"],"repository":{"type":"git","url":"git+https://github.com/agilek/cli-loaders.git"},"description":"Braille unicode spinners as React decorator components","maintainers":[{"name":"agilek","email":"michal.acler@gmail.com"}],"readme":"# cli-loaders for react\n\n> Animated braille-glyph loading spinners for React. 19 unique animations, zero dependencies, fully accessible. — **[Live demo →](https://cli-loaders-two.vercel.app)** · **[GitHub →](https://github.com/agilek/cli-loaders)**\n\n<div align=\"center\">\n  <img src=\"assets/spinners/braille.svg\" alt=\"braille\">\n  <img src=\"assets/spinners/orbit.svg\" alt=\"orbit\">\n  <img src=\"assets/spinners/breathe.svg\" alt=\"breathe\">\n  <img src=\"assets/spinners/braillewave.svg\" alt=\"braillewave\">\n  <img src=\"assets/spinners/dna.svg\" alt=\"dna\">\n  <img src=\"assets/spinners/waverows.svg\" alt=\"waverows\">\n  <img src=\"assets/spinners/helix.svg\" alt=\"helix\">\n  <img src=\"assets/spinners/fillsweep.svg\" alt=\"fillsweep\">\n  <img src=\"assets/spinners/diagswipe.svg\" alt=\"diagswipe\">\n  <img src=\"assets/spinners/scanline.svg\" alt=\"scanline\">\n  <img src=\"assets/spinners/line.svg\" alt=\"line\">\n  <img src=\"assets/spinners/cascade.svg\" alt=\"cascade\">\n  <img src=\"assets/spinners/scan.svg\" alt=\"scan\">\n  <img src=\"assets/spinners/rain.svg\" alt=\"rain\">\n  <img src=\"assets/spinners/pulse.svg\" alt=\"pulse\">\n  <img src=\"assets/spinners/snake.svg\" alt=\"snake\">\n  <img src=\"assets/spinners/sparkle.svg\" alt=\"sparkle\">\n  <img src=\"assets/spinners/columns.svg\" alt=\"columns\">\n  <img src=\"assets/spinners/checkerboard.svg\" alt=\"checkerboard\">\n</div>\n\n`cli-loaders` gives you 19 animated braille-glyph spinners as a set of composable, accessible React components. Zero runtime dependencies beyond React itself.\n\n## Features\n\n- **19 spinner animations** with unique braille Unicode patterns\n- **Zero runtime dependencies** — pure React, no external libraries\n- **Fully accessible** — WCAG 2.1 AA, `prefers-reduced-motion` support, semantic HTML\n- **TypeScript first** — complete type definitions, `DotShape` export for custom rendering\n- **Composable** — 7 components + 2 hooks for any use case\n- **Small bundle** — ~15KB gzipped (lib) + optional SVG rendering\n- **Shape customization** — render as circles, squares, or diamonds (SVG mode)\n\n## Why cli-loaders?\n\n**vs. react-spinners:** Smaller bundle, braille Unicode art for terminal-like aesthetics, context API for global defaults, shape customization (circles/squares/diamonds)\n\n**vs. react-loading:** Zero dependencies, comprehensive accessibility testing, 19+ unique animations, SVG rendering mode\n\n**vs. custom CSS:** No @keyframes to maintain, out-of-the-box reduced-motion support, semantic HTML, accessible by default\n\n## Install\n\n```sh\nnpm install @agilek/cli-loaders\n# or\npnpm add @agilek/cli-loaders\n# or\nyarn add @agilek/cli-loaders\n```\n\n**Requires React ≥ 18.**\n\n## Quick start\n\n```tsx\nimport { Spinner } from '@agilek/cli-loaders';\n\n// Minimal — defaults to the \"braille\" spinner\n<Spinner />\n\n// Named + coloured\n<Spinner name=\"helix\" color=\"#7c3aed\" size=\"1.5rem\" />\n\n// With custom dot shape (renders as SVG instead of braille text)\n<Spinner name=\"scan\" color=\"#00ff99\" shape=\"square\" size=\"2rem\" />\n```\n\n## Components\n\n### `<Spinner>`\n\nThe base animated glyph. Renders as an inline `<span>` so it drops naturally into any line of text.\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `name` | `SpinnerName` | `\"braille\"` | Which spinner animation to use |\n| `color` | `string` | `currentColor` | CSS color value |\n| `size` | `string \\| number` | `undefined` | Font size of the glyph, e.g. `\"1.5rem\"` or `24` |\n| `speed` | `number` | `1` | Playback multiplier — `2` = twice as fast |\n| `paused` | `boolean` | `false` | Freeze the animation |\n| `ignoreReducedMotion` | `boolean` | `false` | Override `prefers-reduced-motion` and always animate |\n| `shape` | `\"circle\" \\| \"square\" \\| \"diamond\"` | `undefined` | Render dots as SVG shapes instead of braille text |\n| `label` | `string` | `\"Loading\"` | Accessible label announced by screen readers |\n| `className` | `string` | — | Applied to the outer `<span>` |\n| `style` | `CSSProperties` | — | Inline styles for the outer `<span>` |\n| `ref` | `Ref<HTMLSpanElement>` | — | Forwarded to the outer `<span>` |\n\nAny additional HTML span attributes are forwarded.\n\n---\n\n### `<SpinnerInline>`\n\nSpinner + children in a flex row — handy for inline status messages.\n\n```tsx\n<SpinnerInline name=\"braille\" color=\"#00ff99\">\n  Fetching data…\n</SpinnerInline>\n```\n\nAccepts all `Spinner` props plus:\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `gap` | `string \\| number` | `\"0.4em\"` | Gap between spinner and children |\n| `children` | `ReactNode` | — | Content rendered after the spinner |\n\n---\n\n### `<SpinnerText>`\n\nDecorates a text string with spinners — supports a bookend mode that mirrors one on each end.\n\n```tsx\n<SpinnerText text=\"Deploying\" color=\"#f59e0b\" bookend />\n// ⠿ Deploying ⠿\n```\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `text` | `string` | required | The text to decorate |\n| `bookend` | `boolean` | `false` | Place a spinner on both sides |\n| `gap` | `string \\| number` | `\"0.4em\"` | Gap between spinners and text |\n\nPlus all `Spinner` props.\n\n---\n\n### `<SpinnerBadge>`\n\nA tinted pill badge with a spinner — good for live status indicators.\n\n```tsx\n<SpinnerBadge label=\"Live\"     color=\"#ef4444\" />\n<SpinnerBadge label=\"Syncing\"  color=\"#38bdf8\" />\n<SpinnerBadge label=\"Building\" color=\"#f59e0b\" />\n```\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `label` | `string` | required | Badge text (also used as the a11y label) |\n| `paddingY` | `string` | `\"0.4em\"` | Vertical padding |\n| `paddingX` | `string` | `\"0.8em\"` | Horizontal base padding |\n| `balanceRatio` | `number` | `0.3` | Extra right padding fraction for optical balance |\n| `borderRadius` | `string \\| number` | `\"999px\"` | Border radius |\n| `gap` | `string \\| number` | `\"0.35em\"` | Gap between glyph and label |\n\nPlus all `Spinner` props.\n\n---\n\n### `<SpinnerTrail>`\n\nRenders a sliding window of recent frames with decreasing opacity — creates a ghost/motion-blur trail effect.\n\n```tsx\n<SpinnerTrail name=\"helix\" color=\"#7c3aed\" size=\"2rem\" trailLength={6} />\n```\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `trailLength` | `number` | `4` | Number of ghost frames (including the current one) |\n| `minOpacity` | `number` | `0.1` | Opacity of the oldest ghost frame |\n| `reverse` | `boolean` | `false` | Flip the opacity gradient (bright on left, fading right) |\n\nPlus all `Spinner` props.\n\n---\n\n### `<SpinnerButton>`\n\nA `<button>` with a built-in loading state. Disables itself and shows a spinner when `loading` is true. Fully forwarded ref.\n\n```tsx\n<SpinnerButton\n  loading={isSaving}\n  onClick={handleSave}\n  spinnerProps={{ name: 'braille', color: '#00ff99' }}\n>\n  Save changes\n</SpinnerButton>\n```\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `loading` | `boolean` | `false` | Show spinner and disable the button |\n| `spinnerPosition` | `\"left\" \\| \"right\"` | `\"left\"` | Which side the spinner appears on |\n| `spinnerGap` | `string \\| number` | `\"0.45em\"` | Gap between spinner and button label |\n| `spinnerProps` | `Omit<BaseSpinnerProps, \"size\">` | — | Props forwarded to the inner `<Spinner>` |\n\nAll standard `<button>` attributes are forwarded.\n\n---\n\n### `<SpinnerOverlay>`\n\nWraps any content and renders a centered spinner overlay when `active`. Uses the native `inert` attribute to block keyboard/pointer access to the content beneath.\n\n```tsx\n<SpinnerOverlay\n  active={isLoading}\n  name=\"orbit\"\n  color=\"#7c3aed\"\n  size=\"2.5rem\"\n  backdrop=\"rgba(0,0,0,0.4)\"\n>\n  <YourContent />\n</SpinnerOverlay>\n```\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `active` | `boolean` | `true` | Show the overlay |\n| `backdrop` | `string` | `\"rgba(0,0,0,0.35)\"` | CSS background for the backdrop |\n| `size` | `string \\| number` | `\"2rem\"` | Spinner glyph size |\n| `containerStyle` | `CSSProperties` | — | Style applied to the outer wrapper `<div>` |\n| `containerClassName` | `string` | — | Class applied to the outer wrapper `<div>` |\n| `children` | `ReactNode` | — | Content that gets overlaid |\n\nPlus all `Spinner` props.\n\n---\n\n### `<SpinnerProvider>`\n\nSets global defaults for every `Spinner`-family component in the subtree. Individual props override context values.\n\n```tsx\n<SpinnerProvider\n  defaultName=\"orbit\"\n  defaultColor=\"#7c3aed\"\n  defaultSpeed={1.2}\n  respectReducedMotion={true}\n>\n  <App />\n</SpinnerProvider>\n\n// Inside: no props needed — picks up context defaults\n<Spinner />\n<SpinnerBadge label=\"Live\" />\n```\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `defaultName` | `SpinnerName` | `\"braille\"` | Default spinner name |\n| `defaultColor` | `string` | `undefined` | Default color |\n| `defaultSize` | `string \\| number` | `undefined` | Default glyph size |\n| `defaultSpeed` | `number` | `1` | Default speed multiplier |\n| `defaultShape` | `\"circle\" \\| \"square\" \\| \"diamond\"` | `undefined` | Default dot shape |\n| `respectReducedMotion` | `boolean` | `true` | Pause animations when the OS has `prefers-reduced-motion: reduce` |\n\n---\n\n## `useSpinner` hook\n\nDrive any element with the raw frame string for fully custom rendering.\n\n```tsx\nimport { useSpinner } from 'cli-loaders';\n\nfunction MyComponent() {\n  const frame = useSpinner('helix', 1.5);\n\n  return (\n    <h1 style={{ fontFamily: 'monospace', color: '#00ff99' }}>\n      {frame}\n    </h1>\n  );\n}\n```\n\n```ts\nuseSpinner(\n  name: SpinnerName,\n  speed?: number,           // default 1\n  paused?: boolean,         // default false\n  ignoreReducedMotion?: boolean  // default false\n): string\n```\n\n### `useSpinnerFrames`\n\nReturns a sliding window of the last `length` frames — the primitive behind `SpinnerTrail`.\n\n```ts\nuseSpinnerFrames(\n  name: SpinnerName,\n  length?: number,          // default 3\n  speed?: number,\n  paused?: boolean,\n  ignoreReducedMotion?: boolean\n): string[]\n```\n\n---\n\n## Available spinners\n\nAll 19 names are available as the `SpinnerName` union type.\n\n```ts\nimport { spinnerNames } from 'cli-loaders';\n// ['braille', 'braillewave', 'dna', ...]\n```\n\n---\n\n## Accessibility\n\n- The animated glyph is wrapped in `aria-hidden=\"true\"` — it is invisible to screen readers.\n- A visually-hidden `<span role=\"status\" aria-live=\"polite\">` announces the `label` prop (default: `\"Loading\"`).\n- `SpinnerButton` sets `aria-busy` and `aria-disabled` on the button element automatically.\n- `SpinnerOverlay` sets `aria-busy` on the container and uses the native `inert` attribute to prevent keyboard/AT access to obscured content.\n- By default, all animations respect `prefers-reduced-motion: reduce`. Override per-component with `ignoreReducedMotion` or globally via `<SpinnerProvider respectReducedMotion={false}>`.\n\n---\n\n---\n\n## FAQ\n\n**Can I use this with Next.js?**\nYes. Works as both client and server components in the App Router.\n\n**How do I customize spinner animations?**\nUse the `useSpinner` hook to drive any custom rendering. See [useSpinner hook](#usespinner-hook) for examples.\n\n**Does this work with TypeScript?**\nFull type support. All component props and the `DotShape` type are exported for type safety.\n\n**How do I change shapes (circles, squares, diamonds)?**\nUse the `shape` prop: `<Spinner shape=\"square\" />`. See [Spinner props](#spinner) for details.\n\n**Does this support reduced motion preferences?**\nYes, by default. Animations pause when `prefers-reduced-motion: reduce` is set. Override with `ignoreReducedMotion={true}`.\n\n**What's the bundle size?**\n~15KB gzipped for the core library. SVG rendering mode adds ~1KB.\n\n---\n\n## Common Patterns\n\n### Form submission with loading state\n\n```tsx\nconst [loading, setLoading] = useState(false);\n\nasync function handleSubmit() {\n  setLoading(true);\n  try {\n    await api.post('/submit', data);\n  } finally {\n    setLoading(false);\n  }\n}\n\nreturn (\n  <SpinnerButton\n    loading={loading}\n    onClick={handleSubmit}\n    spinnerProps={{ name: 'helix', color: '#00ff99' }}\n  >\n    {loading ? 'Submitting...' : 'Submit'}\n  </SpinnerButton>\n);\n```\n\n### Full-screen loading overlay\n\n```tsx\nconst [fetching, setFetching] = useState(false);\n\nreturn (\n  <SpinnerOverlay\n    active={fetching}\n    name=\"orbit\"\n    size=\"2rem\"\n    backdrop=\"rgba(0,0,0,0.5)\"\n  >\n    <Dashboard data={data} />\n  </SpinnerOverlay>\n);\n```\n\n### Inline status message with shape customization\n\n```tsx\nreturn (\n  <SpinnerInline\n    name=\"scan\"\n    shape=\"diamond\"\n    color=\"#7c3aed\"\n  >\n    Syncing your data...\n  </SpinnerInline>\n);\n```\n\n---\n\n## Contributing\n\nBug reports and pull requests are welcome. Please open an issue before submitting large changes.\n\n```sh\n# Install dependencies\nnpm install\n\n# Start the interactive demo\nnpm run dev\n\n# Build the library\nnpm run build\n```\n\n---\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}