Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 'use client'; import { cn } from '@/lib/core'; interface SkipLink { /** Target element ID (without #) */ targetId: string; /** Text to display for the skip link */ label: string; } interface AdminSkipLinksProps { /** Custom skip links (default: main content and navigation) */ links?: SkipLink[]; /** Optional className for custom styling */ className?: string; } const defaultLinks: SkipLink[] = [ { targetId: 'main-content', label: 'Skip to main content' }, { targetId: 'admin-sidebar', label: 'Skip to navigation' }, ]; /** * Skip links for keyboard accessibility. * * Provides hidden links that become visible on focus, allowing keyboard * users to skip repetitive navigation and jump to main content. * * Required: Target elements must have matching IDs (e.g., id="main-content") * * @example * ```tsx * // In admin layout * <AdminSkipLinks /> * <aside id="admin-sidebar">...</aside> * <main id="main-content">...</main> * ``` */ export function AdminSkipLinks({ links = defaultLinks, className, }: AdminSkipLinksProps) { return ( <div className={cn( 'fixed top-0 left-0 z-[100]', className )} > {links.map((link) => ( <a key={link.targetId} href={`#${link.targetId}`} className={cn( // Hidden by default, visible on focus 'sr-only focus:not-sr-only', // Styling when visible 'focus:absolute focus:top-2 focus:left-2', 'focus:z-50 focus:block', 'focus:px-4 focus:py-2', 'focus:bg-primary-600 focus:text-white', 'focus:rounded-md focus:shadow-lg', 'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-primary-600', 'text-sm font-medium', 'transition-none' )} onClick={(e) => { // Prevent URL change and smoothly scroll to target e.preventDefault(); const target = document.getElementById(link.targetId); if (target) { target.focus(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }} > {link.label} </a> ))} </div> ); } export default AdminSkipLinks; |