Skip to content

Commit f836d98

Browse files
authored
Merge pull request #667 from AbelOsaretin/fix/wave10-seo-a11y-error-handling
fix: sitemap SEO contradiction, duplicate error UI, nested interactive elements, and menu keyboard navigation
2 parents 05cc04a + 8d6f698 commit f836d98

4 files changed

Lines changed: 62 additions & 15 deletions

File tree

‎src/app/rewards/page.tsx‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ export default function RewardsPage() {
2929
try {
3030
await claim(claimableId);
3131
addToast("Reward claimed successfully!", "success");
32-
} catch (err) {
32+
} catch {
3333
addToast("Failed to claim reward. Please try again.", "error");
34-
throw err;
3534
}
3635
};
3736

‎src/app/sitemap.ts‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
1818
changeFrequency: "daily",
1919
priority: 0.9,
2020
},
21-
{
22-
url: `${SITE_URL}/connect`,
23-
lastModified: new Date(),
24-
changeFrequency: "monthly",
25-
priority: 0.5,
26-
},
2721
];
2822

2923
let courseRoutes: MetadataRoute.Sitemap = [];

‎src/components/course/course-card.tsx‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { memo } from "react";
4-
import Link from "next/link";
4+
import { useRouter } from "next/navigation";
55
import Image from "next/image";
66
import { cn } from "@/lib/utils/cn";
77
import { Card, CardContent, CardFooter } from "@/components/ui/card";
@@ -44,19 +44,36 @@ export const CourseCard = memo(function CourseCard({
4444
onContinue,
4545
className,
4646
}: CourseCardProps) {
47+
const router = useRouter();
48+
49+
const handleNavigate = () => {
50+
router.push(`/courses/${course.id}`);
51+
};
52+
53+
const handleCardKeyDown = (e: React.KeyboardEvent) => {
54+
if (e.key === "Enter" || e.key === " ") {
55+
e.preventDefault();
56+
handleNavigate();
57+
}
58+
};
59+
4760
const handleEnroll = (e: React.MouseEvent) => {
48-
e.preventDefault();
61+
e.stopPropagation();
4962
onEnroll?.(course.id);
5063
};
5164

5265
const handleContinue = (e: React.MouseEvent) => {
53-
e.preventDefault();
66+
e.stopPropagation();
5467
onContinue?.(course.id);
5568
};
5669

5770
return (
58-
<Link href={`/courses/${course.id}`}>
5971
<Card
72+
role="link"
73+
tabIndex={0}
74+
aria-label={course.title}
75+
onClick={handleNavigate}
76+
onKeyDown={handleCardKeyDown}
6077
className={cn(
6178
"group cursor-pointer transition-all hover:shadow-lg hover:-translate-y-1",
6279
className,
@@ -107,9 +124,9 @@ export const CourseCard = memo(function CourseCard({
107124

108125
<div
109126
className="absolute top-2 right-2"
110-
onClick={(e) => e.preventDefault()}
127+
onClick={(e) => e.stopPropagation()}
111128
onKeyDown={(e) => {
112-
if (e.key === "Enter" || e.key === " ") e.preventDefault();
129+
if (e.key === "Enter" || e.key === " ") e.stopPropagation();
113130
}}
114131
>
115132
<DropdownMenu>
@@ -192,6 +209,5 @@ export const CourseCard = memo(function CourseCard({
192209
)}
193210
</CardFooter>
194211
</Card>
195-
</Link>
196212
);
197213
});

‎src/components/wallet/connect-button.tsx‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,48 @@ export function ConnectButton() {
2929
const [showMainnetConfirm, setShowMainnetConfirm] = useState(false);
3030
const dropdownRef = useRef<HTMLDivElement>(null);
3131
const triggerRef = useRef<HTMLButtonElement>(null);
32+
const menuRef = useRef<HTMLDivElement>(null);
3233

3334
const closeDropdown = useCallback(() => {
3435
setShowDropdown(false);
3536
triggerRef.current?.focus();
3637
}, []);
3738

39+
const getMenuItems = useCallback(() => {
40+
if (!menuRef.current) return [];
41+
return Array.from(
42+
menuRef.current.querySelectorAll<HTMLElement>('[role="menuitem"]')
43+
);
44+
}, []);
45+
46+
const handleMenuKeyDown = (e: React.KeyboardEvent) => {
47+
const items = getMenuItems();
48+
if (items.length === 0) return;
49+
50+
const currentIndex = items.findIndex(
51+
(item) => item === document.activeElement
52+
);
53+
54+
switch (e.key) {
55+
case "ArrowDown":
56+
e.preventDefault();
57+
items[(currentIndex + 1 + items.length) % items.length].focus();
58+
break;
59+
case "ArrowUp":
60+
e.preventDefault();
61+
items[(currentIndex - 1 + items.length) % items.length].focus();
62+
break;
63+
case "Home":
64+
e.preventDefault();
65+
items[0].focus();
66+
break;
67+
case "End":
68+
e.preventDefault();
69+
items[items.length - 1].focus();
70+
break;
71+
}
72+
};
73+
3874
useEffect(() => {
3975
if (!showDropdown) return;
4076

@@ -116,8 +152,10 @@ export function ConnectButton() {
116152

117153
{showDropdown && (
118154
<div
155+
ref={menuRef}
119156
className="absolute right-0 top-full mt-2 w-56 rounded-xl border border-gray-200 bg-white p-1.5 shadow-xl z-50 dark:border-gray-800 dark:bg-gray-900"
120157
role="menu"
158+
onKeyDown={handleMenuKeyDown}
121159
>
122160
<div className="px-3 py-2 border-b border-gray-100 dark:border-gray-800">
123161
<div className="text-xs text-gray-400 font-medium">Connected Wallet</div>

0 commit comments

Comments
 (0)