Skip to content

Commit 0a38711

Browse files
committed
chore: code optimization
1 parent e7a2e7a commit 0a38711

File tree

1 file changed

+50
-1
lines changed
  • apps/web/src/app/(main)/dashboard/newsletter

1 file changed

+50
-1
lines changed

apps/web/src/app/(main)/dashboard/newsletter/page.tsx

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ const NewsletterTimeline = () => {
1717
const [filterMonth, setFilterMonth] = useState<string>("all");
1818
const [filterYear, setFilterYear] = useState<string>("all");
1919
const [sortType, setSortType] = useState<"newest" | "oldest">("newest");
20+
const previousActiveElement = useRef<HTMLElement | null>(null);
21+
22+
const closeModal = () => {
23+
setSelectedNewsletter(null);
24+
setExpandingCard(null);
25+
previousActiveElement.current?.focus();
26+
};
27+
2028

2129
const parseDate = (dateStr: string): Date => {
2230
const months: Record<string, number> = {
@@ -42,7 +50,7 @@ const NewsletterTimeline = () => {
4250
Number(dayWithComma.replace(",", ""))
4351
);
4452
};
45-
53+
4654
const filteredNewsletters = newsletters
4755
.filter((n) => {
4856
const d = parseDate(n.date);
@@ -72,6 +80,45 @@ const NewsletterTimeline = () => {
7280
return () => clearTimeout(timer);
7381
}, []);
7482

83+
useEffect(() => {
84+
if (!selectedNewsletter) return;
85+
86+
const modal = document.getElementById("newsletter-modal");
87+
const firstFocusable = document.getElementById("modal-back-button");
88+
89+
// store old focus
90+
previousActiveElement.current = document.activeElement as HTMLElement;
91+
92+
// move focus into modal
93+
firstFocusable?.focus();
94+
95+
const handleTab = (e: KeyboardEvent) => {
96+
if (!modal) return;
97+
98+
const focusable = modal.querySelectorAll<HTMLElement>(
99+
'button, a, input, textarea, select, [tabindex]:not([tabindex="-1"])'
100+
);
101+
const first = focusable[0];
102+
const last = focusable[focusable.length - 1];
103+
104+
if (e.key === "Tab") {
105+
if (e.shiftKey && document.activeElement === first) {
106+
e.preventDefault();
107+
last.focus();
108+
} else if (!e.shiftKey && document.activeElement === last) {
109+
e.preventDefault();
110+
first.focus();
111+
}
112+
}
113+
};
114+
115+
document.addEventListener("keydown", handleTab);
116+
return () => {
117+
document.removeEventListener("keydown", handleTab);
118+
};
119+
}, [selectedNewsletter]);
120+
121+
75122
useEffect(() => {
76123
const observer = new IntersectionObserver(
77124
(entries) => {
@@ -372,6 +419,7 @@ const NewsletterTimeline = () => {
372419
{/* Full Article View */}
373420
{selectedNewsletter && (
374421
<div
422+
id="newsletter-modal"
375423
className="fixed inset-0 z-50 bg-[#0E0E10]/95 backdrop-blur-md animate-in fade-in duration-300"
376424
role="dialog"
377425
aria-modal="true"
@@ -388,6 +436,7 @@ const NewsletterTimeline = () => {
388436
<div className="max-w-4xl mx-auto px-4 py-16">
389437
{/* Back Button */}
390438
<button
439+
id="modal-back-button"
391440
onClick={() => {
392441
setSelectedNewsletter(null);
393442
setExpandingCard(null);

0 commit comments

Comments
 (0)