Reverted previous actions
This commit is contained in:
parent
b241fafce4
commit
621b8d3d1d
3 changed files with 7 additions and 102 deletions
|
|
@ -104,15 +104,12 @@ p { font-size: 1rem; line-height: 1.6; color: var(--foreground); }
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 150ms ease;
|
transition: background 150ms ease;
|
||||||
white-space: nowrap;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
}
|
||||||
.lang-switcher-btn:hover,
|
.lang-switcher-btn:hover {
|
||||||
.lang-switcher-btn:focus-visible {
|
background: rgba(255, 255, 255, 0.1);
|
||||||
background: rgba(255, 255, 255, 0.15);
|
|
||||||
}
|
}
|
||||||
.lang-switcher-btn.current {
|
.lang-switcher-btn.current {
|
||||||
background: rgba(255, 255, 255, 0.25);
|
background: rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Markdown content */
|
/* Markdown content */
|
||||||
|
|
@ -296,15 +293,6 @@ p { font-size: 1rem; line-height: 1.6; color: var(--foreground); }
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header container - prevent flex wrapping */
|
|
||||||
.app-header .container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hero */
|
/* Hero */
|
||||||
.hero {
|
.hero {
|
||||||
padding: 3rem 0;
|
padding: 3rem 0;
|
||||||
|
|
@ -538,7 +526,7 @@ p { font-size: 1rem; line-height: 1.6; color: var(--foreground); }
|
||||||
.lang-switcher {
|
.lang-switcher {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
background: transparent;
|
background: var(--color-red);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
|
|
@ -548,17 +536,9 @@ p { font-size: 1rem; line-height: 1.6; color: var(--foreground); }
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 0.375rem 0.625rem;
|
padding: 0.375rem 0.625rem;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: transparent;
|
|
||||||
transition: background 150ms ease;
|
|
||||||
white-space: nowrap;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
.lang-switcher a:hover,
|
|
||||||
.lang-switcher a:focus-visible {
|
|
||||||
background: rgba(255,255,255,0.15);
|
|
||||||
}
|
}
|
||||||
.lang-switcher a.current {
|
.lang-switcher a.current {
|
||||||
background: rgba(255,255,255,0.25);
|
background: rgba(255,255,255,0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
type ConstructionModalProps = {
|
type ConstructionModalProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
|
@ -8,8 +8,6 @@ type ConstructionModalProps = {
|
||||||
|
|
||||||
export function ConstructionModal({ isOpen, onClose }: ConstructionModalProps) {
|
export function ConstructionModal({ isOpen, onClose }: ConstructionModalProps) {
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const modalRef = useRef<HTMLDivElement>(null);
|
|
||||||
const previousActiveElement = useRef<HTMLElement | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMounted(true);
|
setMounted(true);
|
||||||
|
|
@ -18,80 +16,20 @@ export function ConstructionModal({ isOpen, onClose }: ConstructionModalProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
document.body.style.overflow = "hidden";
|
document.body.style.overflow = "hidden";
|
||||||
previousActiveElement.current = document.activeElement as HTMLElement;
|
|
||||||
|
|
||||||
// Focus the button inside the modal
|
|
||||||
setTimeout(() => {
|
|
||||||
const button = modalRef.current?.querySelector("button");
|
|
||||||
button?.focus();
|
|
||||||
}, 0);
|
|
||||||
} else {
|
} else {
|
||||||
document.body.style.overflow = "";
|
document.body.style.overflow = "";
|
||||||
// Restore focus to the element that opened the modal
|
|
||||||
previousActiveElement.current?.focus();
|
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
document.body.style.overflow = "";
|
document.body.style.overflow = "";
|
||||||
};
|
};
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
// Focus trap: prevent Tab from leaving the modal
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isOpen || !modalRef.current) return;
|
|
||||||
|
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
|
||||||
if (e.key !== "Tab") return;
|
|
||||||
|
|
||||||
const focusableElements = modalRef.current?.querySelectorAll(
|
|
||||||
"button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])"
|
|
||||||
);
|
|
||||||
if (!focusableElements || focusableElements.length === 0) return;
|
|
||||||
|
|
||||||
const firstElement = focusableElements[0] as HTMLElement;
|
|
||||||
const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;
|
|
||||||
const activeElement = document.activeElement;
|
|
||||||
|
|
||||||
if (e.shiftKey) {
|
|
||||||
// Shift+Tab on first element -> focus last element
|
|
||||||
if (activeElement === firstElement) {
|
|
||||||
e.preventDefault();
|
|
||||||
lastElement.focus();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Tab on last element -> focus first element
|
|
||||||
if (activeElement === lastElement) {
|
|
||||||
e.preventDefault();
|
|
||||||
firstElement.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("keydown", handleKeyDown);
|
|
||||||
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
||||||
}, [isOpen]);
|
|
||||||
|
|
||||||
// Close on Escape key
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isOpen) return;
|
|
||||||
|
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
|
||||||
if (e.key === "Escape") {
|
|
||||||
e.preventDefault();
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("keydown", handleKeyDown);
|
|
||||||
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
||||||
}, [isOpen, onClose]);
|
|
||||||
|
|
||||||
if (!mounted || !isOpen) return null;
|
if (!mounted || !isOpen) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="modal-overlay" onClick={onClose} aria-hidden="true" />
|
<div className="modal-overlay" onClick={onClose} aria-hidden="true" />
|
||||||
<div
|
<div
|
||||||
ref={modalRef}
|
|
||||||
className="modal-dialog"
|
className="modal-dialog"
|
||||||
role="alertdialog"
|
role="alertdialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,17 @@ const slides = [
|
||||||
|
|
||||||
export function ImageCarousel() {
|
export function ImageCarousel() {
|
||||||
const [index, setIndex] = useState(0);
|
const [index, setIndex] = useState(0);
|
||||||
const [isPlaying, setIsPlaying] = useState(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
|
||||||
|
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
setIndex((prev) => (prev + 1) % slides.length);
|
setIndex((prev) => (prev + 1) % slides.length);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, [isPlaying]);
|
}, []);
|
||||||
|
|
||||||
const goTo = (i: number) => setIndex(i % slides.length);
|
const goTo = (i: number) => setIndex(i % slides.length);
|
||||||
const prev = () => setIndex((prev) => (prev - 1 + slides.length) % slides.length);
|
const prev = () => setIndex((prev) => (prev - 1 + slides.length) % slides.length);
|
||||||
const next = () => setIndex((prev) => (prev + 1) % slides.length);
|
const next = () => setIndex((prev) => (prev + 1) % slides.length);
|
||||||
const togglePlayPause = () => setIsPlaying((prev) => !prev);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section aria-label="Destaques" className="carousel" role="region">
|
<section aria-label="Destaques" className="carousel" role="region">
|
||||||
|
|
@ -61,15 +57,6 @@ export function ImageCarousel() {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={togglePlayPause}
|
|
||||||
aria-label={isPlaying ? "Pausar carrossel" : "Reproduzir carrossel"}
|
|
||||||
className="carousel-btn carousel-play-btn"
|
|
||||||
title={isPlaying ? "Pausar" : "Reproduzir"}
|
|
||||||
>
|
|
||||||
{isPlaying ? "⏸" : "▶"}
|
|
||||||
</button>
|
|
||||||
<button type="button" onClick={next} aria-label="Próxima imagem" className="carousel-btn">›</button>
|
<button type="button" onClick={next} aria-label="Próxima imagem" className="carousel-btn">›</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue