Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcee3656

Browse files
chore: add spinner component (#16014)
This component is necessary to move forward with the "[Define a globalbutton style](#14978)" issue, as itrequires buttons to support loading states with spinners. The `Spinner`component is heavily inspired by the [Radix UI Spinnercomponent](https://www.radix-ui.com/themes/docs/components/spinner) andwas developed with the help of [v0](https://v0.dev/).**Preview**![Screen Recording 2025-01-02 at 14 3718](https://github.com/user-attachments/assets/838f6bb2-2125-4a55-9bee-3b3a52852d40)---------Co-authored-by: Jaayden Halko <jaayden.halko@gmail.com>
1 parent21a45cf commitcee3656

File tree

5 files changed

+128
-20
lines changed

5 files changed

+128
-20
lines changed

‎site/src/components/Loader/Loader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
importtype{Interpolation,Theme}from"@emotion/react";
2-
import{Spinner}from"components/Spinner/Spinner";
2+
import{Spinner}from"components/deprecated/Spinner/Spinner";
33
importtype{FC,HTMLAttributes}from"react";
44

55
interfaceLoaderPropsextendsHTMLAttributes<HTMLDivElement>{
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{PlusIcon}from"lucide-react";
3+
import{Spinner}from"./Spinner";
4+
5+
constmeta:Meta<typeofSpinner>={
6+
title:"components/Spinner",
7+
component:Spinner,
8+
args:{
9+
children:<PlusIconclassName="size-icon-lg"/>,
10+
},
11+
};
12+
13+
exportdefaultmeta;
14+
typeStory=StoryObj<typeofSpinner>;
15+
16+
exportconstIdle:Story={};
17+
18+
exportconstLoading:Story={
19+
args:{loading:true},
20+
};
Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,77 @@
1-
importCircularProgress,{
2-
typeCircularProgressProps,
3-
}from"@mui/material/CircularProgress";
4-
importisChromaticfrom"chromatic/isChromatic";
5-
importtype{FC}from"react";
6-
71
/**
8-
*Spinner componentused to indicate loading states. This component abstracts
9-
*the MUI CircularProgress to provide better control over its rendering,
10-
*especially in snapshot tests with Chromatic.
2+
*This componentwas inspired by
3+
*https://www.radix-ui.com/themes/docs/components/spinner and developed using
4+
*https://v0.dev/ help.
115
*/
12-
exportconstSpinner:FC<CircularProgressProps>=(props)=>{
13-
/**
14-
* During Chromatic snapshots, we render the spinner as determinate to make it
15-
* static without animations, using a deterministic value (75%).
16-
*/
17-
if(isChromatic()){
18-
props.variant="determinate";
19-
props.value=75;
6+
7+
importisChromaticfrom"chromatic/isChromatic";
8+
import{typeVariantProps,cva}from"class-variance-authority";
9+
importtype{ReactNode}from"react";
10+
import{cn}from"utils/cn";
11+
12+
constleaves=8;
13+
14+
constspinnerVariants=cva("",{
15+
variants:{
16+
size:{
17+
lg:"size-icon-lg",
18+
sm:"size-icon-sm",
19+
},
20+
},
21+
defaultVariants:{
22+
size:"lg",
23+
},
24+
});
25+
26+
typeSpinnerProps=React.SVGProps<SVGSVGElement>&
27+
VariantProps<typeofspinnerVariants>&{
28+
children?:ReactNode;
29+
loading?:boolean;
30+
};
31+
32+
exportfunctionSpinner({
33+
className,
34+
size,
35+
loading,
36+
children,
37+
...props
38+
}:SpinnerProps){
39+
if(!loading){
40+
returnchildren;
2041
}
21-
return<CircularProgress{...props}/>;
22-
};
42+
43+
return(
44+
<svg
45+
viewBox="0 0 24 24"
46+
xmlns="http://www.w3.org/2000/svg"
47+
fill="currentColor"
48+
className={cn(spinnerVariants({ size, className}))}
49+
{...props}
50+
>
51+
<title>Loading spinner</title>
52+
{[...Array(leaves)].map((_,i)=>{
53+
constrotation=i*(360/leaves);
54+
55+
return(
56+
<rect
57+
key={i}
58+
x="10.9"
59+
y="2"
60+
width="2"
61+
height="5.5"
62+
rx="1"
63+
// 0.8 = leaves * 0.1
64+
className={
65+
isChromatic() ?"" :"animate-[loading_0.8s_ease-in-out_infinite]"
66+
}
67+
style={{
68+
transform:`rotate(${rotation}deg)`,
69+
transformOrigin:"center",
70+
animationDelay:`${-i*0.1}s`,
71+
}}
72+
/>
73+
);
74+
})}
75+
</svg>
76+
);
77+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
importCircularProgress,{
2+
typeCircularProgressProps,
3+
}from"@mui/material/CircularProgress";
4+
importisChromaticfrom"chromatic/isChromatic";
5+
importtype{FC}from"react";
6+
7+
/**
8+
* Spinner component used to indicate loading states. This component abstracts
9+
* the MUI CircularProgress to provide better control over its rendering,
10+
* especially in snapshot tests with Chromatic.
11+
*
12+
*@deprecated prefer `components.Spinner`
13+
*/
14+
exportconstSpinner:FC<CircularProgressProps>=(props)=>{
15+
/**
16+
* During Chromatic snapshots, we render the spinner as determinate to make it
17+
* static without animations, using a deterministic value (75%).
18+
*/
19+
if(isChromatic()){
20+
props.variant="determinate";
21+
props.value=75;
22+
}
23+
return<CircularProgress{...props}/>;
24+
};

‎site/tailwind.config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ module.exports = {
5858
5:"hsl(var(--chart-5))",
5959
},
6060
},
61+
keyframes:{
62+
loading:{
63+
"0%":{opacity:0.85},
64+
"25%":{opacity:0.7},
65+
"50%":{opacity:0.4},
66+
"75%":{opacity:0.3},
67+
"100%":{opacity:0.2},
68+
},
69+
},
6170
},
6271
},
6372
plugins:[require("tailwindcss-animate")],

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp