11// Skip to Main Content - Enhanced Accessibility Component
2- import { useEffect } from "react" ;
2+ import { useEffect , useState } from "react" ;
33
44export function SkipToContent ( ) {
5+ const [ announcement , setAnnouncement ] = useState ( "" ) ;
6+
57 useEffect ( ( ) => {
68 // Handle skip link click
79 const handleSkipClick = ( e : MouseEvent ) => {
@@ -12,6 +14,8 @@ export function SkipToContent() {
1214 if ( mainContent ) {
1315 mainContent . focus ( ) ;
1416 mainContent . scrollIntoView ( { behavior : "smooth" } ) ;
17+ setAnnouncement ( "Navigated to main content" ) ;
18+ setTimeout ( ( ) => setAnnouncement ( "" ) , 3000 ) ;
1519 }
1620 }
1721 } ;
@@ -24,6 +28,8 @@ export function SkipToContent() {
2428 if ( mainContent ) {
2529 mainContent . focus ( ) ;
2630 mainContent . scrollIntoView ( { behavior : "smooth" } ) ;
31+ setAnnouncement ( "Jumped to main content using keyboard shortcut" ) ;
32+ setTimeout ( ( ) => setAnnouncement ( "" ) , 3000 ) ;
2733 }
2834 }
2935 } ;
@@ -37,47 +43,72 @@ export function SkipToContent() {
3743 } ;
3844 } , [ ] ) ;
3945
46+ const skipLinkStyle = {
47+ position : "absolute" as const ,
48+ left : "-9999px" ,
49+ top : "1rem" ,
50+ zIndex : 9999 ,
51+ padding : "0.875rem 1.5rem" ,
52+ backgroundColor : "hsl(262.1, 83.3%, 57.8%)" ,
53+ color : "white" ,
54+ textDecoration : "none" ,
55+ borderRadius : "0.5rem" ,
56+ fontWeight : 600 ,
57+ fontSize : "0.875rem" ,
58+ transition : "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)" ,
59+ boxShadow : "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)" ,
60+ border : "2px solid transparent" ,
61+ } ;
62+
63+ const focusedStyle = {
64+ left : "1rem" ,
65+ outline : "3px solid white" ,
66+ outlineOffset : "2px" ,
67+ border : "2px solid hsl(262.1, 83.3%, 70%)" ,
68+ transform : "scale(1.05)" ,
69+ } ;
70+
4071 return (
4172 < >
4273 < a
4374 href = "#main-content"
4475 className = "skip-to-content"
45- aria-label = "Skip to main content"
46- role = "navigation"
47- style = { {
48- position : "absolute" ,
49- left : "-9999px" ,
50- zIndex : 999 ,
51- padding : "1rem 1.5rem" ,
52- backgroundColor : "hsl(262.1, 83.3%, 57.8%)" ,
53- color : "white" ,
54- textDecoration : "none" ,
55- borderRadius : "0 0 0.375rem 0.375rem" ,
56- fontWeight : 600 ,
57- fontSize : "0.875rem" ,
58- transition : "left 0.2s ease-in-out" ,
59- boxShadow : "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)" ,
60- } }
76+ aria-label = "Skip to main content - Press Enter or Ctrl+/"
77+ style = { skipLinkStyle }
6178 onFocus = { ( e ) => {
62- e . currentTarget . style . left = "1rem" ;
63- e . currentTarget . style . top = "1rem" ;
64- e . currentTarget . style . outline = "3px solid hsl(262.1, 83.3%, 57.8%)" ;
65- e . currentTarget . style . outlineOffset = "2px" ;
79+ Object . assign ( e . currentTarget . style , focusedStyle ) ;
6680 } }
6781 onBlur = { ( e ) => {
6882 e . currentTarget . style . left = "-9999px" ;
6983 e . currentTarget . style . outline = "none" ;
84+ e . currentTarget . style . border = "2px solid transparent" ;
85+ e . currentTarget . style . transform = "scale(1)" ;
86+ } }
87+ onMouseEnter = { ( e ) => {
88+ if ( document . activeElement === e . currentTarget ) {
89+ e . currentTarget . style . backgroundColor = "hsl(262.1, 83.3%, 65%)" ;
90+ }
91+ } }
92+ onMouseLeave = { ( e ) => {
93+ e . currentTarget . style . backgroundColor = "hsl(262.1, 83.3%, 57.8%)" ;
7094 } }
7195 >
72- Skip to Main Content (Ctrl+/)
96+ ⚡ Skip to Main Content < kbd style = { {
97+ marginLeft : "0.5rem" ,
98+ padding : "0.125rem 0.375rem" ,
99+ backgroundColor : "rgba(255,255,255,0.2)" ,
100+ borderRadius : "0.25rem" ,
101+ fontSize : "0.75rem" ,
102+ fontWeight : 400
103+ } } > Ctrl+/</ kbd >
73104 </ a >
74105 < div
75106 role = "status"
76- aria-live = "polite "
107+ aria-live = "assertive "
77108 aria-atomic = "true"
78109 className = "sr-only"
79110 >
80- Press Tab to navigate, Ctrl+/ to skip to main content
111+ { announcement || " Press Tab to navigate, Ctrl+/ to skip to main content" }
81112 </ div >
82113 </ >
83114 ) ;
0 commit comments