-
Notifications
You must be signed in to change notification settings - Fork 200
Expand file tree
/
Copy pathFooter.jsx
More file actions
121 lines (112 loc) · 3.19 KB
/
Footer.jsx
File metadata and controls
121 lines (112 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import React, { useState, useEffect, useRef } from "react";
import heartBeat from "./heart-beat.wav";
import typingSound from "./typing-sound.wav";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCode } from "@fortawesome/free-solid-svg-icons";
import styles from "./Footer.module.css";
const Footer = () => {
const [isMobile, setIsMobile] = useState(window.innerWidth < 640);
const heartAudioRef = useRef(null);
const typingAudioRef = useRef(null);
useEffect(() => {
// create audio objects once
heartAudioRef.current = new Audio(heartBeat);
typingAudioRef.current = new Audio(typingSound);
// make typing audio loop while hovered/focused and set comfortable volume
typingAudioRef.current.loop = true;
typingAudioRef.current.volume = 0.5;
function handleSize() {
setIsMobile(window.innerWidth < 640);
}
window.addEventListener("resize", handleSize);
return () => {
window.removeEventListener("resize", handleSize);
// cleanup audio
if (heartAudioRef.current) {
heartAudioRef.current.pause();
heartAudioRef.current = null;
}
if (typingAudioRef.current) {
typingAudioRef.current.pause();
typingAudioRef.current = null;
}
};
}, []);
const playHeartbeat = () => {
try {
if (heartAudioRef.current) {
heartAudioRef.current.currentTime = 0;
heartAudioRef.current.volume = 0.9;
void heartAudioRef.current.play();
}
} catch (e) {
// ignore play errors
}
};
const stopHeartbeat = () => {
try {
if (heartAudioRef.current) {
heartAudioRef.current.pause();
heartAudioRef.current.currentTime = 0;
}
} catch (e) {}
};
const playTypingSound = () => {
try {
if (typingAudioRef.current) {
typingAudioRef.current.currentTime = 0;
void typingAudioRef.current.play();
}
} catch (e) {}
};
const stopTypingSound = () => {
try {
if (typingAudioRef.current) {
typingAudioRef.current.pause();
typingAudioRef.current.currentTime = 0;
}
} catch (e) {}
};
return (
<footer className={styles["footer"]}>
<p className={styles["footer-message"]}>
<span
className={styles.codeIcon}
role="img"
aria-label="Made"
tabIndex={0}
onMouseEnter={playTypingSound}
onMouseLeave={stopTypingSound}
onFocus={playTypingSound}
onBlur={stopTypingSound}
>
Made
</span>{" "}
with{" "}
<span
className={styles["emoji"]}
role="img"
aria-label="heart"
onMouseEnter={playHeartbeat}
onMouseLeave={stopHeartbeat}
onFocus={playHeartbeat}
onBlur={stopHeartbeat}
tabIndex={0}
>
💙
</span>{" "}
{isMobile && <br />}
by the{" "}
<a
className={styles["footer-message-link"]}
href="https://github.com/BeforeIDieCode"
target="_blank"
rel="noopener noreferrer"
>
Before I Die (GitHub org)
</a>
</p>
</footer>
);
};
export default Footer;