Skip to content

Commit 63a5a90

Browse files
Add home and Back to top button (#1681)
* Add home and Back to top button * updated back to top button
1 parent 647089a commit 63a5a90

7 files changed

Lines changed: 223 additions & 9 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
.back-to-top {
2+
position: fixed;
3+
bottom: 3rem;
4+
right: 2rem;
5+
left: auto;
6+
transform: none;
7+
z-index: 98;
8+
width: 56px;
9+
height: 56px;
10+
border-radius: 50%;
11+
background: var(--color-brand-primary);
12+
border: 3px solid #fff;
13+
color: #fff;
14+
cursor: pointer;
15+
display: flex;
16+
align-items: center;
17+
justify-content: center;
18+
font-size: 1.5rem;
19+
line-height: 1;
20+
padding: 0;
21+
box-shadow: 0 8px 24px rgba(0, 242, 254, 0.35), inset 0 0 20px rgba(255, 255, 255, 0.1);
22+
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
23+
animation: slideUpButton 0.4s ease-out;
24+
flex-shrink: 0;
25+
backdrop-filter: blur(10px);
26+
}
27+
28+
/* Footer variant - inline button */
29+
.back-to-top--footer {
30+
position: static;
31+
bottom: auto;
32+
right: auto;
33+
width: 52px;
34+
height: 52px;
35+
margin: 0 0 0 auto;
36+
animation: none;
37+
}
38+
39+
@keyframes slideUpButton {
40+
from {
41+
opacity: 0;
42+
transform: translateY(40px) scale(0.8);
43+
}
44+
to {
45+
opacity: 1;
46+
transform: translateY(0) scale(1);
47+
}
48+
}
49+
50+
.back-to-top:hover {
51+
background: var(--color-brand-primary);
52+
box-shadow: 0 12px 32px rgba(0, 242, 254, 0.5), inset 0 0 20px rgba(255, 255, 255, 0.2);
53+
transform: translateY(-6px) scale(1.08);
54+
border-color: #00f2fe;
55+
}
56+
57+
.back-to-top--footer:hover {
58+
transform: scale(1.08);
59+
}
60+
61+
.back-to-top:active {
62+
transform: translateY(-2px) scale(0.96);
63+
box-shadow: 0 4px 16px rgba(0, 242, 254, 0.4), inset 0 0 20px rgba(255, 255, 255, 0.1);
64+
}
65+
66+
/* Footer back-to-top container */
67+
.footer-back-to-top {
68+
margin-left: auto;
69+
display: flex;
70+
align-items: center;
71+
padding: 0 1rem;
72+
}
73+
74+
/* Arrow icon — perfectly centered inside the circle */
75+
.back-to-top-icon {
76+
width: 24px;
77+
height: 24px;
78+
stroke-width: 3;
79+
display: block;
80+
position: absolute;
81+
top: 50%;
82+
left: 50%;
83+
transform: translate(-50%, -50%);
84+
pointer-events: none;
85+
}
86+
87+
/* Home Page Specific Styles */
88+
body.home-page .back-to-top {
89+
background: rgba(0, 242, 254, 0.95);
90+
box-shadow: 0 6px 20px rgba(0, 242, 254, 0.4);
91+
}
92+
93+
body.home-page .back-to-top:hover {
94+
background: var(--color-brand-primary);
95+
box-shadow: 0 10px 28px rgba(0, 242, 254, 0.55);
96+
}
97+
98+
@media screen and (max-width: 768px) {
99+
.back-to-top {
100+
bottom: 2.5rem;
101+
right: 1.5rem;
102+
width: 52px;
103+
height: 52px;
104+
font-size: 1.3rem;
105+
}
106+
107+
.footer-back-to-top {
108+
padding: 0 0.5rem;
109+
}
110+
}
111+
112+
@media screen and (max-width: 480px) {
113+
.back-to-top {
114+
bottom: 2rem;
115+
right: 1rem;
116+
width: 48px;
117+
height: 48px;
118+
font-size: 1.1rem;
119+
border: 2px solid #fff;
120+
}
121+
122+
.back-to-top--footer {
123+
width: 48px;
124+
height: 48px;
125+
}
126+
127+
.footer-back-to-top {
128+
padding: 0;
129+
flex: 1;
130+
text-align: right;
131+
}
132+
}
133+
134+
@media screen and (max-height: 700px) {
135+
.back-to-top {
136+
bottom: 2rem;
137+
}
138+
}
139+
140+
@media screen and (max-height: 600px) {
141+
.back-to-top {
142+
bottom: 1.5rem;
143+
}
144+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { useState, useEffect } from 'react';
2+
import { FiArrowUp } from 'react-icons/fi';
3+
import './BackToTop.css';
4+
5+
const BackToTop = ({ isInFooter = false }) => {
6+
const [isVisible, setIsVisible] = useState(isInFooter);
7+
8+
const toggleVisibility = () => {
9+
if (isInFooter) {
10+
setIsVisible(true);
11+
} else if (window.pageYOffset > 400) {
12+
setIsVisible(true);
13+
} else {
14+
setIsVisible(false);
15+
}
16+
};
17+
18+
const scrollToTop = () => {
19+
window.scrollTo({
20+
top: 0,
21+
behavior: 'smooth'
22+
});
23+
};
24+
25+
useEffect(() => {
26+
if (!isInFooter) {
27+
window.addEventListener('scroll', toggleVisibility);
28+
29+
return () => {
30+
window.removeEventListener('scroll', toggleVisibility);
31+
};
32+
}
33+
}, [isInFooter]);
34+
35+
return (
36+
<>
37+
{isVisible && (
38+
<button
39+
aria-label="Back to top"
40+
className={`back-to-top ${isInFooter ? 'back-to-top--footer' : ''}`}
41+
title="Back to top"
42+
type="button"
43+
onClick={scrollToTop}
44+
>
45+
<FiArrowUp className="back-to-top-icon" />
46+
<span className="sr-only">Back to top</span>
47+
</button>
48+
)}
49+
</>
50+
);
51+
};
52+
53+
export default BackToTop;

src/common/footer/ExtendedFooter.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { FaInstagram, FaXTwitter } from 'react-icons/fa6';
77
import { IoAddSharp, IoLogoRss } from 'react-icons/io5';
88
import { MdManageSearch } from 'react-icons/md';
99
import { Link } from 'react-router-dom';
10+
import BackToTop from 'common/components/BackToTop';
1011

1112
const ExtendedFooter = () => {
1213
const { showShareModal, setShowShareModal } = useSearchContext();
@@ -58,6 +59,7 @@ const ExtendedFooter = () => {
5859
return (
5960
<div className="app-footer--home app-footer">
6061
<div className="app-footer-body">
62+
<BackToTop />
6163
<div className="body-primary">
6264
<h3>
6365
<span className="sr-only">ReactPlay</span>

src/common/footer/Footer.jsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ const Footer = () => {
44
return (
55
<footer className="app-footer text-center">
66
<hr className="separater" />
7-
<div className="flex justify-center items-center py-2">
8-
<p className="app-footer-text">
9-
ReactPlay - The MIT License (MIT) Copyright &copy;
10-
{new Date().getFullYear()} . Powered by{' '}
11-
<Link className="text-link-default" to="/tech-stacks">
12-
Top Notch Tech Stacks
13-
</Link>
14-
.
15-
</p>
7+
<div className="footer-content-wrapper">
8+
<div className="flex justify-center items-center py-2">
9+
<p className="app-footer-text">
10+
ReactPlay - The MIT License (MIT) Copyright &copy;
11+
{new Date().getFullYear()} . Powered by{' '}
12+
<Link className="text-link-default" to="/tech-stacks">
13+
Top Notch Tech Stacks
14+
</Link>
15+
.
16+
</p>
17+
</div>
1618
</div>
1719
</footer>
1820
);

src/common/header/HeaderNav.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { FaXTwitter, FaDiscord } from 'react-icons/fa6';
66
import { BiMoney } from 'react-icons/bi';
77
import { IoAddSharp, IoShareSocial, IoHeartSharp } from 'react-icons/io5';
88
import { MdManageSearch, MdClose, MdEvent } from 'react-icons/md';
9+
import { AiOutlineHome } from 'react-icons/ai';
910
import SocialShare from 'common/components/SocialShare';
1011
import { GoX } from 'react-icons/go';
1112
import { Modal, Box, Typography, Menu } from '@mui/material';
@@ -51,6 +52,15 @@ const HeaderNav = ({ showBrowse }) => {
5152
const modalClose = () => setShowShareModal(!showShareModal);
5253

5354
const NavLinks = [
55+
{
56+
type: 'Link',
57+
testId: 'home-btn',
58+
title: 'Home',
59+
to: '/',
60+
icon: AiOutlineHome,
61+
iconClass: 'icon home-icon',
62+
label: 'Home'
63+
},
5464
{
5565
type: 'Link',
5666
testId: 'leaderboard-btn',

src/common/playideas/PlayIdeas.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { RiChatNewLine } from 'react-icons/ri';
55
import LevelBadge from 'common/components/LevelBadge';
66
import './playIdeas.css';
77
import { PLAY_DOC_LINK } from 'constants';
8+
import BackToTop from 'common/components/BackToTop';
89

910
const PlayIdeas = () => {
1011
const [ideas, setIdeas] = useState([]);
@@ -57,6 +58,7 @@ const PlayIdeas = () => {
5758
<main className="app-body app-body-overflow-hidden">
5859
<div className="playideas-container">
5960
<div className="playideas-header">
61+
<BackToTop />
6062
<div>
6163
<h1 className="header-title">
6264
Play Ideas

src/common/routing/RouteDefs.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
Testimonials
1515
} from 'common';
1616
import PlayList from 'common/playlists/PlayList';
17+
import BackToTop from 'common/components/BackToTop';
1718
import { BrowserRouter, Route, Routes } from 'react-router-dom';
1819
import { NhostClient, NhostReactProvider } from '@nhost/react';
1920
import BadgesDashboard from 'common/badges-dashboard';

0 commit comments

Comments
 (0)