fix(a11y): Batch E part 1 — labels, valid nesting, touch targets
- EmptyState: render <Link> as the button (a <button> inside <Link> was invalid and double-focusable); AboutPage <a href> -> <Link> (no full reload) - aria-label on icon-only controls: settings Back, conversation Refresh/Send, crew chat Send - Crew invite Accept/Decline raised to 44px touch targets
This commit is contained in:
parent
0468ed1c1b
commit
09e1612db7
6 changed files with 13 additions and 9 deletions
|
|
@ -431,6 +431,7 @@ export function CrewChat({
|
|||
type="submit"
|
||||
size="icon"
|
||||
disabled={isPending || !draft.trim()}
|
||||
aria-label="Send message"
|
||||
className="bg-teal-500 hover:bg-teal-600 text-black shrink-0"
|
||||
>
|
||||
{isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export function CrewInviteCard({
|
|||
size="sm"
|
||||
onClick={handleAccept}
|
||||
disabled={busy}
|
||||
className="h-8 flex-1 gap-1.5 bg-teal-500 font-bold text-black hover:bg-teal-600"
|
||||
className="min-h-11 flex-1 gap-1.5 bg-teal-500 font-bold text-black hover:bg-teal-600"
|
||||
>
|
||||
{accepting ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Check className="h-3.5 w-3.5" />}
|
||||
Accept
|
||||
|
|
@ -128,7 +128,7 @@ export function CrewInviteCard({
|
|||
variant="outline"
|
||||
onClick={handleDecline}
|
||||
disabled={busy}
|
||||
className="h-8 gap-1.5 border-white/15 text-gray-400 hover:bg-white/10 hover:text-white"
|
||||
className="min-h-11 gap-1.5 border-white/15 text-gray-400 hover:bg-white/10 hover:text-white"
|
||||
>
|
||||
{declining ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <X className="h-3.5 w-3.5" />}
|
||||
Decline
|
||||
|
|
|
|||
|
|
@ -63,11 +63,11 @@ function ActionButton({ action }: { action: EmptyStateAction }) {
|
|||
);
|
||||
|
||||
if (action.to) {
|
||||
// Single interactive element — a <button> nested in a <Link> was invalid
|
||||
// and double-focusable for assistive tech.
|
||||
return (
|
||||
<Link to={action.to} className="w-full sm:w-auto">
|
||||
<button type="button" className={classes}>
|
||||
{inner}
|
||||
</button>
|
||||
<Link to={action.to} className={classes}>
|
||||
{inner}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,11 +156,11 @@ Version: v0.1.0`;
|
|||
<p className="text-gray-300 mb-4 text-sm">
|
||||
SkateSpots is open source and community-driven. Contribute code, share spots, or help others get started.
|
||||
</p>
|
||||
<a href="/onboarding">
|
||||
<Link to="/onboarding">
|
||||
<Button className="gap-2 bg-[#ccff00] text-black hover:bg-[#ccff00]/90 font-bold uppercase w-full">
|
||||
Get Started
|
||||
</Button>
|
||||
</a>
|
||||
</Link>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ export default function ConversationPage() {
|
|||
{/* Header */}
|
||||
<div className="flex items-center gap-2 sm:gap-3 pb-3 sm:pb-4 border-b border-gray-800 flex-shrink-0">
|
||||
<Link to="/messages">
|
||||
<Button variant="ghost" size="icon" className="text-gray-400 hover:text-white">
|
||||
<Button variant="ghost" size="icon" aria-label="Back" className="text-gray-400 hover:text-white">
|
||||
<ArrowLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
|
@ -239,6 +239,7 @@ export default function ConversationPage() {
|
|||
size="icon"
|
||||
onClick={() => refetch()}
|
||||
disabled={isRefetching}
|
||||
aria-label="Refresh"
|
||||
className="text-gray-400 hover:text-white"
|
||||
>
|
||||
<RefreshCw className={cn("h-4 w-4", isRefetching && "animate-spin")} />
|
||||
|
|
@ -303,6 +304,7 @@ export default function ConversationPage() {
|
|||
<Button
|
||||
onClick={handleSend}
|
||||
disabled={!newMessage.trim() || isSending}
|
||||
aria-label="Send message"
|
||||
className="bg-[#ff0040] hover:bg-[#ff0040]/90 text-white h-[44px] w-[44px] sm:h-auto sm:w-auto p-0 sm:px-4 flex-shrink-0"
|
||||
>
|
||||
{isSending ? (
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ function BackHeader({ title, onBack }: { title: string; onBack: () => void }) {
|
|||
<div className="flex items-center gap-3 mb-5">
|
||||
<button
|
||||
onClick={onBack}
|
||||
aria-label="Back"
|
||||
className="flex items-center justify-center w-8 h-8 rounded-xl bg-white/5 hover:bg-white/10 active:scale-95 transition-all"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4 text-white" />
|
||||
|
|
|
|||
Loading…
Reference in a new issue