[{"data":1,"prerenderedAt":3377},["ShallowReactive",2],{"site-header-nav":3,"page-\u002Freact-nextjs-accessibility-patterns\u002F":156,"content-navigation":3303},[4,66,70],{"title":5,"path":6,"stem":7,"children":8},"Core Accessibility Principles For Modern Frameworks","\u002Fcore-accessibility-principles-for-modern-frameworks","core-accessibility-principles-for-modern-frameworks",[9,12,18,24,36,48,60],{"title":10,"path":6,"stem":11},"Core Accessibility Principles for Modern Frameworks","core-accessibility-principles-for-modern-frameworks\u002Findex",{"title":13,"path":14,"stem":15,"children":16},"Accessible Color Contrast & Theming","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Faccessible-color-contrast-theming","core-accessibility-principles-for-modern-frameworks\u002Faccessible-color-contrast-theming\u002Findex",[17],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21,"children":22},"Accessible Form Validation & Error States in Modern Frameworks","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Faccessible-form-validation-error-states","core-accessibility-principles-for-modern-frameworks\u002Faccessible-form-validation-error-states\u002Findex",[23],{"title":19,"path":20,"stem":21},{"title":25,"path":26,"stem":27,"children":28},"Focus Management Strategies for SPAs","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Ffocus-management-strategies-for-spas","core-accessibility-principles-for-modern-frameworks\u002Ffocus-management-strategies-for-spas\u002Findex",[29,30],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":34},"Handling Focus Restoration After Dynamic Route Changes","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Ffocus-management-strategies-for-spas\u002Fhandling-focus-restoration-after-dynamic-route-changes","core-accessibility-principles-for-modern-frameworks\u002Ffocus-management-strategies-for-spas\u002Fhandling-focus-restoration-after-dynamic-route-changes\u002Findex",[35],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":40},"Keyboard Navigation Patterns for Modals","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Fkeyboard-navigation-patterns-for-modals","core-accessibility-principles-for-modern-frameworks\u002Fkeyboard-navigation-patterns-for-modals\u002Findex",[41,42],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45,"children":46},"Building Accessible Dropdowns Without External UI Kits","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Fkeyboard-navigation-patterns-for-modals\u002Fbuilding-accessible-dropdowns-without-external-ui-kits","core-accessibility-principles-for-modern-frameworks\u002Fkeyboard-navigation-patterns-for-modals\u002Fbuilding-accessible-dropdowns-without-external-ui-kits\u002Findex",[47],{"title":43,"path":44,"stem":45},{"title":49,"path":50,"stem":51,"children":52},"Screen Reader Compatibility Testing for Modern Frameworks","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Fscreen-reader-compatibility-testing","core-accessibility-principles-for-modern-frameworks\u002Fscreen-reader-compatibility-testing\u002Findex",[53,54],{"title":49,"path":50,"stem":51},{"title":55,"path":56,"stem":57,"children":58},"Testing ARIA Live Regions with Jest and Testing Library","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Fscreen-reader-compatibility-testing\u002Ftesting-aria-live-regions-with-jest-and-testing-library","core-accessibility-principles-for-modern-frameworks\u002Fscreen-reader-compatibility-testing\u002Ftesting-aria-live-regions-with-jest-and-testing-library\u002Findex",[59],{"title":55,"path":56,"stem":57},{"title":61,"path":62,"stem":63,"children":64},"Semantic HTML vs ARIA in Component Trees","\u002Fcore-accessibility-principles-for-modern-frameworks\u002Fsemantic-html-vs-aria-in-component-trees","core-accessibility-principles-for-modern-frameworks\u002Fsemantic-html-vs-aria-in-component-trees\u002Findex",[65],{"title":61,"path":62,"stem":63},{"title":67,"path":68,"stem":69},"Modern Framework Accessibility","\u002F","index",{"title":71,"path":72,"stem":73,"children":74},"React Nextjs Accessibility Patterns","\u002Freact-nextjs-accessibility-patterns","react-nextjs-accessibility-patterns",[75,78,90,102,108,126,144],{"title":76,"path":72,"stem":77},"React & Next.js Accessibility Patterns","react-nextjs-accessibility-patterns\u002Findex",{"title":79,"path":80,"stem":81,"children":82},"Accessible Component Libraries in React","\u002Freact-nextjs-accessibility-patterns\u002Faccessible-component-libraries-in-react","react-nextjs-accessibility-patterns\u002Faccessible-component-libraries-in-react\u002Findex",[83,84],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87,"children":88},"Building Accessible Tabs in React Without Radix UI","\u002Freact-nextjs-accessibility-patterns\u002Faccessible-component-libraries-in-react\u002Fbuilding-accessible-tabs-in-react-without-radix-ui","react-nextjs-accessibility-patterns\u002Faccessible-component-libraries-in-react\u002Fbuilding-accessible-tabs-in-react-without-radix-ui\u002Findex",[89],{"title":85,"path":86,"stem":87},{"title":91,"path":92,"stem":93,"children":94},"Dynamic Content & State Announcements in React & Next.js","\u002Freact-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements","react-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002Findex",[95,96],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99,"children":100},"Implementing React Context for Global Accessibility Preferences","\u002Freact-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002Freact-context-for-global-accessibility-preferences","react-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002Freact-context-for-global-accessibility-preferences\u002Findex",[101],{"title":97,"path":98,"stem":99},{"title":103,"path":104,"stem":105,"children":106},"Form Handling with React Hook Form & Accessibility","\u002Freact-nextjs-accessibility-patterns\u002Fform-handling-with-react-hook-form-a11y","react-nextjs-accessibility-patterns\u002Fform-handling-with-react-hook-form-a11y\u002Findex",[107],{"title":103,"path":104,"stem":105},{"title":109,"path":110,"stem":111,"children":112},"Next.js App Router & A11y: Implementation Guide for Modern Frameworks","\u002Freact-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y","react-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y\u002Findex",[113,114,120],{"title":109,"path":110,"stem":111},{"title":115,"path":116,"stem":117,"children":118},"Implementing Skip Links in Next.js App Router: A Step-by-Step Guide","\u002Freact-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y\u002Fimplementing-skip-links-in-nextjs-app-router","react-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y\u002Fimplementing-skip-links-in-nextjs-app-router\u002Findex",[119],{"title":115,"path":116,"stem":117},{"title":121,"path":122,"stem":123,"children":124},"Next.js Dynamic Imports and Keyboard Navigation: A Complete A11y Implementation Guide","\u002Freact-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y\u002Fnextjs-dynamic-imports-and-keyboard-navigation","react-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y\u002Fnextjs-dynamic-imports-and-keyboard-navigation\u002Findex",[125],{"title":121,"path":122,"stem":123},{"title":127,"path":128,"stem":129,"children":130},"React Hooks for Accessibility: Implementation Patterns & State Management","\u002Freact-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility","react-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility\u002Findex",[131,132,138],{"title":127,"path":128,"stem":129},{"title":133,"path":134,"stem":135,"children":136},"Fixing Focus Trap Issues in React Portals","\u002Freact-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility\u002Ffixing-focus-trap-issues-in-react-portals","react-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility\u002Ffixing-focus-trap-issues-in-react-portals\u002Findex",[137],{"title":133,"path":134,"stem":135},{"title":139,"path":140,"stem":141,"children":142},"Making React useEffect Accessible for Screen Readers","\u002Freact-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility\u002Fmaking-react-useeffect-accessible-for-screen-readers","react-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility\u002Fmaking-react-useeffect-accessible-for-screen-readers\u002Findex",[143],{"title":139,"path":140,"stem":141},{"title":145,"path":146,"stem":147,"children":148},"Server Components & Client-Side Interactivity","\u002Freact-nextjs-accessibility-patterns\u002Fserver-components-client-side-interactivity","react-nextjs-accessibility-patterns\u002Fserver-components-client-side-interactivity\u002Findex",[149,150],{"title":145,"path":146,"stem":147},{"title":151,"path":152,"stem":153,"children":154},"Handling Accessible Modals in Next.js 14 Server Components","\u002Freact-nextjs-accessibility-patterns\u002Fserver-components-client-side-interactivity\u002Fhandling-accessible-modals-in-nextjs-14-server-components","react-nextjs-accessibility-patterns\u002Fserver-components-client-side-interactivity\u002Fhandling-accessible-modals-in-nextjs-14-server-components\u002Findex",[155],{"title":151,"path":152,"stem":153},{"id":157,"title":76,"body":158,"date":3296,"description":3297,"extension":3298,"image":3296,"meta":3299,"modifiedAt":3296,"navigation":305,"noindex":3300,"path":72,"publishedAt":3296,"seo":3301,"stem":77,"updatedAt":3296,"__hash__":3302},"content\u002Freact-nextjs-accessibility-patterns\u002Findex.md",{"type":159,"value":160,"toc":3285},"minimark",[161,164,168,174,204,209,226,229,234,237,245,530,536,538,542,545,556,913,918,920,924,927,942,1262,1267,1269,1273,1276,1296,1771,1776,1778,1782,1785,1800,2389,2397,2399,2403,2406,2409,2942,2951,2953,2957,2960,2963,3188,3193,3195,3199,3241,3243,3247,3256,3262,3275,3281],[162,163,76],"h1",{"id":73},[165,166,167],"p",{},"A comprehensive architectural blueprint for building WCAG-compliant interfaces using modern React and Next.js paradigms. This guide maps framework-specific rendering strategies, state management, and routing behaviors to established accessibility standards, ensuring scalable, inclusive UI development.",[165,169,170],{},[171,172,173],"strong",{},"Targeted WCAG 2.2 Success Criteria:",[175,176,177,184,189,194,199],"ul",{},[178,179,180],"li",{},[181,182,183],"code",{},"1.3.1 Info and Relationships",[178,185,186],{},[181,187,188],{},"2.1.1 Keyboard",[178,190,191],{},[181,192,193],{},"2.4.3 Focus Order",[178,195,196],{},[181,197,198],{},"4.1.2 Name, Role, Value",[178,200,201],{},[181,202,203],{},"4.1.3 Status Messages",[165,205,206],{},[171,207,208],{},"Architectural Key Points:",[175,210,211,214,223],{},[178,212,213],{},"Establish semantic HTML foundations before applying framework abstractions.",[178,215,216,217,222],{},"Leverage ",[218,219,221],"a",{"href":220},"\u002Freact-nextjs-accessibility-patterns\u002Freact-hooks-for-accessibility\u002F","React Hooks for Accessibility"," to encapsulate focus management and ARIA state logic.",[178,224,225],{},"Align component architecture with progressive enhancement and keyboard-first navigation principles.",[227,228],"hr",{},[230,231,233],"h2",{"id":232},"routing-architecture-navigation-flows","Routing Architecture & Navigation Flows",[165,235,236],{},"Next.js routing paradigms must be explicitly mapped to accessible, predictable navigation experiences for assistive technologies. Client-side navigation inherently suppresses full page reloads, which can silently strip screen readers of context if focus and announcements are not manually orchestrated.",[165,238,239,240,244],{},"Implement route transition announcements and focus restoration strategies to maintain spatial awareness. Configure client-side navigation boundaries using ",[218,241,243],{"href":242},"\u002Freact-nextjs-accessibility-patterns\u002Fnextjs-app-router-a11y\u002F","Next.js App Router & A11y"," to prevent screen reader page reload confusion. Standardize skip links, landmark roles, and heading hierarchies across layout templates to ensure consistent document structure.",[246,247,252],"pre",{"className":248,"code":249,"language":250,"meta":251,"style":251},"language-tsx shiki shiki-themes github-light github-dark","'use client';\nimport { useEffect, useRef } from 'react';\nimport { usePathname } from 'next\u002Fnavigation';\n\nexport function RouteFocusManager() {\n const pathname = usePathname();\n const mainHeadingRef = useRef\u003CHTMLHeadingElement>(null);\n\n useEffect(() => {\n \u002F\u002F 1. Announce route change to assistive technology\n const liveRegion = document.getElementById('route-announcer');\n if (liveRegion) {\n liveRegion.textContent = `Navigated to ${document.title}`;\n }\n \n \u002F\u002F 2. Programmatically restore focus to main content heading\n \u002F\u002F Ensures keyboard users don't lose their place after navigation\n mainHeadingRef.current?.focus({ preventScroll: true });\n }, [pathname]);\n\n return null; \u002F\u002F Logic-only component injected into root layout\n}\n","tsx","",[181,253,254,267,285,300,307,323,342,370,375,390,397,421,430,456,462,468,474,480,498,504,509,524],{"__ignoreMap":251},[255,256,259,263],"span",{"class":257,"line":258},"line",1,[255,260,262],{"class":261},"sZZnC","'use client'",[255,264,266],{"class":265},"sVt8B",";\n",[255,268,270,274,277,280,283],{"class":257,"line":269},2,[255,271,273],{"class":272},"szBVR","import",[255,275,276],{"class":265}," { useEffect, useRef } ",[255,278,279],{"class":272},"from",[255,281,282],{"class":261}," 'react'",[255,284,266],{"class":265},[255,286,288,290,293,295,298],{"class":257,"line":287},3,[255,289,273],{"class":272},[255,291,292],{"class":265}," { usePathname } ",[255,294,279],{"class":272},[255,296,297],{"class":261}," 'next\u002Fnavigation'",[255,299,266],{"class":265},[255,301,303],{"class":257,"line":302},4,[255,304,306],{"emptyLinePlaceholder":305},true,"\n",[255,308,310,313,316,320],{"class":257,"line":309},5,[255,311,312],{"class":272},"export",[255,314,315],{"class":272}," function",[255,317,319],{"class":318},"sScJk"," RouteFocusManager",[255,321,322],{"class":265},"() {\n",[255,324,326,329,333,336,339],{"class":257,"line":325},6,[255,327,328],{"class":272}," const",[255,330,332],{"class":331},"sj4cs"," pathname",[255,334,335],{"class":272}," =",[255,337,338],{"class":318}," usePathname",[255,340,341],{"class":265},"();\n",[255,343,345,347,350,352,355,358,361,364,367],{"class":257,"line":344},7,[255,346,328],{"class":272},[255,348,349],{"class":331}," mainHeadingRef",[255,351,335],{"class":272},[255,353,354],{"class":318}," useRef",[255,356,357],{"class":265},"\u003C",[255,359,360],{"class":318},"HTMLHeadingElement",[255,362,363],{"class":265},">(",[255,365,366],{"class":331},"null",[255,368,369],{"class":265},");\n",[255,371,373],{"class":257,"line":372},8,[255,374,306],{"emptyLinePlaceholder":305},[255,376,378,381,384,387],{"class":257,"line":377},9,[255,379,380],{"class":318}," useEffect",[255,382,383],{"class":265},"(() ",[255,385,386],{"class":272},"=>",[255,388,389],{"class":265}," {\n",[255,391,393],{"class":257,"line":392},10,[255,394,396],{"class":395},"sJ8bj"," \u002F\u002F 1. Announce route change to assistive technology\n",[255,398,400,402,405,407,410,413,416,419],{"class":257,"line":399},11,[255,401,328],{"class":272},[255,403,404],{"class":331}," liveRegion",[255,406,335],{"class":272},[255,408,409],{"class":265}," document.",[255,411,412],{"class":318},"getElementById",[255,414,415],{"class":265},"(",[255,417,418],{"class":261},"'route-announcer'",[255,420,369],{"class":265},[255,422,424,427],{"class":257,"line":423},12,[255,425,426],{"class":272}," if",[255,428,429],{"class":265}," (liveRegion) {\n",[255,431,433,436,439,442,445,448,451,454],{"class":257,"line":432},13,[255,434,435],{"class":265}," liveRegion.textContent ",[255,437,438],{"class":272},"=",[255,440,441],{"class":261}," `Navigated to ${",[255,443,444],{"class":265},"document",[255,446,447],{"class":261},".",[255,449,450],{"class":265},"title",[255,452,453],{"class":261},"}`",[255,455,266],{"class":265},[255,457,459],{"class":257,"line":458},14,[255,460,461],{"class":265}," }\n",[255,463,465],{"class":257,"line":464},15,[255,466,467],{"class":265}," \n",[255,469,471],{"class":257,"line":470},16,[255,472,473],{"class":395}," \u002F\u002F 2. Programmatically restore focus to main content heading\n",[255,475,477],{"class":257,"line":476},17,[255,478,479],{"class":395}," \u002F\u002F Ensures keyboard users don't lose their place after navigation\n",[255,481,483,486,489,492,495],{"class":257,"line":482},18,[255,484,485],{"class":265}," mainHeadingRef.current?.",[255,487,488],{"class":318},"focus",[255,490,491],{"class":265},"({ preventScroll: ",[255,493,494],{"class":331},"true",[255,496,497],{"class":265}," });\n",[255,499,501],{"class":257,"line":500},19,[255,502,503],{"class":265}," }, [pathname]);\n",[255,505,507],{"class":257,"line":506},20,[255,508,306],{"emptyLinePlaceholder":305},[255,510,512,515,518,521],{"class":257,"line":511},21,[255,513,514],{"class":272}," return",[255,516,517],{"class":331}," null",[255,519,520],{"class":265},"; ",[255,522,523],{"class":395},"\u002F\u002F Logic-only component injected into root layout\n",[255,525,527],{"class":257,"line":526},22,[255,528,529],{"class":265},"}\n",[165,531,532,535],{},[171,533,534],{},"Testing Note:"," Verify focus trapping, route change announcements, and keyboard navigation using axe DevTools and VoiceOver. Ensure the focus outline remains visible and matches the visual hierarchy.",[227,537],{},[230,539,541],{"id":540},"component-design-library-integration","Component Design & Library Integration",[165,543,544],{},"Evaluating, extending, and integrating pre-built accessible UI systems requires strict adherence to WCAG success criteria while maintaining framework performance. Third-party components often ship with incomplete ARIA mappings or rely on non-semantic wrappers.",[165,546,547,548,551,552,555],{},"Audit third-party components against WCAG success criteria before adoption. Extend base primitives using ",[218,549,79],{"href":550},"\u002Freact-nextjs-accessibility-patterns\u002Faccessible-component-libraries-in-react\u002F"," to reduce custom ARIA debt. Standardize prop drilling for ",[181,553,554],{},"aria-*"," attributes and avoid prop collision in compound components by explicitly spreading rest props onto the correct DOM node.",[246,557,559],{"className":248,"code":558,"language":250,"meta":251,"style":251},"import { forwardRef } from 'react';\n\ninterface AccessibleButtonProps extends React.ButtonHTMLAttributes\u003CHTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'ghost';\n isLoading?: boolean;\n}\n\nexport const AccessibleButton = forwardRef\u003CHTMLButtonElement, AccessibleButtonProps>(\n ({ variant = 'primary', isLoading, children, disabled, ...rest }, ref) => {\n return (\n \u003Cbutton\n ref={ref}\n disabled={disabled || isLoading}\n aria-busy={isLoading}\n aria-disabled={disabled || isLoading ? 'true' : undefined}\n className={`btn btn-${variant}`}\n {...rest} \u002F\u002F Safely spreads aria-describedby, aria-label, etc.\n >\n {isLoading ? \u003Cspan aria-hidden=\"true\">⟳\u003C\u002Fspan> : children}\n \u003C\u002Fbutton>\n );\n }\n);\nAccessibleButton.displayName = 'AccessibleButton';\n",[181,560,561,574,578,605,630,642,646,650,677,725,732,741,751,767,777,805,824,837,842,875,886,891,895,900],{"__ignoreMap":251},[255,562,563,565,568,570,572],{"class":257,"line":258},[255,564,273],{"class":272},[255,566,567],{"class":265}," { forwardRef } ",[255,569,279],{"class":272},[255,571,282],{"class":261},[255,573,266],{"class":265},[255,575,576],{"class":257,"line":269},[255,577,306],{"emptyLinePlaceholder":305},[255,579,580,583,586,589,592,594,597,599,602],{"class":257,"line":287},[255,581,582],{"class":272},"interface",[255,584,585],{"class":318}," AccessibleButtonProps",[255,587,588],{"class":272}," extends",[255,590,591],{"class":318}," React",[255,593,447],{"class":265},[255,595,596],{"class":318},"ButtonHTMLAttributes",[255,598,357],{"class":265},[255,600,601],{"class":318},"HTMLButtonElement",[255,603,604],{"class":265},"> {\n",[255,606,607,611,614,617,620,623,625,628],{"class":257,"line":302},[255,608,610],{"class":609},"s4XuR"," variant",[255,612,613],{"class":272},"?:",[255,615,616],{"class":261}," 'primary'",[255,618,619],{"class":272}," |",[255,621,622],{"class":261}," 'secondary'",[255,624,619],{"class":272},[255,626,627],{"class":261}," 'ghost'",[255,629,266],{"class":265},[255,631,632,635,637,640],{"class":257,"line":309},[255,633,634],{"class":609}," isLoading",[255,636,613],{"class":272},[255,638,639],{"class":331}," boolean",[255,641,266],{"class":265},[255,643,644],{"class":257,"line":325},[255,645,529],{"class":265},[255,647,648],{"class":257,"line":344},[255,649,306],{"emptyLinePlaceholder":305},[255,651,652,654,656,659,661,664,666,668,671,674],{"class":257,"line":372},[255,653,312],{"class":272},[255,655,328],{"class":272},[255,657,658],{"class":331}," AccessibleButton",[255,660,335],{"class":272},[255,662,663],{"class":318}," forwardRef",[255,665,357],{"class":265},[255,667,601],{"class":318},[255,669,670],{"class":265},", ",[255,672,673],{"class":318},"AccessibleButtonProps",[255,675,676],{"class":265},">(\n",[255,678,679,682,685,687,689,691,694,696,699,701,704,706,709,712,715,718,721,723],{"class":257,"line":377},[255,680,681],{"class":265}," ({ ",[255,683,684],{"class":609},"variant",[255,686,335],{"class":272},[255,688,616],{"class":261},[255,690,670],{"class":265},[255,692,693],{"class":609},"isLoading",[255,695,670],{"class":265},[255,697,698],{"class":609},"children",[255,700,670],{"class":265},[255,702,703],{"class":609},"disabled",[255,705,670],{"class":265},[255,707,708],{"class":272},"...",[255,710,711],{"class":609},"rest",[255,713,714],{"class":265}," }, ",[255,716,717],{"class":609},"ref",[255,719,720],{"class":265},") ",[255,722,386],{"class":272},[255,724,389],{"class":265},[255,726,727,729],{"class":257,"line":392},[255,728,514],{"class":272},[255,730,731],{"class":265}," (\n",[255,733,734,737],{"class":257,"line":399},[255,735,736],{"class":265}," \u003C",[255,738,740],{"class":739},"s9eBZ","button\n",[255,742,743,746,748],{"class":257,"line":423},[255,744,745],{"class":318}," ref",[255,747,438],{"class":272},[255,749,750],{"class":265},"{ref}\n",[255,752,753,756,758,761,764],{"class":257,"line":432},[255,754,755],{"class":318}," disabled",[255,757,438],{"class":272},[255,759,760],{"class":265},"{disabled ",[255,762,763],{"class":272},"||",[255,765,766],{"class":265}," isLoading}\n",[255,768,769,772,774],{"class":257,"line":458},[255,770,771],{"class":318}," aria-busy",[255,773,438],{"class":272},[255,775,776],{"class":265},"{isLoading}\n",[255,778,779,782,784,786,788,791,794,797,800,803],{"class":257,"line":464},[255,780,781],{"class":318}," aria-disabled",[255,783,438],{"class":272},[255,785,760],{"class":265},[255,787,763],{"class":272},[255,789,790],{"class":265}," isLoading ",[255,792,793],{"class":272},"?",[255,795,796],{"class":261}," 'true'",[255,798,799],{"class":272}," :",[255,801,802],{"class":331}," undefined",[255,804,529],{"class":265},[255,806,807,810,812,815,818,820,822],{"class":257,"line":470},[255,808,809],{"class":318}," className",[255,811,438],{"class":272},[255,813,814],{"class":265},"{",[255,816,817],{"class":261},"`btn btn-${",[255,819,684],{"class":265},[255,821,453],{"class":261},[255,823,529],{"class":265},[255,825,826,829,831,834],{"class":257,"line":476},[255,827,828],{"class":265}," {",[255,830,708],{"class":272},[255,832,833],{"class":265},"rest} ",[255,835,836],{"class":395},"\u002F\u002F Safely spreads aria-describedby, aria-label, etc.\n",[255,838,839],{"class":257,"line":482},[255,840,841],{"class":265}," >\n",[255,843,844,847,849,851,853,856,858,861,864,866,869,872],{"class":257,"line":500},[255,845,846],{"class":265}," {isLoading ",[255,848,793],{"class":272},[255,850,736],{"class":265},[255,852,255],{"class":739},[255,854,855],{"class":318}," aria-hidden",[255,857,438],{"class":272},[255,859,860],{"class":261},"\"true\"",[255,862,863],{"class":265},">⟳\u003C\u002F",[255,865,255],{"class":739},[255,867,868],{"class":265},"> ",[255,870,871],{"class":272},":",[255,873,874],{"class":265}," children}\n",[255,876,877,880,883],{"class":257,"line":506},[255,878,879],{"class":265}," \u003C\u002F",[255,881,882],{"class":739},"button",[255,884,885],{"class":265},">\n",[255,887,888],{"class":257,"line":511},[255,889,890],{"class":265}," );\n",[255,892,893],{"class":257,"line":526},[255,894,461],{"class":265},[255,896,898],{"class":257,"line":897},23,[255,899,369],{"class":265},[255,901,903,906,908,911],{"class":257,"line":902},24,[255,904,905],{"class":265},"AccessibleButton.displayName ",[255,907,438],{"class":272},[255,909,910],{"class":261}," 'AccessibleButton'",[255,912,266],{"class":265},[165,914,915,917],{},[171,916,534],{}," Run automated contrast and semantic structure checks; validate interactive states with manual keyboard testing to ensure hover\u002Ffocus\u002Factive states are visually and programmatically distinct.",[227,919],{},[230,921,923],{"id":922},"server-components-client-boundaries","Server Components & Client Boundaries",[165,925,926],{},"Managing interactivity, hydration, and accessibility across React Server Components (RSC) and client-side islands requires deliberate boundary placement. Unmanaged hydration can cause focus loss, DOM reflow during streaming, and screen reader desynchronization.",[165,928,929,930,933,934,937,938,941],{},"Isolate client-side hydration to prevent focus loss and DOM reflow during streaming. Apply progressive enhancement strategies via ",[218,931,145],{"href":932},"\u002Freact-nextjs-accessibility-patterns\u002Fserver-components-client-side-interactivity\u002F"," for resilient fallbacks. Handle ",[181,935,936],{},"Suspense"," boundaries with accessible loading indicators and ",[181,939,940],{},"aria-busy"," states to communicate asynchronous rendering.",[246,943,945],{"className":248,"code":944,"language":250,"meta":251,"style":251},"import { Suspense } from 'react';\nimport { ClientInteractiveWidget } from '.\u002Fclient-widget';\n\nexport default function DashboardPage() {\n return (\n \u003Cmain>\n \u003Ch1>Analytics Dashboard\u003C\u002Fh1>\n \u003CSuspense fallback={\u003CAccessibleSkeleton aria-busy=\"true\" aria-label=\"Loading analytics data\" \u002F>}>\n \u003CClientInteractiveWidget \u002F>\n \u003C\u002FSuspense>\n \u003C\u002Fmain>\n );\n}\n\nfunction AccessibleSkeleton({ 'aria-busy': busy, 'aria-label': label }: { 'aria-busy': string; 'aria-label': string }) {\n return (\n \u003Csection role=\"region\" aria-busy={busy} aria-label={label}>\n \u003Cdiv className=\"skeleton-block\" aria-hidden=\"true\" \u002F>\n \u003Cdiv className=\"skeleton-block\" aria-hidden=\"true\" \u002F>\n \u003Cp className=\"sr-only\">Loading content. Please wait.\u003C\u002Fp>\n \u003C\u002Fsection>\n );\n}\n",[181,946,947,960,974,978,992,998,1007,1020,1054,1064,1072,1080,1084,1088,1092,1148,1154,1184,1206,1226,1246,1254,1258],{"__ignoreMap":251},[255,948,949,951,954,956,958],{"class":257,"line":258},[255,950,273],{"class":272},[255,952,953],{"class":265}," { Suspense } ",[255,955,279],{"class":272},[255,957,282],{"class":261},[255,959,266],{"class":265},[255,961,962,964,967,969,972],{"class":257,"line":269},[255,963,273],{"class":272},[255,965,966],{"class":265}," { ClientInteractiveWidget } ",[255,968,279],{"class":272},[255,970,971],{"class":261}," '.\u002Fclient-widget'",[255,973,266],{"class":265},[255,975,976],{"class":257,"line":287},[255,977,306],{"emptyLinePlaceholder":305},[255,979,980,982,985,987,990],{"class":257,"line":302},[255,981,312],{"class":272},[255,983,984],{"class":272}," default",[255,986,315],{"class":272},[255,988,989],{"class":318}," DashboardPage",[255,991,322],{"class":265},[255,993,994,996],{"class":257,"line":309},[255,995,514],{"class":272},[255,997,731],{"class":265},[255,999,1000,1002,1005],{"class":257,"line":325},[255,1001,736],{"class":265},[255,1003,1004],{"class":739},"main",[255,1006,885],{"class":265},[255,1008,1009,1011,1013,1016,1018],{"class":257,"line":344},[255,1010,736],{"class":265},[255,1012,162],{"class":739},[255,1014,1015],{"class":265},">Analytics Dashboard\u003C\u002F",[255,1017,162],{"class":739},[255,1019,885],{"class":265},[255,1021,1022,1024,1026,1029,1031,1034,1037,1039,1041,1043,1046,1048,1051],{"class":257,"line":372},[255,1023,736],{"class":265},[255,1025,936],{"class":331},[255,1027,1028],{"class":318}," fallback",[255,1030,438],{"class":272},[255,1032,1033],{"class":265},"{\u003C",[255,1035,1036],{"class":331},"AccessibleSkeleton",[255,1038,771],{"class":318},[255,1040,438],{"class":272},[255,1042,860],{"class":261},[255,1044,1045],{"class":318}," aria-label",[255,1047,438],{"class":272},[255,1049,1050],{"class":261},"\"Loading analytics data\"",[255,1052,1053],{"class":265}," \u002F>}>\n",[255,1055,1056,1058,1061],{"class":257,"line":377},[255,1057,736],{"class":265},[255,1059,1060],{"class":331},"ClientInteractiveWidget",[255,1062,1063],{"class":265}," \u002F>\n",[255,1065,1066,1068,1070],{"class":257,"line":392},[255,1067,879],{"class":265},[255,1069,936],{"class":331},[255,1071,885],{"class":265},[255,1073,1074,1076,1078],{"class":257,"line":399},[255,1075,879],{"class":265},[255,1077,1004],{"class":739},[255,1079,885],{"class":265},[255,1081,1082],{"class":257,"line":423},[255,1083,890],{"class":265},[255,1085,1086],{"class":257,"line":432},[255,1087,529],{"class":265},[255,1089,1090],{"class":257,"line":458},[255,1091,306],{"emptyLinePlaceholder":305},[255,1093,1094,1097,1100,1103,1106,1109,1112,1114,1117,1119,1122,1125,1127,1130,1132,1134,1137,1139,1141,1143,1145],{"class":257,"line":464},[255,1095,1096],{"class":272},"function",[255,1098,1099],{"class":318}," AccessibleSkeleton",[255,1101,1102],{"class":265},"({ ",[255,1104,1105],{"class":261},"'aria-busy'",[255,1107,1108],{"class":265},": ",[255,1110,1111],{"class":609},"busy",[255,1113,670],{"class":265},[255,1115,1116],{"class":261},"'aria-label'",[255,1118,1108],{"class":265},[255,1120,1121],{"class":609},"label",[255,1123,1124],{"class":265}," }",[255,1126,871],{"class":272},[255,1128,1129],{"class":265}," { ",[255,1131,1105],{"class":261},[255,1133,871],{"class":272},[255,1135,1136],{"class":331}," string",[255,1138,520],{"class":265},[255,1140,1116],{"class":261},[255,1142,871],{"class":272},[255,1144,1136],{"class":331},[255,1146,1147],{"class":265}," }) {\n",[255,1149,1150,1152],{"class":257,"line":470},[255,1151,514],{"class":272},[255,1153,731],{"class":265},[255,1155,1156,1158,1161,1164,1166,1169,1171,1173,1176,1179,1181],{"class":257,"line":476},[255,1157,736],{"class":265},[255,1159,1160],{"class":739},"section",[255,1162,1163],{"class":318}," role",[255,1165,438],{"class":272},[255,1167,1168],{"class":261},"\"region\"",[255,1170,771],{"class":318},[255,1172,438],{"class":272},[255,1174,1175],{"class":265},"{busy} ",[255,1177,1178],{"class":318},"aria-label",[255,1180,438],{"class":272},[255,1182,1183],{"class":265},"{label}>\n",[255,1185,1186,1188,1191,1193,1195,1198,1200,1202,1204],{"class":257,"line":482},[255,1187,736],{"class":265},[255,1189,1190],{"class":739},"div",[255,1192,809],{"class":318},[255,1194,438],{"class":272},[255,1196,1197],{"class":261},"\"skeleton-block\"",[255,1199,855],{"class":318},[255,1201,438],{"class":272},[255,1203,860],{"class":261},[255,1205,1063],{"class":265},[255,1207,1208,1210,1212,1214,1216,1218,1220,1222,1224],{"class":257,"line":500},[255,1209,736],{"class":265},[255,1211,1190],{"class":739},[255,1213,809],{"class":318},[255,1215,438],{"class":272},[255,1217,1197],{"class":261},[255,1219,855],{"class":318},[255,1221,438],{"class":272},[255,1223,860],{"class":261},[255,1225,1063],{"class":265},[255,1227,1228,1230,1232,1234,1236,1239,1242,1244],{"class":257,"line":506},[255,1229,736],{"class":265},[255,1231,165],{"class":739},[255,1233,809],{"class":318},[255,1235,438],{"class":272},[255,1237,1238],{"class":261},"\"sr-only\"",[255,1240,1241],{"class":265},">Loading content. Please wait.\u003C\u002F",[255,1243,165],{"class":739},[255,1245,885],{"class":265},[255,1247,1248,1250,1252],{"class":257,"line":511},[255,1249,879],{"class":265},[255,1251,1160],{"class":739},[255,1253,885],{"class":265},[255,1255,1256],{"class":257,"line":526},[255,1257,890],{"class":265},[255,1259,1260],{"class":257,"line":897},[255,1261,529],{"class":265},[165,1263,1264,1266],{},[171,1265,534],{}," Test hydration mismatches and ensure ARIA live regions survive server-to-client transitions without duplication. Verify that streaming content does not interrupt ongoing screen reader speech.",[227,1268],{},[230,1270,1272],{"id":1271},"state-management-dynamic-updates","State Management & Dynamic Updates",[165,1274,1275],{},"Communicating asynchronous state changes, data fetching, and UI mutations to assistive technologies requires careful orchestration of DOM updates and announcement queues. Improperly managed live regions cause AT flooding or silent failures.",[165,1277,1278,1279,1282,1283,1287,1288,1291,1292,1295],{},"Implement ",[181,1280,1281],{},"aria-live"," regions for toast notifications, pagination, and data fetches. Utilize ",[218,1284,1286],{"href":1285},"\u002Freact-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002F","Dynamic Content & State Announcements"," to manage screen reader queue priority. Throttle announcements to prevent AT flooding and ensure ",[181,1289,1290],{},"polite"," vs ",[181,1293,1294],{},"assertive"," context alignment.",[246,1297,1299],{"className":248,"code":1298,"language":250,"meta":251,"style":251},"'use client';\nimport { useState, useEffect, useRef } from 'react';\n\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\n const [toasts, setToasts] = useState\u003C{ id: string; message: string }[]>([]);\n const liveRef = useRef\u003CHTMLDivElement>(null);\n\n const addToast = (message: string) => {\n const id = Date.now().toString();\n setToasts(prev => [...prev, { id, message }]);\n };\n\n useEffect(() => {\n if (toasts.length > 0) {\n const timer = setTimeout(() => setToasts(prev => prev.slice(1)), 4000);\n return () => clearTimeout(timer);\n }\n }, [toasts]);\n\n return (\n \u003C>\n {children}\n {\u002F* Polite region for non-urgent UI updates *\u002F}\n \u003Cdiv\n ref={liveRef}\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"toast-container\"\n >\n {toasts.map(toast => (\n \u003Cdiv key={toast.id} className=\"toast-item\">{toast.message}\u003C\u002Fdiv>\n ))}\n \u003C\u002Fdiv>\n \u003C\u002F>\n );\n}\n",[181,1300,1301,1307,1320,1324,1356,1401,1423,1427,1451,1474,1494,1499,1503,1513,1532,1575,1590,1594,1599,1603,1609,1614,1619,1628,1635,1645,1655,1666,1677,1687,1692,1710,1740,1746,1755,1761,1766],{"__ignoreMap":251},[255,1302,1303,1305],{"class":257,"line":258},[255,1304,262],{"class":261},[255,1306,266],{"class":265},[255,1308,1309,1311,1314,1316,1318],{"class":257,"line":269},[255,1310,273],{"class":272},[255,1312,1313],{"class":265}," { useState, useEffect, useRef } ",[255,1315,279],{"class":272},[255,1317,282],{"class":261},[255,1319,266],{"class":265},[255,1321,1322],{"class":257,"line":287},[255,1323,306],{"emptyLinePlaceholder":305},[255,1325,1326,1328,1330,1333,1335,1337,1339,1341,1343,1345,1347,1349,1351,1354],{"class":257,"line":302},[255,1327,312],{"class":272},[255,1329,315],{"class":272},[255,1331,1332],{"class":318}," ToastProvider",[255,1334,1102],{"class":265},[255,1336,698],{"class":609},[255,1338,1124],{"class":265},[255,1340,871],{"class":272},[255,1342,1129],{"class":265},[255,1344,698],{"class":609},[255,1346,871],{"class":272},[255,1348,591],{"class":318},[255,1350,447],{"class":265},[255,1352,1353],{"class":318},"ReactNode",[255,1355,1147],{"class":265},[255,1357,1358,1360,1363,1366,1368,1371,1374,1376,1379,1382,1385,1387,1389,1391,1394,1396,1398],{"class":257,"line":309},[255,1359,328],{"class":272},[255,1361,1362],{"class":265}," [",[255,1364,1365],{"class":331},"toasts",[255,1367,670],{"class":265},[255,1369,1370],{"class":331},"setToasts",[255,1372,1373],{"class":265},"] ",[255,1375,438],{"class":272},[255,1377,1378],{"class":318}," useState",[255,1380,1381],{"class":265},"\u003C{ ",[255,1383,1384],{"class":609},"id",[255,1386,871],{"class":272},[255,1388,1136],{"class":331},[255,1390,520],{"class":265},[255,1392,1393],{"class":609},"message",[255,1395,871],{"class":272},[255,1397,1136],{"class":331},[255,1399,1400],{"class":265}," }[]>([]);\n",[255,1402,1403,1405,1408,1410,1412,1414,1417,1419,1421],{"class":257,"line":325},[255,1404,328],{"class":272},[255,1406,1407],{"class":331}," liveRef",[255,1409,335],{"class":272},[255,1411,354],{"class":318},[255,1413,357],{"class":265},[255,1415,1416],{"class":318},"HTMLDivElement",[255,1418,363],{"class":265},[255,1420,366],{"class":331},[255,1422,369],{"class":265},[255,1424,1425],{"class":257,"line":344},[255,1426,306],{"emptyLinePlaceholder":305},[255,1428,1429,1431,1434,1436,1439,1441,1443,1445,1447,1449],{"class":257,"line":372},[255,1430,328],{"class":272},[255,1432,1433],{"class":318}," addToast",[255,1435,335],{"class":272},[255,1437,1438],{"class":265}," (",[255,1440,1393],{"class":609},[255,1442,871],{"class":272},[255,1444,1136],{"class":331},[255,1446,720],{"class":265},[255,1448,386],{"class":272},[255,1450,389],{"class":265},[255,1452,1453,1455,1458,1460,1463,1466,1469,1472],{"class":257,"line":377},[255,1454,328],{"class":272},[255,1456,1457],{"class":331}," id",[255,1459,335],{"class":272},[255,1461,1462],{"class":265}," Date.",[255,1464,1465],{"class":318},"now",[255,1467,1468],{"class":265},"().",[255,1470,1471],{"class":318},"toString",[255,1473,341],{"class":265},[255,1475,1476,1479,1481,1484,1487,1489,1491],{"class":257,"line":392},[255,1477,1478],{"class":318}," setToasts",[255,1480,415],{"class":265},[255,1482,1483],{"class":609},"prev",[255,1485,1486],{"class":272}," =>",[255,1488,1362],{"class":265},[255,1490,708],{"class":272},[255,1492,1493],{"class":265},"prev, { id, message }]);\n",[255,1495,1496],{"class":257,"line":399},[255,1497,1498],{"class":265}," };\n",[255,1500,1501],{"class":257,"line":423},[255,1502,306],{"emptyLinePlaceholder":305},[255,1504,1505,1507,1509,1511],{"class":257,"line":432},[255,1506,380],{"class":318},[255,1508,383],{"class":265},[255,1510,386],{"class":272},[255,1512,389],{"class":265},[255,1514,1515,1517,1520,1523,1526,1529],{"class":257,"line":458},[255,1516,426],{"class":272},[255,1518,1519],{"class":265}," (toasts.",[255,1521,1522],{"class":331},"length",[255,1524,1525],{"class":272}," >",[255,1527,1528],{"class":331}," 0",[255,1530,1531],{"class":265},") {\n",[255,1533,1534,1536,1539,1541,1544,1546,1548,1550,1552,1554,1556,1559,1562,1564,1567,1570,1573],{"class":257,"line":464},[255,1535,328],{"class":272},[255,1537,1538],{"class":331}," timer",[255,1540,335],{"class":272},[255,1542,1543],{"class":318}," setTimeout",[255,1545,383],{"class":265},[255,1547,386],{"class":272},[255,1549,1478],{"class":318},[255,1551,415],{"class":265},[255,1553,1483],{"class":609},[255,1555,1486],{"class":272},[255,1557,1558],{"class":265}," prev.",[255,1560,1561],{"class":318},"slice",[255,1563,415],{"class":265},[255,1565,1566],{"class":331},"1",[255,1568,1569],{"class":265},")), ",[255,1571,1572],{"class":331},"4000",[255,1574,369],{"class":265},[255,1576,1577,1579,1582,1584,1587],{"class":257,"line":470},[255,1578,514],{"class":272},[255,1580,1581],{"class":265}," () ",[255,1583,386],{"class":272},[255,1585,1586],{"class":318}," clearTimeout",[255,1588,1589],{"class":265},"(timer);\n",[255,1591,1592],{"class":257,"line":476},[255,1593,461],{"class":265},[255,1595,1596],{"class":257,"line":482},[255,1597,1598],{"class":265}," }, [toasts]);\n",[255,1600,1601],{"class":257,"line":500},[255,1602,306],{"emptyLinePlaceholder":305},[255,1604,1605,1607],{"class":257,"line":506},[255,1606,514],{"class":272},[255,1608,731],{"class":265},[255,1610,1611],{"class":257,"line":511},[255,1612,1613],{"class":265}," \u003C>\n",[255,1615,1616],{"class":257,"line":526},[255,1617,1618],{"class":265}," {children}\n",[255,1620,1621,1623,1626],{"class":257,"line":897},[255,1622,828],{"class":265},[255,1624,1625],{"class":395},"\u002F* Polite region for non-urgent UI updates *\u002F",[255,1627,529],{"class":265},[255,1629,1630,1632],{"class":257,"line":902},[255,1631,736],{"class":265},[255,1633,1634],{"class":739},"div\n",[255,1636,1638,1640,1642],{"class":257,"line":1637},25,[255,1639,745],{"class":318},[255,1641,438],{"class":272},[255,1643,1644],{"class":265},"{liveRef}\n",[255,1646,1648,1650,1652],{"class":257,"line":1647},26,[255,1649,1163],{"class":318},[255,1651,438],{"class":272},[255,1653,1654],{"class":261},"\"status\"\n",[255,1656,1658,1661,1663],{"class":257,"line":1657},27,[255,1659,1660],{"class":318}," aria-live",[255,1662,438],{"class":272},[255,1664,1665],{"class":261},"\"polite\"\n",[255,1667,1669,1672,1674],{"class":257,"line":1668},28,[255,1670,1671],{"class":318}," aria-atomic",[255,1673,438],{"class":272},[255,1675,1676],{"class":261},"\"true\"\n",[255,1678,1680,1682,1684],{"class":257,"line":1679},29,[255,1681,809],{"class":318},[255,1683,438],{"class":272},[255,1685,1686],{"class":261},"\"toast-container\"\n",[255,1688,1690],{"class":257,"line":1689},30,[255,1691,841],{"class":265},[255,1693,1695,1698,1701,1703,1706,1708],{"class":257,"line":1694},31,[255,1696,1697],{"class":265}," {toasts.",[255,1699,1700],{"class":318},"map",[255,1702,415],{"class":265},[255,1704,1705],{"class":609},"toast",[255,1707,1486],{"class":272},[255,1709,731],{"class":265},[255,1711,1713,1715,1717,1720,1722,1725,1728,1730,1733,1736,1738],{"class":257,"line":1712},32,[255,1714,736],{"class":265},[255,1716,1190],{"class":739},[255,1718,1719],{"class":318}," key",[255,1721,438],{"class":272},[255,1723,1724],{"class":265},"{toast.id} ",[255,1726,1727],{"class":318},"className",[255,1729,438],{"class":272},[255,1731,1732],{"class":261},"\"toast-item\"",[255,1734,1735],{"class":265},">{toast.message}\u003C\u002F",[255,1737,1190],{"class":739},[255,1739,885],{"class":265},[255,1741,1743],{"class":257,"line":1742},33,[255,1744,1745],{"class":265}," ))}\n",[255,1747,1749,1751,1753],{"class":257,"line":1748},34,[255,1750,879],{"class":265},[255,1752,1190],{"class":739},[255,1754,885],{"class":265},[255,1756,1758],{"class":257,"line":1757},35,[255,1759,1760],{"class":265}," \u003C\u002F>\n",[255,1762,1764],{"class":257,"line":1763},36,[255,1765,890],{"class":265},[255,1767,1769],{"class":257,"line":1768},37,[255,1770,529],{"class":265},[165,1772,1773,1775],{},[171,1774,534],{}," Validate announcement timing, politeness attributes, and DOM update synchronization with NVDA and JAWS. Ensure rapid state changes are debounced to prevent queue overflow.",[227,1777],{},[230,1779,1781],{"id":1780},"form-architecture-validation-workflows","Form Architecture & Validation Workflows",[165,1783,1784],{},"Building accessible, performant, and user-friendly form submission and error handling patterns requires explicit mapping between validation logic and ARIA attributes. Uncontrolled rendering and improper error association break keyboard navigation and screen reader flow.",[165,1786,1787,1788,670,1791,1794,1795,1799],{},"Map validation errors to ",[181,1789,1790],{},"aria-invalid",[181,1792,1793],{},"aria-describedby",", and programmatic input associations. Integrate ",[218,1796,1798],{"href":1797},"\u002Freact-nextjs-accessibility-patterns\u002Fform-handling-with-react-hook-form-a11y\u002F","Form Handling with React Hook Form & A11y"," to optimize uncontrolled rendering and reduce re-renders. Ensure error summaries are focusable and announced upon form submission failure.",[246,1801,1803],{"className":248,"code":1802,"language":250,"meta":251,"style":251},"'use client';\nimport { useForm } from 'react-hook-form';\nimport { useState, useEffect, useRef } from 'react';\n\nexport default function AccessibleContactForm() {\n const { register, handleSubmit, formState: { errors, isSubmitted } } = useForm();\n const [hasError, setHasError] = useState(false);\n const errorSummaryRef = useRef\u003CHTMLDivElement>(null);\n\n const onSubmit = () => setHasError(false);\n const onError = () => {\n setHasError(true);\n \u002F\u002F Move focus to error summary for immediate AT announcement\n setTimeout(() => errorSummaryRef.current?.focus(), 0);\n };\n\n return (\n \u003Cform onSubmit={handleSubmit(onSubmit, onError)} noValidate>\n {hasError && (\n \u003Cdiv\n ref={errorSummaryRef}\n role=\"alert\"\n aria-live=\"assertive\"\n tabIndex={-1}\n id=\"form-error-summary\"\n className=\"error-summary\"\n >\n \u003Cp>Please correct the highlighted errors below.\u003C\u002Fp>\n \u003C\u002Fdiv>\n )}\n\n \u003Clabel htmlFor=\"email\">Email Address\u003C\u002Flabel>\n \u003Cinput\n id=\"email\"\n type=\"email\"\n aria-invalid={!!errors.email}\n aria-describedby={errors.email ? \"email-error\" : undefined}\n {...register('email', { required: 'Email address is required' })}\n \u002F>\n {errors.email && (\n \u003Cspan id=\"email-error\" className=\"error-text\" role=\"alert\">\n {errors.email.message as string}\n \u003C\u002Fspan>\n )}\n\n \u003Cbutton type=\"submit\">Submit\u003C\u002Fbutton>\n \u003C\u002Fform>\n );\n}\n",[181,1804,1805,1811,1825,1837,1841,1854,1894,1921,1942,1946,1968,1983,1993,1998,2019,2023,2027,2033,2056,2066,2072,2081,2090,2099,2115,2124,2133,2137,2150,2158,2163,2167,2188,2195,2204,2213,2228,2249,2272,2277,2287,2317,2330,2339,2344,2349,2370,2379,2384],{"__ignoreMap":251},[255,1806,1807,1809],{"class":257,"line":258},[255,1808,262],{"class":261},[255,1810,266],{"class":265},[255,1812,1813,1815,1818,1820,1823],{"class":257,"line":269},[255,1814,273],{"class":272},[255,1816,1817],{"class":265}," { useForm } ",[255,1819,279],{"class":272},[255,1821,1822],{"class":261}," 'react-hook-form'",[255,1824,266],{"class":265},[255,1826,1827,1829,1831,1833,1835],{"class":257,"line":287},[255,1828,273],{"class":272},[255,1830,1313],{"class":265},[255,1832,279],{"class":272},[255,1834,282],{"class":261},[255,1836,266],{"class":265},[255,1838,1839],{"class":257,"line":302},[255,1840,306],{"emptyLinePlaceholder":305},[255,1842,1843,1845,1847,1849,1852],{"class":257,"line":309},[255,1844,312],{"class":272},[255,1846,984],{"class":272},[255,1848,315],{"class":272},[255,1850,1851],{"class":318}," AccessibleContactForm",[255,1853,322],{"class":265},[255,1855,1856,1858,1860,1863,1865,1868,1870,1873,1876,1879,1881,1884,1887,1889,1892],{"class":257,"line":325},[255,1857,328],{"class":272},[255,1859,1129],{"class":265},[255,1861,1862],{"class":331},"register",[255,1864,670],{"class":265},[255,1866,1867],{"class":331},"handleSubmit",[255,1869,670],{"class":265},[255,1871,1872],{"class":609},"formState",[255,1874,1875],{"class":265},": { ",[255,1877,1878],{"class":331},"errors",[255,1880,670],{"class":265},[255,1882,1883],{"class":331},"isSubmitted",[255,1885,1886],{"class":265}," } } ",[255,1888,438],{"class":272},[255,1890,1891],{"class":318}," useForm",[255,1893,341],{"class":265},[255,1895,1896,1898,1900,1903,1905,1908,1910,1912,1914,1916,1919],{"class":257,"line":344},[255,1897,328],{"class":272},[255,1899,1362],{"class":265},[255,1901,1902],{"class":331},"hasError",[255,1904,670],{"class":265},[255,1906,1907],{"class":331},"setHasError",[255,1909,1373],{"class":265},[255,1911,438],{"class":272},[255,1913,1378],{"class":318},[255,1915,415],{"class":265},[255,1917,1918],{"class":331},"false",[255,1920,369],{"class":265},[255,1922,1923,1925,1928,1930,1932,1934,1936,1938,1940],{"class":257,"line":372},[255,1924,328],{"class":272},[255,1926,1927],{"class":331}," errorSummaryRef",[255,1929,335],{"class":272},[255,1931,354],{"class":318},[255,1933,357],{"class":265},[255,1935,1416],{"class":318},[255,1937,363],{"class":265},[255,1939,366],{"class":331},[255,1941,369],{"class":265},[255,1943,1944],{"class":257,"line":377},[255,1945,306],{"emptyLinePlaceholder":305},[255,1947,1948,1950,1953,1955,1957,1959,1962,1964,1966],{"class":257,"line":392},[255,1949,328],{"class":272},[255,1951,1952],{"class":318}," onSubmit",[255,1954,335],{"class":272},[255,1956,1581],{"class":265},[255,1958,386],{"class":272},[255,1960,1961],{"class":318}," setHasError",[255,1963,415],{"class":265},[255,1965,1918],{"class":331},[255,1967,369],{"class":265},[255,1969,1970,1972,1975,1977,1979,1981],{"class":257,"line":399},[255,1971,328],{"class":272},[255,1973,1974],{"class":318}," onError",[255,1976,335],{"class":272},[255,1978,1581],{"class":265},[255,1980,386],{"class":272},[255,1982,389],{"class":265},[255,1984,1985,1987,1989,1991],{"class":257,"line":423},[255,1986,1961],{"class":318},[255,1988,415],{"class":265},[255,1990,494],{"class":331},[255,1992,369],{"class":265},[255,1994,1995],{"class":257,"line":432},[255,1996,1997],{"class":395}," \u002F\u002F Move focus to error summary for immediate AT announcement\n",[255,1999,2000,2002,2004,2006,2009,2011,2014,2017],{"class":257,"line":458},[255,2001,1543],{"class":318},[255,2003,383],{"class":265},[255,2005,386],{"class":272},[255,2007,2008],{"class":265}," errorSummaryRef.current?.",[255,2010,488],{"class":318},[255,2012,2013],{"class":265},"(), ",[255,2015,2016],{"class":331},"0",[255,2018,369],{"class":265},[255,2020,2021],{"class":257,"line":464},[255,2022,1498],{"class":265},[255,2024,2025],{"class":257,"line":470},[255,2026,306],{"emptyLinePlaceholder":305},[255,2028,2029,2031],{"class":257,"line":476},[255,2030,514],{"class":272},[255,2032,731],{"class":265},[255,2034,2035,2037,2040,2042,2044,2046,2048,2051,2054],{"class":257,"line":482},[255,2036,736],{"class":265},[255,2038,2039],{"class":739},"form",[255,2041,1952],{"class":318},[255,2043,438],{"class":272},[255,2045,814],{"class":265},[255,2047,1867],{"class":318},[255,2049,2050],{"class":265},"(onSubmit, onError)} ",[255,2052,2053],{"class":318},"noValidate",[255,2055,885],{"class":265},[255,2057,2058,2061,2064],{"class":257,"line":500},[255,2059,2060],{"class":265}," {hasError ",[255,2062,2063],{"class":272},"&&",[255,2065,731],{"class":265},[255,2067,2068,2070],{"class":257,"line":506},[255,2069,736],{"class":265},[255,2071,1634],{"class":739},[255,2073,2074,2076,2078],{"class":257,"line":511},[255,2075,745],{"class":318},[255,2077,438],{"class":272},[255,2079,2080],{"class":265},"{errorSummaryRef}\n",[255,2082,2083,2085,2087],{"class":257,"line":526},[255,2084,1163],{"class":318},[255,2086,438],{"class":272},[255,2088,2089],{"class":261},"\"alert\"\n",[255,2091,2092,2094,2096],{"class":257,"line":897},[255,2093,1660],{"class":318},[255,2095,438],{"class":272},[255,2097,2098],{"class":261},"\"assertive\"\n",[255,2100,2101,2104,2106,2108,2111,2113],{"class":257,"line":902},[255,2102,2103],{"class":318}," tabIndex",[255,2105,438],{"class":272},[255,2107,814],{"class":265},[255,2109,2110],{"class":272},"-",[255,2112,1566],{"class":331},[255,2114,529],{"class":265},[255,2116,2117,2119,2121],{"class":257,"line":1637},[255,2118,1457],{"class":318},[255,2120,438],{"class":272},[255,2122,2123],{"class":261},"\"form-error-summary\"\n",[255,2125,2126,2128,2130],{"class":257,"line":1647},[255,2127,809],{"class":318},[255,2129,438],{"class":272},[255,2131,2132],{"class":261},"\"error-summary\"\n",[255,2134,2135],{"class":257,"line":1657},[255,2136,841],{"class":265},[255,2138,2139,2141,2143,2146,2148],{"class":257,"line":1668},[255,2140,736],{"class":265},[255,2142,165],{"class":739},[255,2144,2145],{"class":265},">Please correct the highlighted errors below.\u003C\u002F",[255,2147,165],{"class":739},[255,2149,885],{"class":265},[255,2151,2152,2154,2156],{"class":257,"line":1679},[255,2153,879],{"class":265},[255,2155,1190],{"class":739},[255,2157,885],{"class":265},[255,2159,2160],{"class":257,"line":1689},[255,2161,2162],{"class":265}," )}\n",[255,2164,2165],{"class":257,"line":1694},[255,2166,306],{"emptyLinePlaceholder":305},[255,2168,2169,2171,2173,2176,2178,2181,2184,2186],{"class":257,"line":1712},[255,2170,736],{"class":265},[255,2172,1121],{"class":739},[255,2174,2175],{"class":318}," htmlFor",[255,2177,438],{"class":272},[255,2179,2180],{"class":261},"\"email\"",[255,2182,2183],{"class":265},">Email Address\u003C\u002F",[255,2185,1121],{"class":739},[255,2187,885],{"class":265},[255,2189,2190,2192],{"class":257,"line":1742},[255,2191,736],{"class":265},[255,2193,2194],{"class":739},"input\n",[255,2196,2197,2199,2201],{"class":257,"line":1748},[255,2198,1457],{"class":318},[255,2200,438],{"class":272},[255,2202,2203],{"class":261},"\"email\"\n",[255,2205,2206,2209,2211],{"class":257,"line":1757},[255,2207,2208],{"class":318}," type",[255,2210,438],{"class":272},[255,2212,2203],{"class":261},[255,2214,2215,2218,2220,2222,2225],{"class":257,"line":1763},[255,2216,2217],{"class":318}," aria-invalid",[255,2219,438],{"class":272},[255,2221,814],{"class":265},[255,2223,2224],{"class":272},"!!",[255,2226,2227],{"class":265},"errors.email}\n",[255,2229,2230,2233,2235,2238,2240,2243,2245,2247],{"class":257,"line":1768},[255,2231,2232],{"class":318}," aria-describedby",[255,2234,438],{"class":272},[255,2236,2237],{"class":265},"{errors.email ",[255,2239,793],{"class":272},[255,2241,2242],{"class":261}," \"email-error\"",[255,2244,799],{"class":272},[255,2246,802],{"class":331},[255,2248,529],{"class":265},[255,2250,2252,2254,2256,2258,2260,2263,2266,2269],{"class":257,"line":2251},38,[255,2253,828],{"class":265},[255,2255,708],{"class":272},[255,2257,1862],{"class":318},[255,2259,415],{"class":265},[255,2261,2262],{"class":261},"'email'",[255,2264,2265],{"class":265},", { required: ",[255,2267,2268],{"class":261},"'Email address is required'",[255,2270,2271],{"class":265}," })}\n",[255,2273,2275],{"class":257,"line":2274},39,[255,2276,1063],{"class":265},[255,2278,2280,2283,2285],{"class":257,"line":2279},40,[255,2281,2282],{"class":265}," {errors.email ",[255,2284,2063],{"class":272},[255,2286,731],{"class":265},[255,2288,2290,2292,2294,2296,2298,2301,2303,2305,2308,2310,2312,2315],{"class":257,"line":2289},41,[255,2291,736],{"class":265},[255,2293,255],{"class":739},[255,2295,1457],{"class":318},[255,2297,438],{"class":272},[255,2299,2300],{"class":261},"\"email-error\"",[255,2302,809],{"class":318},[255,2304,438],{"class":272},[255,2306,2307],{"class":261},"\"error-text\"",[255,2309,1163],{"class":318},[255,2311,438],{"class":272},[255,2313,2314],{"class":261},"\"alert\"",[255,2316,885],{"class":265},[255,2318,2320,2323,2326,2328],{"class":257,"line":2319},42,[255,2321,2322],{"class":265}," {errors.email.message ",[255,2324,2325],{"class":272},"as",[255,2327,1136],{"class":331},[255,2329,529],{"class":265},[255,2331,2333,2335,2337],{"class":257,"line":2332},43,[255,2334,879],{"class":265},[255,2336,255],{"class":739},[255,2338,885],{"class":265},[255,2340,2342],{"class":257,"line":2341},44,[255,2343,2162],{"class":265},[255,2345,2347],{"class":257,"line":2346},45,[255,2348,306],{"emptyLinePlaceholder":305},[255,2350,2352,2354,2356,2358,2360,2363,2366,2368],{"class":257,"line":2351},46,[255,2353,736],{"class":265},[255,2355,882],{"class":739},[255,2357,2208],{"class":318},[255,2359,438],{"class":272},[255,2361,2362],{"class":261},"\"submit\"",[255,2364,2365],{"class":265},">Submit\u003C\u002F",[255,2367,882],{"class":739},[255,2369,885],{"class":265},[255,2371,2373,2375,2377],{"class":257,"line":2372},47,[255,2374,879],{"class":265},[255,2376,2039],{"class":739},[255,2378,885],{"class":265},[255,2380,2382],{"class":257,"line":2381},48,[255,2383,890],{"class":265},[255,2385,2387],{"class":257,"line":2386},49,[255,2388,529],{"class":265},[165,2390,2391,2393,2394,2396],{},[171,2392,534],{}," Test form submission flows using keyboard-only navigation and verify error announcement order matches visual layout. Ensure ",[181,2395,2053],{}," is present to prevent native browser validation from conflicting with custom ARIA mappings.",[227,2398],{},[230,2400,2402],{"id":2401},"complex-widgets-advanced-aria","Complex Widgets & Advanced ARIA",[165,2404,2405],{},"Implementing custom interactive components safely is necessary when native HTML elements are insufficient. However, custom widgets must strictly adhere to WAI-ARIA authoring practices to avoid creating inaccessible black boxes.",[165,2407,2408],{},"Apply WAI-ARIA authoring practices for custom dropdowns, modals, tabs, and data grids. Reference Advanced ARIA Patterns for Complex Widgets for edge-case role and state synchronization. Avoid overusing ARIA when native HTML semantics provide equivalent functionality.",[246,2410,2412],{"className":248,"code":2411,"language":250,"meta":251,"style":251},"'use client';\nimport { useEffect, useRef, useCallback } from 'react';\n\nconst FOCUSABLE_SELECTORS = 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])';\n\nexport function useFocusTrap(containerRef: React.RefObject\u003CHTMLElement>, isActive: boolean) {\n const previousFocusRef = useRef\u003CHTMLElement | null>(null);\n\n const trapFocus = useCallback((e: KeyboardEvent) => {\n if (!isActive || !containerRef.current) return;\n const container = containerRef.current;\n const focusableElements = Array.from(container.querySelectorAll(FOCUSABLE_SELECTORS));\n if (focusableElements.length === 0) return;\n\n const firstEl = focusableElements[0];\n const lastEl = focusableElements[focusableElements.length - 1];\n\n if (e.key === 'Tab') {\n if (e.shiftKey && document.activeElement === firstEl) {\n e.preventDefault();\n lastEl.focus();\n } else if (!e.shiftKey && document.activeElement === lastEl) {\n e.preventDefault();\n firstEl.focus();\n }\n }\n }, [isActive, containerRef]);\n\n useEffect(() => {\n if (isActive) {\n previousFocusRef.current = document.activeElement as HTMLElement;\n document.addEventListener('keydown', trapFocus);\n const firstFocusable = containerRef.current?.querySelector(FOCUSABLE_SELECTORS) as HTMLElement;\n firstFocusable?.focus();\n } else {\n document.removeEventListener('keydown', trapFocus);\n previousFocusRef.current?.focus();\n }\n return () => document.removeEventListener('keydown', trapFocus);\n }, [isActive, trapFocus, containerRef]);\n}\n",[181,2413,2414,2420,2433,2437,2452,2456,2496,2521,2525,2554,2579,2591,2619,2639,2643,2660,2682,2686,2701,2718,2728,2737,2763,2771,2780,2784,2788,2793,2797,2807,2814,2830,2845,2872,2881,2889,2902,2911,2915,2933,2938],{"__ignoreMap":251},[255,2415,2416,2418],{"class":257,"line":258},[255,2417,262],{"class":261},[255,2419,266],{"class":265},[255,2421,2422,2424,2427,2429,2431],{"class":257,"line":269},[255,2423,273],{"class":272},[255,2425,2426],{"class":265}," { useEffect, useRef, useCallback } ",[255,2428,279],{"class":272},[255,2430,282],{"class":261},[255,2432,266],{"class":265},[255,2434,2435],{"class":257,"line":287},[255,2436,306],{"emptyLinePlaceholder":305},[255,2438,2439,2442,2445,2447,2450],{"class":257,"line":302},[255,2440,2441],{"class":272},"const",[255,2443,2444],{"class":331}," FOCUSABLE_SELECTORS",[255,2446,335],{"class":272},[255,2448,2449],{"class":261}," 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])'",[255,2451,266],{"class":265},[255,2453,2454],{"class":257,"line":309},[255,2455,306],{"emptyLinePlaceholder":305},[255,2457,2458,2460,2462,2465,2467,2470,2472,2474,2476,2479,2481,2484,2487,2490,2492,2494],{"class":257,"line":325},[255,2459,312],{"class":272},[255,2461,315],{"class":272},[255,2463,2464],{"class":318}," useFocusTrap",[255,2466,415],{"class":265},[255,2468,2469],{"class":609},"containerRef",[255,2471,871],{"class":272},[255,2473,591],{"class":318},[255,2475,447],{"class":265},[255,2477,2478],{"class":318},"RefObject",[255,2480,357],{"class":265},[255,2482,2483],{"class":318},"HTMLElement",[255,2485,2486],{"class":265},">, ",[255,2488,2489],{"class":609},"isActive",[255,2491,871],{"class":272},[255,2493,639],{"class":331},[255,2495,1531],{"class":265},[255,2497,2498,2500,2503,2505,2507,2509,2511,2513,2515,2517,2519],{"class":257,"line":344},[255,2499,328],{"class":272},[255,2501,2502],{"class":331}," previousFocusRef",[255,2504,335],{"class":272},[255,2506,354],{"class":318},[255,2508,357],{"class":265},[255,2510,2483],{"class":318},[255,2512,619],{"class":272},[255,2514,517],{"class":331},[255,2516,363],{"class":265},[255,2518,366],{"class":331},[255,2520,369],{"class":265},[255,2522,2523],{"class":257,"line":372},[255,2524,306],{"emptyLinePlaceholder":305},[255,2526,2527,2529,2532,2534,2537,2540,2543,2545,2548,2550,2552],{"class":257,"line":377},[255,2528,328],{"class":272},[255,2530,2531],{"class":331}," trapFocus",[255,2533,335],{"class":272},[255,2535,2536],{"class":318}," useCallback",[255,2538,2539],{"class":265},"((",[255,2541,2542],{"class":609},"e",[255,2544,871],{"class":272},[255,2546,2547],{"class":318}," KeyboardEvent",[255,2549,720],{"class":265},[255,2551,386],{"class":272},[255,2553,389],{"class":265},[255,2555,2556,2558,2560,2563,2566,2568,2571,2574,2577],{"class":257,"line":392},[255,2557,426],{"class":272},[255,2559,1438],{"class":265},[255,2561,2562],{"class":272},"!",[255,2564,2565],{"class":265},"isActive ",[255,2567,763],{"class":272},[255,2569,2570],{"class":272}," !",[255,2572,2573],{"class":265},"containerRef.current) ",[255,2575,2576],{"class":272},"return",[255,2578,266],{"class":265},[255,2580,2581,2583,2586,2588],{"class":257,"line":399},[255,2582,328],{"class":272},[255,2584,2585],{"class":331}," container",[255,2587,335],{"class":272},[255,2589,2590],{"class":265}," containerRef.current;\n",[255,2592,2593,2595,2598,2600,2603,2605,2608,2611,2613,2616],{"class":257,"line":423},[255,2594,328],{"class":272},[255,2596,2597],{"class":331}," focusableElements",[255,2599,335],{"class":272},[255,2601,2602],{"class":265}," Array.",[255,2604,279],{"class":318},[255,2606,2607],{"class":265},"(container.",[255,2609,2610],{"class":318},"querySelectorAll",[255,2612,415],{"class":265},[255,2614,2615],{"class":331},"FOCUSABLE_SELECTORS",[255,2617,2618],{"class":265},"));\n",[255,2620,2621,2623,2626,2628,2631,2633,2635,2637],{"class":257,"line":432},[255,2622,426],{"class":272},[255,2624,2625],{"class":265}," (focusableElements.",[255,2627,1522],{"class":331},[255,2629,2630],{"class":272}," ===",[255,2632,1528],{"class":331},[255,2634,720],{"class":265},[255,2636,2576],{"class":272},[255,2638,266],{"class":265},[255,2640,2641],{"class":257,"line":458},[255,2642,306],{"emptyLinePlaceholder":305},[255,2644,2645,2647,2650,2652,2655,2657],{"class":257,"line":464},[255,2646,328],{"class":272},[255,2648,2649],{"class":331}," firstEl",[255,2651,335],{"class":272},[255,2653,2654],{"class":265}," focusableElements[",[255,2656,2016],{"class":331},[255,2658,2659],{"class":265},"];\n",[255,2661,2662,2664,2667,2669,2672,2674,2677,2680],{"class":257,"line":470},[255,2663,328],{"class":272},[255,2665,2666],{"class":331}," lastEl",[255,2668,335],{"class":272},[255,2670,2671],{"class":265}," focusableElements[focusableElements.",[255,2673,1522],{"class":331},[255,2675,2676],{"class":272}," -",[255,2678,2679],{"class":331}," 1",[255,2681,2659],{"class":265},[255,2683,2684],{"class":257,"line":476},[255,2685,306],{"emptyLinePlaceholder":305},[255,2687,2688,2690,2693,2696,2699],{"class":257,"line":482},[255,2689,426],{"class":272},[255,2691,2692],{"class":265}," (e.key ",[255,2694,2695],{"class":272},"===",[255,2697,2698],{"class":261}," 'Tab'",[255,2700,1531],{"class":265},[255,2702,2703,2705,2708,2710,2713,2715],{"class":257,"line":500},[255,2704,426],{"class":272},[255,2706,2707],{"class":265}," (e.shiftKey ",[255,2709,2063],{"class":272},[255,2711,2712],{"class":265}," document.activeElement ",[255,2714,2695],{"class":272},[255,2716,2717],{"class":265}," firstEl) {\n",[255,2719,2720,2723,2726],{"class":257,"line":506},[255,2721,2722],{"class":265}," e.",[255,2724,2725],{"class":318},"preventDefault",[255,2727,341],{"class":265},[255,2729,2730,2733,2735],{"class":257,"line":511},[255,2731,2732],{"class":265}," lastEl.",[255,2734,488],{"class":318},[255,2736,341],{"class":265},[255,2738,2739,2742,2745,2747,2749,2751,2754,2756,2758,2760],{"class":257,"line":526},[255,2740,2741],{"class":265}," } ",[255,2743,2744],{"class":272},"else",[255,2746,426],{"class":272},[255,2748,1438],{"class":265},[255,2750,2562],{"class":272},[255,2752,2753],{"class":265},"e.shiftKey ",[255,2755,2063],{"class":272},[255,2757,2712],{"class":265},[255,2759,2695],{"class":272},[255,2761,2762],{"class":265}," lastEl) {\n",[255,2764,2765,2767,2769],{"class":257,"line":897},[255,2766,2722],{"class":265},[255,2768,2725],{"class":318},[255,2770,341],{"class":265},[255,2772,2773,2776,2778],{"class":257,"line":902},[255,2774,2775],{"class":265}," firstEl.",[255,2777,488],{"class":318},[255,2779,341],{"class":265},[255,2781,2782],{"class":257,"line":1637},[255,2783,461],{"class":265},[255,2785,2786],{"class":257,"line":1647},[255,2787,461],{"class":265},[255,2789,2790],{"class":257,"line":1657},[255,2791,2792],{"class":265}," }, [isActive, containerRef]);\n",[255,2794,2795],{"class":257,"line":1668},[255,2796,306],{"emptyLinePlaceholder":305},[255,2798,2799,2801,2803,2805],{"class":257,"line":1679},[255,2800,380],{"class":318},[255,2802,383],{"class":265},[255,2804,386],{"class":272},[255,2806,389],{"class":265},[255,2808,2809,2811],{"class":257,"line":1689},[255,2810,426],{"class":272},[255,2812,2813],{"class":265}," (isActive) {\n",[255,2815,2816,2819,2821,2823,2825,2828],{"class":257,"line":1694},[255,2817,2818],{"class":265}," previousFocusRef.current ",[255,2820,438],{"class":272},[255,2822,2712],{"class":265},[255,2824,2325],{"class":272},[255,2826,2827],{"class":318}," HTMLElement",[255,2829,266],{"class":265},[255,2831,2832,2834,2837,2839,2842],{"class":257,"line":1712},[255,2833,409],{"class":265},[255,2835,2836],{"class":318},"addEventListener",[255,2838,415],{"class":265},[255,2840,2841],{"class":261},"'keydown'",[255,2843,2844],{"class":265},", trapFocus);\n",[255,2846,2847,2849,2852,2854,2857,2860,2862,2864,2866,2868,2870],{"class":257,"line":1742},[255,2848,328],{"class":272},[255,2850,2851],{"class":331}," firstFocusable",[255,2853,335],{"class":272},[255,2855,2856],{"class":265}," containerRef.current?.",[255,2858,2859],{"class":318},"querySelector",[255,2861,415],{"class":265},[255,2863,2615],{"class":331},[255,2865,720],{"class":265},[255,2867,2325],{"class":272},[255,2869,2827],{"class":318},[255,2871,266],{"class":265},[255,2873,2874,2877,2879],{"class":257,"line":1748},[255,2875,2876],{"class":265}," firstFocusable?.",[255,2878,488],{"class":318},[255,2880,341],{"class":265},[255,2882,2883,2885,2887],{"class":257,"line":1757},[255,2884,2741],{"class":265},[255,2886,2744],{"class":272},[255,2888,389],{"class":265},[255,2890,2891,2893,2896,2898,2900],{"class":257,"line":1763},[255,2892,409],{"class":265},[255,2894,2895],{"class":318},"removeEventListener",[255,2897,415],{"class":265},[255,2899,2841],{"class":261},[255,2901,2844],{"class":265},[255,2903,2904,2907,2909],{"class":257,"line":1768},[255,2905,2906],{"class":265}," previousFocusRef.current?.",[255,2908,488],{"class":318},[255,2910,341],{"class":265},[255,2912,2913],{"class":257,"line":2251},[255,2914,461],{"class":265},[255,2916,2917,2919,2921,2923,2925,2927,2929,2931],{"class":257,"line":2274},[255,2918,514],{"class":272},[255,2920,1581],{"class":265},[255,2922,386],{"class":272},[255,2924,409],{"class":265},[255,2926,2895],{"class":318},[255,2928,415],{"class":265},[255,2930,2841],{"class":261},[255,2932,2844],{"class":265},[255,2934,2935],{"class":257,"line":2279},[255,2936,2937],{"class":265}," }, [isActive, trapFocus, containerRef]);\n",[255,2939,2940],{"class":257,"line":2289},[255,2941,529],{"class":265},[165,2943,2944,2946,2947,2950],{},[171,2945,534],{}," Conduct manual testing with multiple ATs to verify role, state, and property synchronization across interaction models. Validate that ",[181,2948,2949],{},"Escape"," closes overlays and returns focus appropriately.",[227,2952],{},[230,2954,2956],{"id":2955},"performance-optimization-a11y-balance","Performance Optimization & A11y Balance",[165,2958,2959],{},"Evaluating rendering tradeoffs to maintain both Core Web Vitals and inclusive user experiences requires balancing bundle size, hydration costs, and render-blocking scripts. Heavy JavaScript payloads can delay interactive readiness, directly impacting keyboard and screen reader responsiveness.",[165,2961,2962],{},"Analyze hydration costs, bundle size impacts, and render-blocking scripts on AT performance. Apply Performance vs Accessibility Tradeoffs to balance lazy loading with immediate focus requirements. Implement code-splitting strategies that preserve semantic document structure.",[246,2964,2966],{"className":248,"code":2965,"language":250,"meta":251,"style":251},"import dynamic from 'next\u002Fdynamic';\n\n\u002F\u002F Lazy-load heavy interactive component while preserving semantic structure\nconst HeavyDataGrid = dynamic(() => import('.\u002FHeavyDataGrid'), {\n ssr: false,\n loading: () => (\n \u003Cdiv role=\"grid\" aria-label=\"Loading data table\" aria-busy=\"true\" className=\"grid-placeholder\">\n \u003Cdiv className=\"grid-row\" aria-hidden=\"true\">Loading rows...\u003C\u002Fdiv>\n \u003C\u002Fdiv>\n )\n});\n\nexport default function DataPage() {\n return (\n \u003Cmain>\n \u003Ch1>Analytics\u003C\u002Fh1>\n \u003CHeavyDataGrid \u002F>\n \u003C\u002Fmain>\n );\n}\n",[181,2967,2968,2982,2986,2991,3018,3028,3040,3075,3101,3109,3114,3119,3123,3136,3142,3150,3163,3172,3180,3184],{"__ignoreMap":251},[255,2969,2970,2972,2975,2977,2980],{"class":257,"line":258},[255,2971,273],{"class":272},[255,2973,2974],{"class":265}," dynamic ",[255,2976,279],{"class":272},[255,2978,2979],{"class":261}," 'next\u002Fdynamic'",[255,2981,266],{"class":265},[255,2983,2984],{"class":257,"line":269},[255,2985,306],{"emptyLinePlaceholder":305},[255,2987,2988],{"class":257,"line":287},[255,2989,2990],{"class":395},"\u002F\u002F Lazy-load heavy interactive component while preserving semantic structure\n",[255,2992,2993,2995,2998,3000,3003,3005,3007,3010,3012,3015],{"class":257,"line":302},[255,2994,2441],{"class":272},[255,2996,2997],{"class":331}," HeavyDataGrid",[255,2999,335],{"class":272},[255,3001,3002],{"class":318}," dynamic",[255,3004,383],{"class":265},[255,3006,386],{"class":272},[255,3008,3009],{"class":272}," import",[255,3011,415],{"class":265},[255,3013,3014],{"class":261},"'.\u002FHeavyDataGrid'",[255,3016,3017],{"class":265},"), {\n",[255,3019,3020,3023,3025],{"class":257,"line":309},[255,3021,3022],{"class":265}," ssr: ",[255,3024,1918],{"class":331},[255,3026,3027],{"class":265},",\n",[255,3029,3030,3033,3036,3038],{"class":257,"line":325},[255,3031,3032],{"class":318}," loading",[255,3034,3035],{"class":265},": () ",[255,3037,386],{"class":272},[255,3039,731],{"class":265},[255,3041,3042,3044,3046,3048,3050,3053,3055,3057,3060,3062,3064,3066,3068,3070,3073],{"class":257,"line":344},[255,3043,736],{"class":265},[255,3045,1190],{"class":739},[255,3047,1163],{"class":318},[255,3049,438],{"class":272},[255,3051,3052],{"class":261},"\"grid\"",[255,3054,1045],{"class":318},[255,3056,438],{"class":272},[255,3058,3059],{"class":261},"\"Loading data table\"",[255,3061,771],{"class":318},[255,3063,438],{"class":272},[255,3065,860],{"class":261},[255,3067,809],{"class":318},[255,3069,438],{"class":272},[255,3071,3072],{"class":261},"\"grid-placeholder\"",[255,3074,885],{"class":265},[255,3076,3077,3079,3081,3083,3085,3088,3090,3092,3094,3097,3099],{"class":257,"line":372},[255,3078,736],{"class":265},[255,3080,1190],{"class":739},[255,3082,809],{"class":318},[255,3084,438],{"class":272},[255,3086,3087],{"class":261},"\"grid-row\"",[255,3089,855],{"class":318},[255,3091,438],{"class":272},[255,3093,860],{"class":261},[255,3095,3096],{"class":265},">Loading rows...\u003C\u002F",[255,3098,1190],{"class":739},[255,3100,885],{"class":265},[255,3102,3103,3105,3107],{"class":257,"line":377},[255,3104,879],{"class":265},[255,3106,1190],{"class":739},[255,3108,885],{"class":265},[255,3110,3111],{"class":257,"line":392},[255,3112,3113],{"class":265}," )\n",[255,3115,3116],{"class":257,"line":399},[255,3117,3118],{"class":265},"});\n",[255,3120,3121],{"class":257,"line":423},[255,3122,306],{"emptyLinePlaceholder":305},[255,3124,3125,3127,3129,3131,3134],{"class":257,"line":432},[255,3126,312],{"class":272},[255,3128,984],{"class":272},[255,3130,315],{"class":272},[255,3132,3133],{"class":318}," DataPage",[255,3135,322],{"class":265},[255,3137,3138,3140],{"class":257,"line":458},[255,3139,514],{"class":272},[255,3141,731],{"class":265},[255,3143,3144,3146,3148],{"class":257,"line":464},[255,3145,736],{"class":265},[255,3147,1004],{"class":739},[255,3149,885],{"class":265},[255,3151,3152,3154,3156,3159,3161],{"class":257,"line":470},[255,3153,736],{"class":265},[255,3155,162],{"class":739},[255,3157,3158],{"class":265},">Analytics\u003C\u002F",[255,3160,162],{"class":739},[255,3162,885],{"class":265},[255,3164,3165,3167,3170],{"class":257,"line":476},[255,3166,736],{"class":265},[255,3168,3169],{"class":331},"HeavyDataGrid",[255,3171,1063],{"class":265},[255,3173,3174,3176,3178],{"class":257,"line":482},[255,3175,879],{"class":265},[255,3177,1004],{"class":739},[255,3179,885],{"class":265},[255,3181,3182],{"class":257,"line":500},[255,3183,890],{"class":265},[255,3185,3186],{"class":257,"line":506},[255,3187,529],{"class":265},[165,3189,3190,3192],{},[171,3191,534],{}," Audit Lighthouse a11y scores alongside Web Vitals; test screen reader responsiveness under throttled network conditions to ensure fallback states remain accessible.",[227,3194],{},[230,3196,3198],{"id":3197},"common-pitfalls","Common Pitfalls",[175,3200,3201,3219,3222,3225,3231],{},[178,3202,3203,3204,68,3206,3208,3209,670,3212,670,3215,3218],{},"Over-reliance on ",[181,3205,1190],{},[181,3207,255],{}," instead of semantic HTML elements (",[181,3210,3211],{},"\u003Cbutton>",[181,3213,3214],{},"\u003Cnav>",[181,3216,3217],{},"\u003Carticle>",").",[178,3220,3221],{},"Missing focus restoration after modal dismissal or client-side route change.",[178,3223,3224],{},"Unmanaged hydration causing screen reader DOM desynchronization and duplicate announcements.",[178,3226,3227,3228,3230],{},"Excessive ",[181,3229,1281],{}," updates causing announcement queue flooding and speech interruption.",[178,3232,3233,3234,3237,3238,3218],{},"Using ",[181,3235,3236],{},"aria-hidden"," on interactive elements without removing them from the tab order (",[181,3239,3240],{},"tabindex=\"-1\"",[227,3242],{},[230,3244,3246],{"id":3245},"frequently-asked-questions","Frequently Asked Questions",[165,3248,3249,3252,3253,3255],{},[171,3250,3251],{},"How do I prevent screen reader confusion during Next.js client-side navigation?","\nImplement route change announcements using a centralized ",[181,3254,1281],{}," region, restore focus to the main content heading or skip link after navigation, and ensure layout templates maintain consistent landmark roles across all pages.",[165,3257,3258,3261],{},[171,3259,3260],{},"When should I use React Server Components versus Client Components for accessibility?","\nUse Server Components for static, semantic content to reduce JS payload and improve initial render. Use Client Components only for interactive elements requiring state, event listeners, or browser APIs, ensuring they are progressively enhanced with accessible fallbacks.",[165,3263,3264,3267,3268,3271,3272,3274],{},[171,3265,3266],{},"How do I handle dynamic content updates without flooding the screen reader?","\nUse ",[181,3269,3270],{},"aria-live=\"polite\""," for non-urgent updates and ",[181,3273,1294],{}," only for critical alerts. Debounce or batch rapid DOM changes, and ensure live regions are present in the DOM before content updates occur to prevent silent failures.",[165,3276,3277,3280],{},[171,3278,3279],{},"Is it better to build custom accessible components or use a library?","\nFor most teams, using a well-maintained accessible component library reduces ARIA debt and testing overhead. Build custom components only when design requirements exceed library capabilities, and rigorously test them against WAI-ARIA authoring practices.",[3282,3283,3284],"style",{},"html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":251,"searchDepth":269,"depth":269,"links":3286},[3287,3288,3289,3290,3291,3292,3293,3294,3295],{"id":232,"depth":269,"text":233},{"id":540,"depth":269,"text":541},{"id":922,"depth":269,"text":923},{"id":1271,"depth":269,"text":1272},{"id":1780,"depth":269,"text":1781},{"id":2401,"depth":269,"text":2402},{"id":2955,"depth":269,"text":2956},{"id":3197,"depth":269,"text":3198},{"id":3245,"depth":269,"text":3246},null,"Build WCAG-aligned React and Next.js experiences with production-focused patterns for routing, state changes, keyboard flows, and screen reader support.","md",{},false,{"title":76,"description":3297},"4FvQtLWfUQIaBHmnxhFBTrVgDfCepNOER1lfc4E07C8",[3304,3334,3335],{"title":5,"path":6,"stem":7,"children":3305,"page":-1},[3306,3307,3310,3313,3319,3325,3331],{"title":10,"path":6,"stem":11},{"title":13,"path":14,"stem":15,"children":3308},[3309],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21,"children":3311},[3312],{"title":19,"path":20,"stem":21},{"title":25,"path":26,"stem":27,"children":3314,"page":-1},[3315,3316],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":3317},[3318],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":3320,"page":-1},[3321,3322],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45,"children":3323},[3324],{"title":43,"path":44,"stem":45},{"title":49,"path":50,"stem":51,"children":3326},[3327,3328],{"title":49,"path":50,"stem":51},{"title":55,"path":56,"stem":57,"children":3329},[3330],{"title":55,"path":56,"stem":57},{"title":61,"path":62,"stem":63,"children":3332},[3333],{"title":61,"path":62,"stem":63},{"title":67,"path":68,"stem":69},{"title":71,"path":72,"stem":73,"children":3336,"page":-1},[3337,3338,3344,3350,3353,3362,3371],{"title":76,"path":72,"stem":77},{"title":79,"path":80,"stem":81,"children":3339,"page":-1},[3340,3341],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87,"children":3342},[3343],{"title":85,"path":86,"stem":87},{"title":91,"path":92,"stem":93,"children":3345},[3346,3347],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99,"children":3348},[3349],{"title":97,"path":98,"stem":99},{"title":103,"path":104,"stem":105,"children":3351},[3352],{"title":103,"path":104,"stem":105},{"title":109,"path":110,"stem":111,"children":3354,"page":-1},[3355,3356,3359],{"title":109,"path":110,"stem":111},{"title":115,"path":116,"stem":117,"children":3357},[3358],{"title":115,"path":116,"stem":117},{"title":121,"path":122,"stem":123,"children":3360},[3361],{"title":121,"path":122,"stem":123},{"title":127,"path":128,"stem":129,"children":3363,"page":-1},[3364,3365,3368],{"title":127,"path":128,"stem":129},{"title":133,"path":134,"stem":135,"children":3366},[3367],{"title":133,"path":134,"stem":135},{"title":139,"path":140,"stem":141,"children":3369},[3370],{"title":139,"path":140,"stem":141},{"title":145,"path":146,"stem":147,"children":3372,"page":-1},[3373,3374],{"title":145,"path":146,"stem":147},{"title":151,"path":152,"stem":153,"children":3375},[3376],{"title":151,"path":152,"stem":153},1778094795979]