File tree Expand file tree Collapse file tree 3 files changed +102
-0
lines changed Expand file tree Collapse file tree 3 files changed +102
-0
lines changed Original file line number Diff line number Diff line change
1
+ import type { Meta , StoryObj } from "@storybook/react" ;
2
+ import { Spinner } from "./Spinner" ;
3
+ import { PlusIcon } from "lucide-react" ;
4
+
5
+ const meta : Meta < typeof Spinner > = {
6
+ title : "components/Spinner" ,
7
+ component : Spinner ,
8
+ args : {
9
+ children : < PlusIcon className = "size-icon-lg" /> ,
10
+ } ,
11
+ } ;
12
+
13
+ export default meta ;
14
+ type Story = StoryObj < typeof Spinner > ;
15
+
16
+ export const Idle : Story = { } ;
17
+
18
+ export const Loading : Story = {
19
+ args : { loading : true } ,
20
+ } ;
Original file line number Diff line number Diff line change
1
+ /**
2
+ * This component was inspired by
3
+ * https://www.radix-ui.com/themes/docs/components/spinner and developed using
4
+ * https://v0.dev/ help.
5
+ */
6
+
7
+ import { cva , type VariantProps } from "class-variance-authority" ;
8
+ import type { ReactNode } from "react" ;
9
+ import { cn } from "utils/cn" ;
10
+
11
+ const leaves = 8 ;
12
+
13
+ const spinnerVariants = cva ( "" , {
14
+ variants : {
15
+ size : {
16
+ lg : "size-icon-lg" ,
17
+ sm : "size-icon-sm" ,
18
+ } ,
19
+ } ,
20
+ defaultVariants : {
21
+ size : "lg" ,
22
+ } ,
23
+ } ) ;
24
+
25
+ type SpinnerProps = React . SVGProps < SVGSVGElement > &
26
+ VariantProps < typeof spinnerVariants > & {
27
+ children ?: ReactNode ;
28
+ loading ?: boolean ;
29
+ } ;
30
+
31
+ export function Spinner ( {
32
+ className,
33
+ size,
34
+ loading,
35
+ children,
36
+ ...props
37
+ } : SpinnerProps ) {
38
+ if ( ! loading ) {
39
+ return children ;
40
+ }
41
+
42
+ return (
43
+ < svg
44
+ viewBox = "0 0 24 24"
45
+ xmlns = "http://www.w3.org/2000/svg"
46
+ fill = "currentColor"
47
+ className = { cn ( spinnerVariants ( { size, className } ) ) }
48
+ { ...props }
49
+ >
50
+ < title > Loading spinner</ title >
51
+ { [ ...Array ( leaves ) ] . map ( ( _ , i ) => {
52
+ const rotation = i * ( 360 / leaves ) ;
53
+
54
+ return (
55
+ < rect
56
+ // biome-ignore lint/suspicious/noArrayIndexKey: This is a static array
57
+ key = { i }
58
+ x = "11.5"
59
+ y = "3"
60
+ width = "1.5"
61
+ height = "4"
62
+ rx = "0.5"
63
+ // 0.8 = leaves * 0.1
64
+ className = "animate-[loading_0.8s_ease-in-out_infinite]"
65
+ style = { {
66
+ transform : `rotate(${ rotation } deg)` ,
67
+ transformOrigin : "center" ,
68
+ animationDelay : `${ - i * 0.1 } s` ,
69
+ } }
70
+ />
71
+ ) ;
72
+ } ) }
73
+ </ svg >
74
+ ) ;
75
+ }
Original file line number Diff line number Diff line change @@ -58,6 +58,13 @@ module.exports = {
58
58
5 : "hsl(var(--chart-5))" ,
59
59
} ,
60
60
} ,
61
+ keyframes : {
62
+ loading : {
63
+ "0%" : { opacity : 0.85 } ,
64
+ "50%" : { opacity : 0.25 } ,
65
+ "100%" : { opacity : 0.25 } ,
66
+ } ,
67
+ } ,
61
68
} ,
62
69
} ,
63
70
plugins : [ require ( "tailwindcss-animate" ) ] ,
You can’t perform that action at this time.
0 commit comments