Skip to content

Commit f26cce6

Browse files
committed
Nieve
1 parent f2577ec commit f26cce6

File tree

6 files changed

+181
-8
lines changed

6 files changed

+181
-8
lines changed

link_bio/assets/css/styles.css

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* General */
2+
13
body {
24
background-color: #1A1A1A;
35
}
@@ -7,9 +9,35 @@ a:hover {
79
}
810

911
@keyframes blinker {
10-
50% { opacity: 0; }
12+
50% {
13+
opacity: 0;
14+
}
1115
}
1216

1317
.blink {
1418
animation: blinker 1.5s linear infinite;
1519
}
20+
21+
/* Snow */
22+
23+
#SnowflakeContainer {
24+
position: absolute;
25+
left: 0px;
26+
top: 0px;
27+
}
28+
29+
.snowflake {
30+
padding-left: 15px;
31+
font-family: Cambria, Georgia, serif;
32+
font-size: 14px;
33+
line-height: 24px;
34+
position: fixed;
35+
color: #F7F7F7;
36+
user-select: none;
37+
z-index: 1000;
38+
pointer-events: none;
39+
}
40+
41+
.snowflake:hover {
42+
cursor: default;
43+
}

link_bio/assets/js/snowflakes.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { useEffect } from 'react';
2+
3+
export function Snowflakes() {
4+
5+
useEffect(() => {
6+
function handlePageChange() {
7+
clearSnowflakes();
8+
generateSnowflakes();
9+
}
10+
11+
function clearSnowflakes() {
12+
const snowflakes = document.querySelectorAll(".snowflake");
13+
snowflakes.forEach(snowflake => snowflake.remove());
14+
}
15+
16+
function getSupportedPropertyName(properties) {
17+
for (var i = 0; i < properties.length; i++) {
18+
if (typeof document.body.style[properties[i]] !== "undefined") {
19+
return properties[i];
20+
}
21+
}
22+
return null;
23+
}
24+
25+
class Snowflake {
26+
constructor(element, speed, xPos, yPos) {
27+
this.element = element;
28+
this.speed = speed;
29+
this.xPos = xPos;
30+
this.yPos = yPos;
31+
this.counter = 0;
32+
this.sign = Math.random() < 0.5 ? 1 : -1;
33+
this.element.style.opacity = 0.1 + Math.random();
34+
this.element.style.fontSize = 12 + 50 * Math.random() + 'px';
35+
}
36+
37+
update() {
38+
this.counter += this.speed / 5000;
39+
this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
40+
this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
41+
setTranslate3DTransform(this.element, Math.round(this.xPos), Math.round(this.yPos));
42+
43+
if (this.yPos > browserHeight) {
44+
this.yPos = -50;
45+
}
46+
}
47+
}
48+
49+
function setTranslate3DTransform(element, x, y) {
50+
var transform = "translate3d(" + x + "px, " + y + "px, 0)";
51+
element.style[transformProperty] = transform;
52+
}
53+
54+
function generateSnowflakes() {
55+
var originalSnowflake = document.querySelector(".snowflake");
56+
if (!originalSnowflake) {
57+
console.error("No element with class 'snowflake' found");
58+
return;
59+
}
60+
var container = originalSnowflake.parentNode;
61+
browserWidth = document.documentElement.clientWidth;
62+
browserHeight = document.documentElement.clientHeight;
63+
64+
for (var i = 0; i < numberOfSnowflakes; i++) {
65+
var clone = originalSnowflake.cloneNode(true);
66+
container.appendChild(clone);
67+
var xPos = getPosition(50, browserWidth);
68+
var yPos = getPosition(50, browserHeight);
69+
var speed = 5 + 40 * Math.random();
70+
var snowflake = new Snowflake(clone, speed, xPos, yPos);
71+
snowflakes.push(snowflake);
72+
}
73+
container.removeChild(originalSnowflake);
74+
moveSnowflakes();
75+
}
76+
77+
function moveSnowflakes() {
78+
for (var i = 0; i < snowflakes.length; i++) {
79+
var snowflake = snowflakes[i];
80+
snowflake.update();
81+
}
82+
if (resetPosition) {
83+
browserWidth = document.documentElement.clientWidth;
84+
browserHeight = document.documentElement.clientHeight;
85+
for (var i = 0; i < snowflakes.length; i++) {
86+
var snowflake = snowflakes[i];
87+
snowflake.xPos = getPosition(50, browserWidth);
88+
snowflake.yPos = getPosition(50, browserHeight);
89+
}
90+
resetPosition = false;
91+
}
92+
requestAnimationFrame(moveSnowflakes);
93+
}
94+
95+
function getPosition(offset, size) {
96+
return Math.round(-1 * offset + Math.random() * (size + 2 * offset));
97+
}
98+
99+
function setResetFlag() {
100+
resetPosition = true;
101+
}
102+
103+
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
104+
var transforms = ["transform", "msTransform", "webkitTransform", "mozTransform", "oTransform"];
105+
var transformProperty = getSupportedPropertyName(transforms);
106+
var snowflakes = [];
107+
var browserWidth;
108+
var browserHeight;
109+
var numberOfSnowflakes = 25;
110+
var resetPosition = false;
111+
112+
generateSnowflakes();
113+
window.addEventListener("resize", setResetFlag, false);
114+
window.addEventListener("popstate", handlePageChange, false);
115+
116+
return () => {
117+
window.removeEventListener("resize", setResetFlag, false);
118+
window.removeEventListener("popstate", handlePageChange, false);
119+
};
120+
}, []);
121+
122+
return null;
123+
}
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import reflex as rx
2-
import link_bio.styles.styles as styles
2+
3+
from link_bio import conf
4+
from link_bio.lib.snow import snow
35
from link_bio.routes import Route
4-
from link_bio.styles.styles import Size
56
from link_bio.styles.colors import Color
7+
from link_bio.styles.styles import Size
68

79

810
def navbar() -> rx.Component:
@@ -13,15 +15,16 @@ def navbar() -> rx.Component:
1315
width="auto",
1416
height=Size.LARGE.value,
1517
justify="start",
16-
alt=f"MoureDev logo"
18+
alt="MoureDev logo",
1719
),
18-
href=Route.INDEX.value
20+
href=Route.INDEX.value,
1921
),
22+
rx.cond(conf.SNOW, snow()),
2023
position="sticky",
2124
bg=Color.DARK.value,
2225
border_bottom="1px solid rgba(247, 247, 247, 0.2)",
2326
padding_x=Size.BIG.value,
2427
padding_y=Size.DEFAULT.value,
2528
z_index="999",
26-
top="0"
29+
top="0",
2730
)

link_bio/link_bio/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SNOW = True

link_bio/link_bio/lib/snow.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import reflex as rx
2+
3+
4+
class Snowflakes(rx.Component):
5+
tag = "Snowflakes"
6+
library = "/public/js/snowflakes.js"
7+
8+
9+
snowflakes = Snowflakes.create
10+
11+
12+
def snow() -> rx.Component:
13+
return rx.el.div(
14+
rx.el.p("*", class_name="snowflake"),
15+
snowflakes(),
16+
id="SnowflakeContainer",
17+
aria_hidden="true",
18+
)

link_bio/requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
pip==25.2
2-
reflex==0.8.11
1+
pip==25.3
2+
reflex==0.8.24.post1
33
python-dotenv==1.0.1
44
supabase==2.13.0
55
configcat-client==9.0.4

0 commit comments

Comments
 (0)