Skip to content

Commit 356f651

Browse files
authored
feat: spinner component (#1432)
* feat: spinner component implementation * docs: add spinner component with demos * chore: update registries with spinner component
1 parent f5f52ff commit 356f651

37 files changed

+628
-1
lines changed

apps/v4/__registry__/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,25 @@ export const Index: Record<string, any> = {
17821782
category: "",
17831783
subcategory: ""
17841784
},
1785+
"spinner": {
1786+
name: "spinner",
1787+
description: "",
1788+
type: "registry:ui",
1789+
registryDependencies: [],
1790+
files: [{
1791+
path: "registry/new-york-v4/ui/spinner/Spinner.vue",
1792+
type: "registry:ui",
1793+
target: ""
1794+
},{
1795+
path: "registry/new-york-v4/ui/spinner/index.ts",
1796+
type: "registry:ui",
1797+
target: ""
1798+
}],
1799+
component: () => import("@/registry/new-york-v4/ui/spinner/Spinner.vue").then((m) => m.default),
1800+
source: "",
1801+
category: "",
1802+
subcategory: ""
1803+
},
17851804
"stepper": {
17861805
name: "stepper",
17871806
description: "",

apps/v4/components/SpinnerDemo.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script setup lang="ts">
2+
import { Button } from '@/registry/new-york-v4/ui/button'
3+
import { Spinner } from '@/registry/new-york-v4/ui/spinner'
4+
</script>
5+
6+
<template>
7+
<Button disabled>
8+
<Spinner />
9+
Processing Payment
10+
</Button>
11+
</template>

apps/v4/public/r/index.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,22 @@
17581758
}
17591759
]
17601760
},
1761+
{
1762+
"name": "spinner",
1763+
"type": "registry:ui",
1764+
"dependencies": [],
1765+
"registryDependencies": [],
1766+
"files": [
1767+
{
1768+
"path": "ui/spinner/Spinner.vue",
1769+
"type": "registry:ui"
1770+
},
1771+
{
1772+
"path": "ui/spinner/index.ts",
1773+
"type": "registry:ui"
1774+
}
1775+
]
1776+
},
17611777
{
17621778
"name": "stepper",
17631779
"type": "registry:ui",
@@ -2034,4 +2050,4 @@
20342050
}
20352051
]
20362052
}
2037-
]
2053+
]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script setup lang="ts">
2+
import { Loader2Icon } from "lucide-vue-next"
3+
import { cn } from "@/lib/utils"
4+
</script>
5+
6+
<template>
7+
<Loader2Icon
8+
role="status"
9+
aria-label="Loading"
10+
:class="cn('size-4 animate-spin', $attrs.class ?? '')"
11+
v-bind="$attrs"
12+
/>
13+
</template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as Spinner } from "./Spinner.vue"

apps/www/.vitepress/theme/config/docs.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ export const docsConfig: DocsConfig = {
361361
href: '/docs/components/sonner',
362362
items: [],
363363
},
364+
{
365+
title: 'Spinner',
366+
href: '/docs/components/spinner',
367+
},
364368
{
365369
title: 'Stepper',
366370
href: '/docs/components/stepper',

apps/www/__registry__/index.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4579,6 +4579,81 @@ export const Index: Record<string, any> = {
45794579
category: "",
45804580
subcategory: ""
45814581
},
4582+
"SpinnerButtonsDemo": {
4583+
name: "SpinnerButtonsDemo",
4584+
description: "",
4585+
type: "registry:example",
4586+
registryDependencies: ["button","spinner"],
4587+
files: [{
4588+
path: "registry/new-york/examples/SpinnerButtonsDemo.vue",
4589+
type: "registry:example",
4590+
target: ""
4591+
}],
4592+
component: () => import("@/registry/new-york/examples/SpinnerButtonsDemo.vue").then((m) => m.default),
4593+
source: "",
4594+
category: "",
4595+
subcategory: ""
4596+
},
4597+
"SpinnerColorsDemo": {
4598+
name: "SpinnerColorsDemo",
4599+
description: "",
4600+
type: "registry:example",
4601+
registryDependencies: ["spinner"],
4602+
files: [{
4603+
path: "registry/new-york/examples/SpinnerColorsDemo.vue",
4604+
type: "registry:example",
4605+
target: ""
4606+
}],
4607+
component: () => import("@/registry/new-york/examples/SpinnerColorsDemo.vue").then((m) => m.default),
4608+
source: "",
4609+
category: "",
4610+
subcategory: ""
4611+
},
4612+
"SpinnerCustomDemo": {
4613+
name: "SpinnerCustomDemo",
4614+
description: "",
4615+
type: "registry:example",
4616+
registryDependencies: [],
4617+
files: [{
4618+
path: "registry/new-york/examples/SpinnerCustomDemo.vue",
4619+
type: "registry:example",
4620+
target: ""
4621+
}],
4622+
component: () => import("@/registry/new-york/examples/SpinnerCustomDemo.vue").then((m) => m.default),
4623+
source: "",
4624+
category: "",
4625+
subcategory: ""
4626+
},
4627+
"SpinnerDemo": {
4628+
name: "SpinnerDemo",
4629+
description: "",
4630+
type: "registry:example",
4631+
registryDependencies: ["button","spinner"],
4632+
files: [{
4633+
path: "registry/new-york/examples/SpinnerDemo.vue",
4634+
type: "registry:example",
4635+
target: ""
4636+
}],
4637+
component: () => import("@/registry/new-york/examples/SpinnerDemo.vue").then((m) => m.default),
4638+
source: "",
4639+
category: "",
4640+
subcategory: ""
4641+
},
4642+
"SpinnerSizesDemo": {
4643+
name: "SpinnerSizesDemo",
4644+
description: "",
4645+
type: "registry:example",
4646+
registryDependencies: ["spinner"],
4647+
files: [{
4648+
path: "registry/new-york/examples/SpinnerSizesDemo.vue",
4649+
type: "registry:example",
4650+
target: ""
4651+
}],
4652+
component: () => import("@/registry/new-york/examples/SpinnerSizesDemo.vue").then((m) => m.default),
4653+
source: "",
4654+
category: "",
4655+
subcategory: ""
4656+
},
45824657
"StepperDemo": {
45834658
name: "StepperDemo",
45844659
description: "",
@@ -8037,6 +8112,25 @@ export const Index: Record<string, any> = {
80378112
category: "",
80388113
subcategory: ""
80398114
},
8115+
"spinner": {
8116+
name: "spinner",
8117+
description: "",
8118+
type: "registry:ui",
8119+
registryDependencies: [],
8120+
files: [{
8121+
path: "registry/new-york/ui/spinner/Spinner.vue",
8122+
type: "registry:ui",
8123+
target: ""
8124+
},{
8125+
path: "registry/new-york/ui/spinner/index.ts",
8126+
type: "registry:ui",
8127+
target: ""
8128+
}],
8129+
component: () => import("@/registry/new-york/ui/spinner/Spinner.vue").then((m) => m.default),
8130+
source: "",
8131+
category: "",
8132+
subcategory: ""
8133+
},
80408134
"stepper": {
80418135
name: "stepper",
80428136
description: "",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: Spinner
3+
description: An indicator that can be used to show a loading state.
4+
---
5+
6+
<ComponentPreview name="SpinnerDemo" />
7+
8+
## Installation
9+
10+
```bash
11+
npx shadcn-vue@latest add spinner
12+
```
13+
14+
## Usage
15+
16+
```vue
17+
<script setup lang="ts">
18+
import { Spinner } from '@/components/ui/Spinner'
19+
</script>
20+
21+
<template>
22+
<Spinner />
23+
</template>
24+
```
25+
26+
## Customization
27+
You can replace the default spinner icon with any other icon by editing the `Spinner` component.
28+
29+
<ComponentPreview name="SpinnerCustomDemo" />
30+
31+
## Examples
32+
33+
### Size
34+
35+
Use the `size-*` utility class to change the size of the spinner.
36+
37+
<ComponentPreview name="SpinnerSizesDemo" />
38+
39+
### Color
40+
41+
Use the `text-*` utility class to change the color of the spinner.
42+
43+
<ComponentPreview name="SpinnerColorsDemo" />
44+
45+
### Button
46+
47+
Add a spinner to a button to indicate a loading state. The `<Button />` will handle the spacing between the spinner and the text.
48+
49+
<ComponentPreview name="SpinnerButtonsDemo" />
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "SpinnerButtonsDemo",
3+
"type": "registry:example",
4+
"dependencies": [],
5+
"registryDependencies": [
6+
"button",
7+
"spinner"
8+
],
9+
"files": [
10+
{
11+
"path": "examples/SpinnerButtonsDemo.vue",
12+
"content": "<script setup lang=\"ts\">\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Spinner } from \"@/registry/default/ui/spinner\";\n</script>\n\n<template>\n <div className=\"flex flex-col items-center gap-4\">\n <Button disabled size=\"sm\">\n <Spinner class=\"size-2\" />\n Loading...\n </Button>\n <Button variant=\"outline\" disabled size=\"sm\">\n <Spinner class=\"size-2\" />\n Please wait\n </Button>\n <Button variant=\"secondary\" disabled size=\"sm\">\n <Spinner class=\"size-2\" />\n Processing\n </Button>\n </div>\n</template>\n",
13+
"type": "registry:example",
14+
"target": ""
15+
}
16+
]
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "SpinnerColorDemo",
3+
"type": "registry:example",
4+
"dependencies": [],
5+
"registryDependencies": [
6+
"spinner"
7+
],
8+
"files": [
9+
{
10+
"path": "examples/SpinnerColorDemo.vue",
11+
"content": "<script setup lang=\"ts\">\nimport { Spinner } from \"@/registry/default/ui/spinner\";\n</script>\n\n<template>\n <div className=\"flex items-center gap-6\">\n <Spinner class=\"size-6 text-red-500\" />\n <Spinner class=\"size-6 text-green-500\" />\n <Spinner class=\"size-6 text-blue-500\" />\n <Spinner class=\"size-6 text-yellow-500\" />\n <Spinner class=\"size-6 text-purple-500\" />\n </div>\n</template>\n",
12+
"type": "registry:example",
13+
"target": ""
14+
}
15+
]
16+
}

0 commit comments

Comments
 (0)