polishing ui

This commit is contained in:
FernandoJVideira committed 2026-09-12 13:31:50 +01:00
1 parent e5820a4890
commit ec0f73f560
4 files changed
+68 -17

No files matched your search

+8 -3
View File
@@ -5,6 +5,11 @@ import { motion } from "framer-motion";
const Footer = () => {
const { t, i18n } = useTranslation();
// Browsers report region variants (e.g. "en-US", "pt-BR"), not just the
// bare "en"/"pt" i18next is configured with - matching on that exactly
// would pick the wrong sized text class for most real visitors.
const currentLang = i18n.language?.startsWith("pt") ? "pt" : "en";
return (
<footer className="flex flex-col space-y-8 justify-center items-center mt-10 mb-8 px-6 pt-10">
<div className="w-full max-w-xs h-px bg-gradient-to-r from-transparent via-white/10 to-transparent" />
@@ -38,7 +43,7 @@ const Footer = () => {
<a
href="/tos"
className={
i18n.language === "en"
currentLang === "en"
? "footer-text hover:text-gold-light transition-colors"
: "footer-text-pt hover:text-gold-light transition-colors"
}
@@ -48,7 +53,7 @@ const Footer = () => {
<a
href="/privacy"
className={
i18n.language === "en"
currentLang === "en"
? "footer-text hover:text-gold-light transition-colors"
: "footer-text-pt hover:text-gold-light transition-colors"
}
@@ -59,7 +64,7 @@ const Footer = () => {
<p
className={
i18n.language === "en"
currentLang === "en"
? "footer-text text-center"
: "footer-text-pt text-center"
}
+50 -9
View File
@@ -31,26 +31,52 @@ const Navbar = () => {
];
useEffect(() => {
const handleScroll = () => {
// Each section's offset, measured once (and on resize) instead of on
// every scroll tick - getBoundingClientRect() forces a synchronous
// layout recalc, and calling it on every native scroll event (which
// fires far more often than the display's refresh rate during a fast
// swipe or a smooth-scroll animation) is what made scrolling feel
// sluggish: layout was being thrashed dozens of times a second.
let sectionTops: { path: string; top: number }[] = [];
const measureSections = () => {
sectionTops = navigation.map((item) => {
const el = document.getElementById(item.path);
const top = el
? el.getBoundingClientRect().top + window.scrollY
: Infinity;
return { path: item.path, top };
});
};
let ticking = false;
const updateFromScroll = () => {
setColorChange(window.scrollY >= 100);
// The active section is whichever nav target's start we've scrolled
// past most recently - not just "is it in the viewport", since a
// short section could otherwise never register as active at all.
let current = navigation[0].path;
for (const item of navigation) {
const el = document.getElementById(item.path);
if (!el) continue;
const top = el.getBoundingClientRect().top + window.scrollY;
for (const { path, top } of sectionTops) {
if (window.scrollY + NAVBAR_HEIGHT + 40 >= top) {
current = item.path;
current = path;
}
}
setActiveSection(current);
ticking = false;
};
handleScroll();
const handleScroll = () => {
if (ticking) return;
ticking = true;
requestAnimationFrame(updateFromScroll);
};
measureSections();
updateFromScroll();
window.addEventListener("scroll", handleScroll, { passive: true });
window.addEventListener("resize", measureSections);
const scrollPath = sessionStorage.getItem("scrollPath");
if (scrollPath) {
@@ -60,6 +86,7 @@ const Navbar = () => {
return () => {
window.removeEventListener("scroll", handleScroll);
window.removeEventListener("resize", measureSections);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -109,12 +136,26 @@ const Navbar = () => {
>
<div className={colorChange ? "px-4" : ""}>
<div
className={`relative mx-auto flex items-center justify-between transition-all duration-500 ${
className={`relative mx-auto flex items-center justify-between transition-[max-width,margin,padding] duration-500 ${
colorChange
? "mt-3 max-w-3xl rounded-full glass-nav shadow-glass-lg px-5 py-2.5"
? "mt-3 max-w-3xl px-5 py-2.5"
: "max-w-screen-xl px-4 py-3 md:px-8 md:py-5"
}`}
>
{/*
The glass material is its own layer, separate from the box
above whose size/margin is animating. backdrop-filter can't be
smoothly interpolated between "none" and "blur(20px)" - toggling
it on the same element that's also resizing is what produced a
seam along the bottom edge mid-transition. Here it's always
present and only crossfades via opacity, which is safe.
*/}
<div
className={`absolute inset-0 -z-10 rounded-full glass-nav shadow-glass-lg transition-opacity duration-500 ${
colorChange ? "opacity-100" : "opacity-0"
}`}
/>
<motion.a
href="Top"
whileTap={{ scale: 0.92 }}
+9 -4
View File
@@ -7,6 +7,11 @@ const Hero = () => {
const { t, i18n } = useTranslation();
const prefersReducedMotion = useReducedMotion();
// Browsers report region variants (e.g. "en-US", "pt-BR"), not just the
// bare "en"/"pt" i18next is configured with - matching on that exactly
// would pick the wrong sized text class for most real visitors.
const currentLang = i18n.language?.startsWith("pt") ? "pt" : "en";
const handleNavigation = (path: string) => {
const element = document.getElementById(path);
const navbarHeight = 110;
@@ -51,13 +56,13 @@ const Hero = () => {
/>
<div>
<motion.h1
className={i18n.language === "en" ? "hero-text" : "hero-text-pt"}
className={currentLang === "en" ? "hero-text" : "hero-text-pt"}
{...rise(0.05)}
>
{t("hero.heading.part1")}
</motion.h1>
<motion.h1
className={i18n.language === "en" ? "hero-text" : "hero-text-pt"}
className={currentLang === "en" ? "hero-text" : "hero-text-pt"}
{...rise(0.1)}
>
<span className="gold-text">{t("hero.heading.part2")}</span>
@@ -69,7 +74,7 @@ const Hero = () => {
<motion.div className="mx-5 lg:mx-0" {...rise(0.15)}>
<h2
className={
i18n.language === "en"
currentLang === "en"
? "hero-sub-text mt-4 md:mt-10"
: "hero-sub-text-pt mt-4 md:mt-10"
}
@@ -78,7 +83,7 @@ const Hero = () => {
</h2>
<h2
className={
i18n.language === "en" ? "hero-sub-text" : "hero-sub-text-pt"
currentLang === "en" ? "hero-sub-text" : "hero-sub-text-pt"
}
>
{t("hero.subheading.part2")}
+1 -1
View File
@@ -121,7 +121,7 @@ body {
background: rgba(10, 10, 13, 0.55);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
border-bottom: 1px solid rgba(250, 204, 151, 0.1);
border: 1px solid rgba(250, 204, 151, 0.1);
}
/* Heavier material for full takeover surfaces (mobile menu sheet) — a