Skip to content

Commit 6bfe239

Browse files
committed
feat: implement scroll-to-top button and background animations
1 parent 6391556 commit 6bfe239

9 files changed

Lines changed: 238 additions & 143 deletions

File tree

srcs/Layout/MainLayout.razor

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
@inherits LayoutComponentBase
2-
@using kfolio.Services
3-
@inject ThemeService ThemeService
42

53
<div class="bg-container">
64
<div class="shape blob-1"></div>
75
<div class="shape blob-2"></div>
86
<div class="shape blob-3"></div>
9-
10-
@Body
117
</div>
128

13-
@code {
14-
private string? _theme;
9+
@Body
1510

16-
protected override async Task OnInitializedAsync()
17-
{
18-
_theme = await ThemeService.GetAsync();
19-
}
20-
}
11+
<button class="scroll-to-top" @onclick="ScrollToTop" title="Go to top">
12+
⬆️
13+
</button>

srcs/Layout/MainLayout.razor.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using kfolio.Services;
2+
using Microsoft.AspNetCore.Components;
3+
using Microsoft.JSInterop;
4+
5+
namespace kfolio.Layout;
6+
7+
public partial class MainLayout
8+
{
9+
[Inject]
10+
private IJSRuntime JSRuntime { get; set; } = default!;
11+
12+
[Inject]
13+
private ThemeService ThemeService { get; set; } = default!;
14+
15+
private string? _theme;
16+
17+
protected override async Task OnInitializedAsync() =>
18+
_theme = await ThemeService.GetAsync();
19+
20+
private async Task ScrollToTop() =>
21+
await JSRuntime.InvokeVoidAsync("window.scrollTo", new { top = 0, behavior = "smooth" });
22+
}

srcs/Pages/Home.razor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ private async Task SetTheme(string theme)
1818
currentTheme = theme;
1919
await ThemeService.SetAsync(theme);
2020
}
21+
2122
private static class CvData
2223
{
2324
public static string Name = "Yaroslav Kyliushyk";

srcs/Pages/Home.razor.css

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,61 +9,6 @@
99
transition: background-color var(--transition-speed), color var(--transition-speed);
1010
}
1111

12-
.background-blobs {
13-
position: fixed;
14-
top: 0;
15-
left: 0;
16-
width: 100%;
17-
height: 100%;
18-
z-index: 0;
19-
pointer-events: none;
20-
overflow: hidden;
21-
}
22-
23-
.blob {
24-
position: absolute;
25-
border-radius: 50%;
26-
filter: blur(80px);
27-
opacity: 0.6;
28-
animation: float 10s infinite ease-in-out alternate;
29-
}
30-
31-
.blob-1 {
32-
width: 500px;
33-
height: 500px;
34-
background: var(--blob-color-1);
35-
top: -100px;
36-
left: -100px;
37-
}
38-
39-
.blob-2 {
40-
width: 400px;
41-
height: 400px;
42-
background: var(--blob-color-2);
43-
bottom: 20%;
44-
right: -50px;
45-
animation-delay: -2s;
46-
}
47-
48-
.blob-3 {
49-
width: 300px;
50-
height: 300px;
51-
background: var(--blob-color-3);
52-
bottom: -50px;
53-
left: 30%;
54-
animation-delay: -4s;
55-
}
56-
57-
@keyframes float {
58-
0% {
59-
transform: translate(0, 0);
60-
}
61-
62-
100% {
63-
transform: translate(30px, 50px);
64-
}
65-
}
66-
6712
.container {
6813
max-width: 1200px;
6914
margin: 0 auto;

srcs/wwwroot/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
<link rel="stylesheet" href="styles/themes.css" />
1717
<link rel="stylesheet" href="styles/startup-loader.css" />
1818
<link rel="stylesheet" href="styles/errors.css" />
19+
<link rel="stylesheet" href="styles/background.css" />
20+
<link rel="stylesheet" href="styles/scroll.css" />
1921
<link rel="stylesheet" href="styles/app.css" />
2022

2123
<link href="kfolio.styles.css" rel="stylesheet" />

srcs/wwwroot/scripts/theme.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,20 @@
4141
});
4242
}
4343
});
44+
45+
function handleScroll() {
46+
const btn = document.querySelector('.scroll-to-top');
47+
if (btn) {
48+
const scrolled = window.scrollY || window.pageYOffset || document.documentElement.scrollTop;
49+
if (scrolled > 100) {
50+
btn.classList.add('visible');
51+
} else {
52+
btn.classList.remove('visible');
53+
}
54+
}
55+
}
56+
57+
window.addEventListener('scroll', handleScroll);
58+
// Initial check
59+
setTimeout(handleScroll, 500);
4460
})();

srcs/wwwroot/styles/app.css

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -22,83 +22,6 @@ body {
2222
backdrop-filter: none;
2323
}
2424

25-
.bg-container {
26-
position: fixed;
27-
top: 0;
28-
left: 0;
29-
width: 100%;
30-
height: 100%;
31-
z-index: -1;
32-
overflow-y: auto;
33-
overflow-x: hidden;
34-
background-color: var(--bg-main);
35-
}
36-
37-
.shape {
38-
position: absolute;
39-
filter: blur(80px);
40-
opacity: 0.4;
41-
border-radius: 50%;
42-
transition: background-color var(--transition-speed);
43-
}
44-
45-
.blob-1 {
46-
width: 400px;
47-
height: 400px;
48-
background: var(--blob-color-1);
49-
top: -100px;
50-
right: -100px;
51-
animation: move-1 20s infinite alternate;
52-
}
53-
54-
.blob-2 {
55-
width: 300px;
56-
height: 300px;
57-
background: var(--blob-color-2);
58-
bottom: -50px;
59-
left: -50px;
60-
animation: move-2 25s infinite alternate;
61-
}
62-
63-
.blob-3 {
64-
width: 250px;
65-
height: 250px;
66-
background: var(--blob-color-3);
67-
top: 40%;
68-
left: 20%;
69-
animation: move-3 15s infinite alternate;
70-
}
71-
72-
@keyframes move-1 {
73-
from {
74-
transform: translate(0, 0);
75-
}
76-
77-
to {
78-
transform: translate(-100px, 100px);
79-
}
80-
}
81-
82-
@keyframes move-2 {
83-
from {
84-
transform: translate(0, 0);
85-
}
86-
87-
to {
88-
transform: translate(150px, -100px);
89-
}
90-
}
91-
92-
@keyframes move-3 {
93-
from {
94-
transform: translate(0, 0) scale(1);
95-
}
96-
97-
to {
98-
transform: translate(-50px, 50px) scale(1.2);
99-
}
100-
}
101-
10225
@media (max-width: 768px) {
10326
.main-grid {
10427
grid-template-columns: 1fr;

srcs/wwwroot/styles/background.css

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/* Global Background Shapes */
2+
.bg-container {
3+
position: fixed;
4+
top: 0;
5+
left: 0;
6+
width: 100%;
7+
height: 100%;
8+
z-index: -1;
9+
overflow: hidden;
10+
pointer-events: none;
11+
}
12+
13+
.shape {
14+
position: absolute;
15+
filter: blur(80px);
16+
opacity: 0.4;
17+
border-radius: 50%;
18+
transition: background-color var(--transition-speed);
19+
}
20+
21+
.blob-1 {
22+
width: 400px;
23+
height: 400px;
24+
background: var(--blob-color-1);
25+
top: -100px;
26+
right: -100px;
27+
animation: move-1 20s infinite alternate;
28+
}
29+
30+
.blob-2 {
31+
width: 300px;
32+
height: 300px;
33+
background: var(--blob-color-2);
34+
bottom: -50px;
35+
left: -50px;
36+
animation: move-2 25s infinite alternate;
37+
}
38+
39+
.blob-3 {
40+
width: 250px;
41+
height: 250px;
42+
background: var(--blob-color-3);
43+
top: 40%;
44+
left: 20%;
45+
animation: move-3 15s infinite alternate;
46+
}
47+
48+
@keyframes move-1 {
49+
from { transform: translate(0, 0); }
50+
to { transform: translate(-100px, 100px); }
51+
}
52+
53+
@keyframes move-2 {
54+
from { transform: translate(0, 0); }
55+
to { transform: translate(150px, -100px); }
56+
}
57+
58+
@keyframes move-3 {
59+
from { transform: translate(0, 0) scale(1); }
60+
to { transform: translate(-50px, 50px) scale(1.2); }
61+
}
62+
63+
/* Page Specific Blobs (from Home.razor) */
64+
.background-blobs {
65+
position: fixed;
66+
top: 0;
67+
left: 0;
68+
width: 100%;
69+
height: 100%;
70+
z-index: 0;
71+
pointer-events: none;
72+
overflow: hidden;
73+
}
74+
75+
.blob {
76+
position: absolute;
77+
border-radius: 50%;
78+
filter: blur(80px);
79+
opacity: 0.6;
80+
animation: float 10s infinite ease-in-out alternate;
81+
}
82+
83+
.cv-wrapper .blob-1 {
84+
width: 500px;
85+
height: 500px;
86+
background: var(--blob-color-1);
87+
top: -100px;
88+
left: -100px;
89+
}
90+
91+
.cv-wrapper .blob-2 {
92+
width: 400px;
93+
height: 400px;
94+
background: var(--blob-color-2);
95+
bottom: 20%;
96+
right: -50px;
97+
animation-delay: -2s;
98+
}
99+
100+
.cv-wrapper .blob-3 {
101+
width: 300px;
102+
height: 300px;
103+
background: var(--blob-color-3);
104+
bottom: -50px;
105+
left: 30%;
106+
animation-delay: -4s;
107+
}
108+
109+
@keyframes float {
110+
0% { transform: translate(0, 0); }
111+
100% { transform: translate(30px, 50px); }
112+
}

0 commit comments

Comments
 (0)