Skip to content

Commit d9fa747

Browse files
committed
feat: add spinner component
1 parent 2aace9f commit d9fa747

File tree

11 files changed

+128
-8
lines changed

11 files changed

+128
-8
lines changed
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
.container {
2+
padding-top: 40px;
3+
margin: auto;
4+
width: 100%;
5+
height: 100%;
6+
@include flex-center();
7+
}
8+
9+
.spinner {
10+
display: inline-block;
11+
position: relative;
12+
width: 80px;
13+
height: 80px;
14+
transform: scale(0.6);
15+
}
16+
.spinner div {
17+
transform-origin: 40px 40px;
18+
animation: spinner 1.2s linear infinite;
19+
}
20+
.spinner div:after {
21+
content: ' ';
22+
display: block;
23+
position: absolute;
24+
top: 3px;
25+
left: 37px;
26+
width: 6px;
27+
height: 18px;
28+
border-radius: 20%;
29+
background: $color-primary;
30+
}
31+
.spinner div:nth-child(1) {
32+
transform: rotate(0deg);
33+
animation-delay: -1.1s;
34+
}
35+
.spinner div:nth-child(2) {
36+
transform: rotate(30deg);
37+
animation-delay: -1s;
38+
}
39+
.spinner div:nth-child(3) {
40+
transform: rotate(60deg);
41+
animation-delay: -0.9s;
42+
}
43+
.spinner div:nth-child(4) {
44+
transform: rotate(90deg);
45+
animation-delay: -0.8s;
46+
}
47+
.spinner div:nth-child(5) {
48+
transform: rotate(120deg);
49+
animation-delay: -0.7s;
50+
}
51+
.spinner div:nth-child(6) {
52+
transform: rotate(150deg);
53+
animation-delay: -0.6s;
54+
}
55+
.spinner div:nth-child(7) {
56+
transform: rotate(180deg);
57+
animation-delay: -0.5s;
58+
}
59+
.spinner div:nth-child(8) {
60+
transform: rotate(210deg);
61+
animation-delay: -0.4s;
62+
}
63+
.spinner div:nth-child(9) {
64+
transform: rotate(240deg);
65+
animation-delay: -0.3s;
66+
}
67+
.spinner div:nth-child(10) {
68+
transform: rotate(270deg);
69+
animation-delay: -0.2s;
70+
}
71+
.spinner div:nth-child(11) {
72+
transform: rotate(300deg);
73+
animation-delay: -0.1s;
74+
}
75+
.spinner div:nth-child(12) {
76+
transform: rotate(330deg);
77+
animation-delay: 0s;
78+
}
79+
@keyframes spinner {
80+
0% {
81+
opacity: 1;
82+
}
83+
100% {
84+
opacity: 0;
85+
}
86+
}

src/components/Spinner/Spinner.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import styles from './Spinner.module.scss';
2+
3+
const Spinner = () => {
4+
return (
5+
<div className={styles.container}>
6+
<div className={styles.spinner}>
7+
<div></div>
8+
<div></div>
9+
<div></div>
10+
<div></div>
11+
<div></div>
12+
<div></div>
13+
<div></div>
14+
<div></div>
15+
<div></div>
16+
<div></div>
17+
<div></div>
18+
<div></div>
19+
</div>
20+
</div>
21+
);
22+
};
23+
24+
export default Spinner;

src/components/Spinner/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './Spinner';

src/containers/Category/Category.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import LinkButton from '@/components/LinkButton';
1111
import TodoList from '@/components/TodoList';
1212
import Header from '@/components/Header';
1313
import { useBackButton } from '@/hooks/useBackButton';
14+
import Spinner from '@/components/Spinner';
1415

1516
const Category = () => {
1617
const {
@@ -25,7 +26,7 @@ const Category = () => {
2526

2627
const { mutate } = useDeleteCategory();
2728

28-
if (isLoading) return 'loading ...';
29+
if (isLoading) return <Spinner />;
2930

3031
if (!data) return <NotFound />;
3132

src/containers/CategoryForm/CategoryForm.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { yupResolver } from '@hookform/resolvers/yup';
1818
import Header from '@/components/Header';
1919
import { useBackButton } from '@/hooks/useBackButton';
2020
import NotFound from '@/components/NotFound';
21+
import Spinner from '@/components/Spinner';
2122

2223
interface IProps {
2324
type: IFormType;
@@ -69,7 +70,7 @@ const CategoryForm = ({ type }: IProps) => {
6970

7071
useClosingBehaviour(isValid);
7172

72-
if (isLoading) return 'loading...';
73+
if (type === 'edit' && isLoading) return <Spinner />;
7374

7475
if (!category && type === 'edit') return <NotFound />;
7576

src/containers/Landing/Landing.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@ import { useTranslation } from '@/hooks/useTranslation/useTranslation';
55
import LinkButton from '@/components/LinkButton';
66
import Profile from '@/components/Profile';
77
import { useBackButton } from '@/hooks/useBackButton';
8+
import Spinner from '@/components/Spinner';
89

910
const Landing = () => {
1011
useBackButton();
11-
const { data } = useCategories();
12+
const { data, isLoading } = useCategories();
1213
const { t } = useTranslation();
1314

1415
const items = data?.map(category => (
1516
<Category key={category.id} {...category} />
1617
));
1718

19+
if (isLoading) return <Spinner />;
20+
1821
return (
1922
<div className={styles.landing}>
2023
<Profile />

src/containers/TaskForm/TaskForm.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { useCreateTask, useEditTask, useTask } from '@/hooks/api/task';
1818
import Header from '@/components/Header';
1919
import { useBackButton } from '@/hooks/useBackButton';
2020
import NotFound from '@/components/NotFound';
21+
import Spinner from '@/components/Spinner';
2122

2223
interface IProps {
2324
type: IFormType;
@@ -85,7 +86,7 @@ const TaskForm = ({ type }: IProps) => {
8586

8687
useClosingBehaviour(isValid);
8788

88-
if (isLoading) return 'loading...';
89+
if (type === 'edit' && isLoading) return <Spinner />;
8990

9091
if (!task && type === 'edit') return <NotFound />;
9192

src/containers/TodoList/TodoList.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Task from '@/components/Task';
1212
import { useDeleteTodoList, useTodoList } from '@/hooks/api/todo-list';
1313
import Header from '@/components/Header';
1414
import { useBackButton } from '@/hooks/useBackButton';
15+
import Spinner from '@/components/Spinner';
1516

1617
const TodoList = () => {
1718
const {
@@ -26,7 +27,7 @@ const TodoList = () => {
2627

2728
const { mutate } = useDeleteTodoList();
2829

29-
if (isLoading) return 'loading ...';
30+
if (isLoading) return <Spinner />;
3031

3132
if (!data) return <NotFound />;
3233

src/containers/TodoListForm/TodoListForm.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import Header from '@/components/Header';
1717
import { useBackButton } from '@/hooks/useBackButton';
1818
import NotFound from '@/components/NotFound';
19+
import Spinner from '@/components/Spinner';
1920

2021
interface IProps {
2122
type: IFormType;
@@ -68,7 +69,7 @@ const TodoListForm = ({ type }: IProps) => {
6869

6970
useClosingBehaviour(isValid);
7071

71-
if (isLoading) return 'loading...';
72+
if (type === 'edit' && isLoading) return <Spinner />;
7273

7374
if (!todoList && type === 'edit') return <NotFound />;
7475

Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
.layout {
2-
// padding: 10px;
2+
height: 100%;
33
}

src/styles/globals.scss

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ body {
1515
@include no-select;
1616
}
1717

18-
input,textarea{
18+
input,
19+
textarea {
1920
color: inherit;
2021
}
2122

0 commit comments

Comments
 (0)