ade21ee4e0109c70e29860d5393306e48e6a44d3 lrnassar Mon Mar 16 16:38:58 2026 -0700 Adding keyboard navigation accessibility to the Genome Browser menu bar and all main CGI pages. Converts non-focusable menu bar span elements to keyboard-accessible buttons using the W3C disclosure navigation pattern, adds aria-expanded state for screen readers, skip navigation link, and main content landmark. Also adds a Keyboard Navigation section to the accessibility page with screenshots. refs #37252 diff --git src/hg/lib/web.c src/hg/lib/web.c index b614bba99d1..829fe9d9214 100644 --- src/hg/lib/web.c +++ src/hg/lib/web.c @@ -233,30 +233,31 @@ printf("</HEAD>\n"); printBodyTag(stdout); htmlWarnBoxSetup(stdout);// Sets up a warning box which can be filled with errors as they occur puts(commonCssStyles()); } /* Put up the hot links bar. */ char *menuStr = menuBar(theCart, db); if(menuStr) { puts(menuStr); } +puts("<main id=\"mainContent\">"); webStartSectionTables(); if (withLogo) { puts("<TR><TH COLSPAN=1 ALIGN=\"left\">"); if (isEncode) { puts("<A HREF=\"http://www.genome.gov/10005107\" TARGET=\"_BLANK\">" "<IMG SRC=\"../images/ENCODE_scaleup_logo.png\" height=50 ALT=\"ENCODE Project at NHGRI\">" "</A>"); puts("<IMG SRC=\"../images/encodeDcc.jpg\" ALT=\"ENCODE Project at UCSC\">"); } else { puts("<IMG SRC=\"../images/title.jpg\">"); @@ -470,45 +471,47 @@ void webEndSectionTables() /* Finish with section tables (but don't do /BODY /HTML like * webEnd does. */ { webEndSection(); puts("</TD></TR></TABLE>\n"); } void webEnd() /* output the footer of the HTML page */ { if(!webInTextMode) { webEndSectionTables(); + puts("</main>"); #ifndef GBROWSE googleAnalytics(); #endif /* GBROWSE */ jsInlineFinish(); puts( "</BODY></HTML>"); webPopErrHandlers(); } } void webEndExtra(char *footer) /* output the footer of the HTML page with extra footer as desired */ { if(!webInTextMode) { webEndSectionTables(); + puts("</main>"); #ifndef GBROWSE googleAnalytics(); #endif /* GBROWSE */ jsInlineFinish(); if (footer) puts(footer); puts( "</BODY></HTML>"); webPopErrHandlers(); } } static void webStartGbOptionalBanner(struct cart *cart, char *db, char *title, boolean doBanner, boolean hgGateway) /* Start HTML with new header and footer design by JWest. Optionally display banner above menubar. Use flag with hgGateway, till that is migrated. @@ -539,43 +542,45 @@ , title); } freeMem(csp); webPushErrHandlersCartDb(cart, db); htmlWarnBoxSetup(stdout); // Add hotlinks bar char *navBar = menuBar(cart, db); if (navBar) { puts(navBar); // Override nice-menu.css's menu background and fonts: webIncludeResourceFile("gbAfterMenu.css"); } +puts("<main id=\"mainContent\">"); webHeadAlreadyOutputed = TRUE; errAbortSetDoContentType(FALSE); } void webStartGbNoBanner(struct cart *cart, char *db, char *title) /* Start HTML with new header and footer design by jWest, but no banner */ { webStartGbOptionalBanner(cart, db, title, FALSE, FALSE); } void webEndGb() /* End HTML that was started with webStartJWest. */ { +puts("</main>"); googleAnalytics(); jsInlineFinish(); puts("</body></html>"); webPopErrHandlers(); } void webStartJWest(struct cart *cart, char *db, char *title) /* Start HTML with new banner and footer design by jWest (with modifications). */ { webStartGbOptionalBanner(cart, db, title, TRUE, TRUE); } void webEndJWest() /* End HTML that was started with webStartJWest. */ {