Skip to content

Commit e20f0e3

Browse files
committed
Update Spinner
1 parent 3b5d462 commit e20f0e3

File tree

5 files changed

+269
-14
lines changed

5 files changed

+269
-14
lines changed

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { AppWindow } from "./components/AppWindow";
22
import { Hero } from "./components/Hero";
3+
import { Install } from "./components/Install";
34
import { NewProject } from "./components/NewProject";
45
import { Projects } from "./components/Projects";
56

@@ -10,6 +11,7 @@ export function App() {
1011
<Hero />
1112
<Projects />
1213
<NewProject />
14+
<Install />
1315
</AppWindow>
1416
</div>
1517
</>);

src/components/Actions/index.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { GitPullRequestArrow, Plus } from "lucide-react";
33

44
import {
55
checkUpdates,
6-
updateTools,
76
} from "../../utils/desktopTools";
87

98
import "./style.css";
@@ -18,15 +17,11 @@ export function Actions() {
1817
});
1918
}, []);
2019

21-
const startUpdate = useCallback(() => {
22-
const message = [
23-
"Are you sure you want to update the tools?",
24-
"This will close the application.",
25-
"You will need to start it again manually.",
26-
].join(" ");
27-
28-
if (!confirm(message)) return;
29-
updateTools();
20+
const scrollUpdate = useCallback(() => {
21+
document.getElementById("install")?.scrollIntoView({
22+
behavior: "smooth",
23+
block: "end",
24+
});
3025
}, []);
3126

3227
useEffect(() => {
@@ -55,7 +50,7 @@ export function Actions() {
5550

5651
<button
5752
className="action"
58-
onClick={startUpdate}
53+
onClick={scrollUpdate}
5954
disabled={!updatesAvailable}
6055
>
6156
<GitPullRequestArrow className="action-icon" />

src/components/Install/index.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { useCallback, useState } from "react";
2+
import { ChevronUp, Download } from "lucide-react";
3+
import { updateTools } from "../../utils/desktopTools";
4+
5+
import "./style.css";
6+
7+
export function Install() {
8+
const [installing, setInstalling] = useState(false);
9+
10+
const scrollUp = useCallback(() => {
11+
document.getElementById("hero")?.scrollIntoView({
12+
behavior: "smooth",
13+
block: "end",
14+
});
15+
}, []);
16+
17+
const startInstall = useCallback(() => {
18+
setInstalling(true);
19+
updateTools();
20+
}, []);
21+
22+
return (<>
23+
<div id="install" className="install">
24+
<button
25+
className="install-scroll scroll-up"
26+
onClick={scrollUp}
27+
disabled={installing}
28+
>
29+
<ChevronUp className="install-scroll-icon" />
30+
31+
<span className="install-scroll-text">
32+
Welcome Screen
33+
</span>
34+
35+
<ChevronUp className="install-scroll-icon" />
36+
</button>
37+
38+
<div className="install-content">
39+
<button
40+
className="install-button"
41+
onClick={startInstall}
42+
disabled={installing}
43+
>
44+
<Download className="install-button-icon" />
45+
46+
<span className="install-button-text">
47+
Update Tools
48+
</span>
49+
</button>
50+
</div>
51+
52+
<div
53+
className={[
54+
"installing-text",
55+
installing ? "active" : "",
56+
].join(" ")}
57+
>
58+
Updating
59+
</div>
60+
61+
<span className={[
62+
"install-spinner",
63+
installing ? "active" : "",
64+
].join(" ")} />
65+
</div>
66+
</>);
67+
}
68+

src/components/Install/style.css

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
@keyframes spinner {
2+
0% {
3+
transform: rotate(0deg);
4+
scale: 2;
5+
}
6+
50% {
7+
transform: rotate(180deg);
8+
scale: 4;
9+
}
10+
100% {
11+
transform: rotate(360deg);
12+
scale: 2;
13+
}
14+
}
15+
16+
.install {
17+
width: 100%;
18+
min-height: 100%;
19+
height: 100%;
20+
position: relative;
21+
display: flex;
22+
flex-direction: column;
23+
align-items: center;
24+
justify-content: start;
25+
pointer-events: none;
26+
}
27+
28+
.install > * {
29+
pointer-events: auto;
30+
}
31+
32+
.install-scroll {
33+
position: absolute;
34+
padding: 0.5rem 1rem;
35+
border: none;
36+
border-radius: 1rem;
37+
outline: none;
38+
background: var(--color-black);
39+
cursor: pointer;
40+
opacity: 0.5;
41+
display: flex;
42+
align-items: center;
43+
justify-content: center;
44+
gap: 0.25rem;
45+
z-index: 10;
46+
}
47+
48+
.install-scroll:disabled {
49+
opacity: 0;
50+
pointer-events: none;
51+
}
52+
53+
.scroll-up {
54+
top: 1rem;
55+
}
56+
57+
.scroll-down {
58+
bottom: 1rem;
59+
}
60+
61+
.install-scroll:hover {
62+
opacity: 1;
63+
}
64+
65+
.install-scroll:active {
66+
scale: 0.5;
67+
}
68+
69+
.install-scroll-icon {
70+
height: 1rem;
71+
width: 1rem;
72+
}
73+
74+
.install-content {
75+
width: 100%;
76+
height: 100%;
77+
overflow-y: auto;
78+
padding: 1rem;
79+
display: flex;
80+
flex-direction: column;
81+
align-items: center;
82+
justify-content: center;
83+
gap: 1rem;
84+
pointer-events: none;
85+
}
86+
87+
.install-content > * {
88+
pointer-events: auto;
89+
}
90+
91+
.install-button {
92+
height: 3rem;
93+
aspect-ratio: 1;
94+
border: none;
95+
outline: none;
96+
position: relative;
97+
}
98+
99+
.install-button:disabled {
100+
opacity: 0;
101+
pointer-events: none;
102+
}
103+
104+
.install-button-icon {
105+
height: 100%;
106+
width: 100%;
107+
padding: 0.75rem;
108+
border-radius: 0.5rem;
109+
background: #ffffff11;
110+
color: #ffffff;
111+
font-size: 0.75rem;
112+
font-weight: 200;
113+
cursor: pointer;
114+
}
115+
116+
.install-button-text {
117+
position: absolute;
118+
top: 100%;
119+
left: 50%;
120+
text-wrap: nowrap;
121+
transform: translateX(-50%) translateY(0);
122+
opacity: 0;
123+
pointer-events: none;
124+
}
125+
126+
.install-button:hover .install-button-text {
127+
transform: translateX(-50%) translateY(0.5rem);
128+
opacity: 1;
129+
}
130+
131+
.install-button:hover .install-button-icon {
132+
background: #ffffff22;
133+
}
134+
135+
.install-button:active .install-button-icon {
136+
scale: 0.5;
137+
}
138+
139+
.install-spinner {
140+
position: fixed;
141+
left: 50%;
142+
top: 50%;
143+
transform: translate(-50%, -50%);
144+
display: flex;
145+
align-items: center;
146+
justify-content: center;
147+
opacity: 0;
148+
pointer-events: none;
149+
}
150+
151+
.install-spinner::before {
152+
content: "";
153+
width: 2rem;
154+
aspect-ratio: 1;
155+
border-radius: 0.5rem;
156+
animation: spinner 1s linear infinite;
157+
background: linear-gradient(
158+
to bottom right,
159+
var(--color-primary),
160+
var(--color-secondary),
161+
var(--color-tertiary)
162+
);
163+
}
164+
165+
.install-spinner.active {
166+
opacity: 1;
167+
}
168+
169+
.installing-text {
170+
position: fixed;
171+
bottom: 1rem;
172+
left: 50%;
173+
transform: translate(-50%, 0);
174+
color: #ffffff;
175+
font-size: 3rem;
176+
font-weight: 100;
177+
text-align: center;
178+
opacity: 0;
179+
z-index: 2;
180+
pointer-events: none;
181+
}
182+
183+
.installing-text.active {
184+
opacity: 1;
185+
}
186+

src/index.css

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Lexend:[email protected]&family=Pacifico&display=swap');
22

33
:root {
4-
--window-background: #1a1a1f;
5-
4+
--color-primary: #A15EFF;
5+
--color-secondary: #D65EBA;
6+
--color-tertiary: #FF7E47;
7+
68
--color-black: #000000;
79
--color-white: #FFFFFF;
810
--color-gray: #808080;
9-
11+
1012
--color-danger: #FF4C4C;
1113
--color-success: #4CAF50;
1214
--color-warning: #FF9800;
15+
16+
--color-background: #111111;
1317
}
1418

1519
* {

0 commit comments

Comments
 (0)