[{"data":1,"prerenderedAt":2673},["ShallowReactive",2],{"site-header-nav":3,"page-\u002Freact-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002Freact-context-for-global-accessibility-preferences\u002F":156,"content-navigation":2599},[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":97,"body":158,"date":2592,"description":2593,"extension":2594,"image":2592,"meta":2595,"modifiedAt":2592,"navigation":260,"noindex":2596,"path":98,"publishedAt":2592,"seo":2597,"stem":99,"updatedAt":2592,"__hash__":2598},"content\u002Freact-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002Freact-context-for-global-accessibility-preferences\u002Findex.md",{"type":159,"value":160,"toc":2569},"minimark",[161,165,179,184,192,197,233,975,986,990,996,999,1038,1373,1383,1387,1394,1397,1412,1623,1635,1639,1642,1645,1689,1825,1830,1834,1837,1840,1874,2209,2214,2218,2222,2273,2277,2458,2469,2473,2515,2519,2537,2550,2565],[162,163,97],"h1",{"id":164},"implementing-react-context-for-global-accessibility-preferences",[166,167,168,169,174,175,178],"p",{},"Establishing a centralized architecture using React Context allows developers to propagate user-defined accessibility settings across complex component trees. This guide details how to build a type-safe, performant context provider that manages preferences like reduced motion, high contrast, and screen reader verbosity. By synchronizing these states with system-level media queries and local storage, teams can ensure consistent ",[170,171,173],"a",{"href":172},"\u002Freact-nextjs-accessibility-patterns\u002Fdynamic-content-state-announcements\u002F","Dynamic Content & State Announcements"," without triggering unnecessary re-renders or breaking assistive technology expectations. This implementation aligns with established ",[170,176,76],{"href":177},"\u002Freact-nextjs-accessibility-patterns\u002F"," and satisfies WCAG 2.1 Success Criteria 1.4.8 (Visual Presentation), 2.2.2 (Pause, Stop, Hide), 3.2.1 (On Focus), and 3.3.2 (Labels or Instructions).",[180,181,183],"h2",{"id":182},"context-architecture-provider-setup","Context Architecture & Provider Setup",[166,185,186,187,191],{},"Define a strict TypeScript interface and a stable provider wrapper. The provider must initialize with system defaults, defer client-side hydration to prevent mismatches, and expose a stable ",[188,189,190],"code",{},"updatePreference"," reference to prevent cascading re-renders.",[193,194,196],"h3",{"id":195},"implementation-steps","Implementation Steps",[198,199,200,212,219,222],"ol",{},[201,202,203,204,207,208,211],"li",{},"Create a dedicated ",[188,205,206],{},"AccessibilityContext"," with a strict ",[188,209,210],{},"AccessibilityPrefs"," type.",[201,213,214,215,218],{},"Initialize state using lazy initialization to defer ",[188,216,217],{},"localStorage"," reads until mount.",[201,220,221],{},"Memoize the context value object to maintain referential equality across renders.",[201,223,224,225,228,229,232],{},"Wrap the root ",[188,226,227],{},"layout.tsx"," (Next.js App Router) or ",[188,230,231],{},"_app.tsx"," (Pages Router) with the provider.",[234,235,240],"pre",{"className":236,"code":237,"language":238,"meta":239,"style":239},"language-tsx shiki shiki-themes github-light github-dark","'use client';\n\nimport { createContext, useContext, useState, useEffect, useMemo, useCallback, ReactNode } from 'react';\n\nexport type AccessibilityPrefs = {\n reducedMotion: boolean;\n highContrast: boolean;\n screenReaderMode: boolean;\n updatePreference: (key: keyof Omit\u003CAccessibilityPrefs, 'updatePreference'>, value: boolean) => void;\n};\n\nconst AccessibilityContext = createContext\u003CAccessibilityPrefs | undefined>(undefined);\n\nconst STORAGE_KEY = 'app-a11y-prefs';\n\nexport const AccessibilityProvider = ({ children }: { children: ReactNode }) => {\n const [prefs, setPrefs] = useState\u003COmit\u003CAccessibilityPrefs, 'updatePreference'>>(() => ({\n reducedMotion: false,\n highContrast: false,\n screenReaderMode: false,\n }));\n\n const updatePreference = useCallback((key: keyof Omit\u003CAccessibilityPrefs, 'updatePreference'>, value: boolean) => {\n setPrefs(prev => {\n const next = { ...prev, [key]: value };\n if (typeof window !== 'undefined') {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\n }\n return next;\n });\n }, []);\n\n \u002F\u002F Hydration-safe initialization\n useEffect(() => {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n try {\n setPrefs(JSON.parse(stored));\n } catch {\n \u002F\u002F Fallback to defaults on parse failure\n }\n }\n }, []);\n\n const contextValue = useMemo\u003CAccessibilityPrefs>(\n () => ({ ...prefs, updatePreference }),\n [prefs, updatePreference]\n );\n\n return (\n \u003CAccessibilityContext.Provider value={contextValue}>\n {children}\n \u003C\u002FAccessibilityContext.Provider>\n );\n};\n","tsx","",[188,241,242,255,262,280,285,304,320,332,344,398,404,409,442,447,462,467,508,554,566,576,586,592,597,642,659,677,700,728,734,743,749,755,760,767,780,801,809,817,834,845,851,856,861,866,871,891,906,912,918,923,931,948,954,965,970],{"__ignoreMap":239},[243,244,247,251],"span",{"class":245,"line":246},"line",1,[243,248,250],{"class":249},"sZZnC","'use client'",[243,252,254],{"class":253},"sVt8B",";\n",[243,256,258],{"class":245,"line":257},2,[243,259,261],{"emptyLinePlaceholder":260},true,"\n",[243,263,265,269,272,275,278],{"class":245,"line":264},3,[243,266,268],{"class":267},"szBVR","import",[243,270,271],{"class":253}," { createContext, useContext, useState, useEffect, useMemo, useCallback, ReactNode } ",[243,273,274],{"class":267},"from",[243,276,277],{"class":249}," 'react'",[243,279,254],{"class":253},[243,281,283],{"class":245,"line":282},4,[243,284,261],{"emptyLinePlaceholder":260},[243,286,288,291,294,298,301],{"class":245,"line":287},5,[243,289,290],{"class":267},"export",[243,292,293],{"class":267}," type",[243,295,297],{"class":296},"sScJk"," AccessibilityPrefs",[243,299,300],{"class":267}," =",[243,302,303],{"class":253}," {\n",[243,305,307,311,314,318],{"class":245,"line":306},6,[243,308,310],{"class":309},"s4XuR"," reducedMotion",[243,312,313],{"class":267},":",[243,315,317],{"class":316},"sj4cs"," boolean",[243,319,254],{"class":253},[243,321,323,326,328,330],{"class":245,"line":322},7,[243,324,325],{"class":309}," highContrast",[243,327,313],{"class":267},[243,329,317],{"class":316},[243,331,254],{"class":253},[243,333,335,338,340,342],{"class":245,"line":334},8,[243,336,337],{"class":309}," screenReaderMode",[243,339,313],{"class":267},[243,341,317],{"class":316},[243,343,254],{"class":253},[243,345,347,350,352,355,358,360,363,366,369,371,374,377,380,383,385,387,390,393,396],{"class":245,"line":346},9,[243,348,349],{"class":296}," updatePreference",[243,351,313],{"class":267},[243,353,354],{"class":253}," (",[243,356,357],{"class":309},"key",[243,359,313],{"class":267},[243,361,362],{"class":267}," keyof",[243,364,365],{"class":296}," Omit",[243,367,368],{"class":253},"\u003C",[243,370,210],{"class":296},[243,372,373],{"class":253},", ",[243,375,376],{"class":249},"'updatePreference'",[243,378,379],{"class":253},">, ",[243,381,382],{"class":309},"value",[243,384,313],{"class":267},[243,386,317],{"class":316},[243,388,389],{"class":253},") ",[243,391,392],{"class":267},"=>",[243,394,395],{"class":316}," void",[243,397,254],{"class":253},[243,399,401],{"class":245,"line":400},10,[243,402,403],{"class":253},"};\n",[243,405,407],{"class":245,"line":406},11,[243,408,261],{"emptyLinePlaceholder":260},[243,410,412,415,418,420,423,425,427,430,433,436,439],{"class":245,"line":411},12,[243,413,414],{"class":267},"const",[243,416,417],{"class":316}," AccessibilityContext",[243,419,300],{"class":267},[243,421,422],{"class":296}," createContext",[243,424,368],{"class":253},[243,426,210],{"class":296},[243,428,429],{"class":267}," |",[243,431,432],{"class":316}," undefined",[243,434,435],{"class":253},">(",[243,437,438],{"class":316},"undefined",[243,440,441],{"class":253},");\n",[243,443,445],{"class":245,"line":444},13,[243,446,261],{"emptyLinePlaceholder":260},[243,448,450,452,455,457,460],{"class":245,"line":449},14,[243,451,414],{"class":267},[243,453,454],{"class":316}," STORAGE_KEY",[243,456,300],{"class":267},[243,458,459],{"class":249}," 'app-a11y-prefs'",[243,461,254],{"class":253},[243,463,465],{"class":245,"line":464},15,[243,466,261],{"emptyLinePlaceholder":260},[243,468,470,472,475,478,480,483,486,489,491,494,496,498,501,504,506],{"class":245,"line":469},16,[243,471,290],{"class":267},[243,473,474],{"class":267}," const",[243,476,477],{"class":296}," AccessibilityProvider",[243,479,300],{"class":267},[243,481,482],{"class":253}," ({ ",[243,484,485],{"class":309},"children",[243,487,488],{"class":253}," }",[243,490,313],{"class":267},[243,492,493],{"class":253}," { ",[243,495,485],{"class":309},[243,497,313],{"class":267},[243,499,500],{"class":296}," ReactNode",[243,502,503],{"class":253}," }) ",[243,505,392],{"class":267},[243,507,303],{"class":253},[243,509,511,513,516,519,521,524,527,530,533,535,538,540,542,544,546,549,551],{"class":245,"line":510},17,[243,512,474],{"class":267},[243,514,515],{"class":253}," [",[243,517,518],{"class":316},"prefs",[243,520,373],{"class":253},[243,522,523],{"class":316},"setPrefs",[243,525,526],{"class":253},"] ",[243,528,529],{"class":267},"=",[243,531,532],{"class":296}," useState",[243,534,368],{"class":253},[243,536,537],{"class":296},"Omit",[243,539,368],{"class":253},[243,541,210],{"class":296},[243,543,373],{"class":253},[243,545,376],{"class":249},[243,547,548],{"class":253},">>(() ",[243,550,392],{"class":267},[243,552,553],{"class":253}," ({\n",[243,555,557,560,563],{"class":245,"line":556},18,[243,558,559],{"class":253}," reducedMotion: ",[243,561,562],{"class":316},"false",[243,564,565],{"class":253},",\n",[243,567,569,572,574],{"class":245,"line":568},19,[243,570,571],{"class":253}," highContrast: ",[243,573,562],{"class":316},[243,575,565],{"class":253},[243,577,579,582,584],{"class":245,"line":578},20,[243,580,581],{"class":253}," screenReaderMode: ",[243,583,562],{"class":316},[243,585,565],{"class":253},[243,587,589],{"class":245,"line":588},21,[243,590,591],{"class":253}," }));\n",[243,593,595],{"class":245,"line":594},22,[243,596,261],{"emptyLinePlaceholder":260},[243,598,600,602,604,606,609,612,614,616,618,620,622,624,626,628,630,632,634,636,638,640],{"class":245,"line":599},23,[243,601,474],{"class":267},[243,603,349],{"class":316},[243,605,300],{"class":267},[243,607,608],{"class":296}," useCallback",[243,610,611],{"class":253},"((",[243,613,357],{"class":309},[243,615,313],{"class":267},[243,617,362],{"class":267},[243,619,365],{"class":296},[243,621,368],{"class":253},[243,623,210],{"class":296},[243,625,373],{"class":253},[243,627,376],{"class":249},[243,629,379],{"class":253},[243,631,382],{"class":309},[243,633,313],{"class":267},[243,635,317],{"class":316},[243,637,389],{"class":253},[243,639,392],{"class":267},[243,641,303],{"class":253},[243,643,645,648,651,654,657],{"class":245,"line":644},24,[243,646,647],{"class":296}," setPrefs",[243,649,650],{"class":253},"(",[243,652,653],{"class":309},"prev",[243,655,656],{"class":267}," =>",[243,658,303],{"class":253},[243,660,662,664,667,669,671,674],{"class":245,"line":661},25,[243,663,474],{"class":267},[243,665,666],{"class":316}," next",[243,668,300],{"class":267},[243,670,493],{"class":253},[243,672,673],{"class":267},"...",[243,675,676],{"class":253},"prev, [key]: value };\n",[243,678,680,683,685,688,691,694,697],{"class":245,"line":679},26,[243,681,682],{"class":267}," if",[243,684,354],{"class":253},[243,686,687],{"class":267},"typeof",[243,689,690],{"class":253}," window ",[243,692,693],{"class":267},"!==",[243,695,696],{"class":249}," 'undefined'",[243,698,699],{"class":253},") {\n",[243,701,703,706,709,711,714,716,719,722,725],{"class":245,"line":702},27,[243,704,705],{"class":253}," localStorage.",[243,707,708],{"class":296},"setItem",[243,710,650],{"class":253},[243,712,713],{"class":316},"STORAGE_KEY",[243,715,373],{"class":253},[243,717,718],{"class":316},"JSON",[243,720,721],{"class":253},".",[243,723,724],{"class":296},"stringify",[243,726,727],{"class":253},"(next));\n",[243,729,731],{"class":245,"line":730},28,[243,732,733],{"class":253}," }\n",[243,735,737,740],{"class":245,"line":736},29,[243,738,739],{"class":267}," return",[243,741,742],{"class":253}," next;\n",[243,744,746],{"class":245,"line":745},30,[243,747,748],{"class":253}," });\n",[243,750,752],{"class":245,"line":751},31,[243,753,754],{"class":253}," }, []);\n",[243,756,758],{"class":245,"line":757},32,[243,759,261],{"emptyLinePlaceholder":260},[243,761,763],{"class":245,"line":762},33,[243,764,766],{"class":765},"sJ8bj"," \u002F\u002F Hydration-safe initialization\n",[243,768,770,773,776,778],{"class":245,"line":769},34,[243,771,772],{"class":296}," useEffect",[243,774,775],{"class":253},"(() ",[243,777,392],{"class":267},[243,779,303],{"class":253},[243,781,783,785,788,790,792,795,797,799],{"class":245,"line":782},35,[243,784,474],{"class":267},[243,786,787],{"class":316}," stored",[243,789,300],{"class":267},[243,791,705],{"class":253},[243,793,794],{"class":296},"getItem",[243,796,650],{"class":253},[243,798,713],{"class":316},[243,800,441],{"class":253},[243,802,804,806],{"class":245,"line":803},36,[243,805,682],{"class":267},[243,807,808],{"class":253}," (stored) {\n",[243,810,812,815],{"class":245,"line":811},37,[243,813,814],{"class":267}," try",[243,816,303],{"class":253},[243,818,820,822,824,826,828,831],{"class":245,"line":819},38,[243,821,647],{"class":296},[243,823,650],{"class":253},[243,825,718],{"class":316},[243,827,721],{"class":253},[243,829,830],{"class":296},"parse",[243,832,833],{"class":253},"(stored));\n",[243,835,837,840,843],{"class":245,"line":836},39,[243,838,839],{"class":253}," } ",[243,841,842],{"class":267},"catch",[243,844,303],{"class":253},[243,846,848],{"class":245,"line":847},40,[243,849,850],{"class":765}," \u002F\u002F Fallback to defaults on parse failure\n",[243,852,854],{"class":245,"line":853},41,[243,855,733],{"class":253},[243,857,859],{"class":245,"line":858},42,[243,860,733],{"class":253},[243,862,864],{"class":245,"line":863},43,[243,865,754],{"class":253},[243,867,869],{"class":245,"line":868},44,[243,870,261],{"emptyLinePlaceholder":260},[243,872,874,876,879,881,884,886,888],{"class":245,"line":873},45,[243,875,474],{"class":267},[243,877,878],{"class":316}," contextValue",[243,880,300],{"class":267},[243,882,883],{"class":296}," useMemo",[243,885,368],{"class":253},[243,887,210],{"class":296},[243,889,890],{"class":253},">(\n",[243,892,894,897,899,901,903],{"class":245,"line":893},46,[243,895,896],{"class":253}," () ",[243,898,392],{"class":267},[243,900,482],{"class":253},[243,902,673],{"class":267},[243,904,905],{"class":253},"prefs, updatePreference }),\n",[243,907,909],{"class":245,"line":908},47,[243,910,911],{"class":253}," [prefs, updatePreference]\n",[243,913,915],{"class":245,"line":914},48,[243,916,917],{"class":253}," );\n",[243,919,921],{"class":245,"line":920},49,[243,922,261],{"emptyLinePlaceholder":260},[243,924,926,928],{"class":245,"line":925},50,[243,927,739],{"class":267},[243,929,930],{"class":253}," (\n",[243,932,934,937,940,943,945],{"class":245,"line":933},51,[243,935,936],{"class":253}," \u003C",[243,938,939],{"class":316},"AccessibilityContext.Provider",[243,941,942],{"class":296}," value",[243,944,529],{"class":267},[243,946,947],{"class":253},"{contextValue}>\n",[243,949,951],{"class":245,"line":950},52,[243,952,953],{"class":253}," {children}\n",[243,955,957,960,962],{"class":245,"line":956},53,[243,958,959],{"class":253}," \u003C\u002F",[243,961,939],{"class":316},[243,963,964],{"class":253},">\n",[243,966,968],{"class":245,"line":967},54,[243,969,917],{"class":253},[243,971,973],{"class":245,"line":972},55,[243,974,403],{"class":253},[166,976,977,981,982,985],{},[978,979,980],"strong",{},"Testing Note:"," Verify that child components receive default values before hydration completes. Use ",[188,983,984],{},"hydrateRoot"," in a test environment to confirm the provider does not block initial paint or trigger hydration mismatch warnings.",[180,987,989],{"id":988},"synchronizing-with-system-preferences","Synchronizing with System Preferences",[166,991,992,993,995],{},"Implement real-time tracking of OS\u002Fbrowser media queries. System preferences act as the baseline; explicit user overrides stored in ",[188,994,217],{}," take precedence.",[193,997,196],{"id":998},"implementation-steps-1",[198,1000,1001,1016,1029,1035],{},[201,1002,1003,1004,1007,1008,1011,1012,1015],{},"Create a ",[188,1005,1006],{},"useMediaQuery"," hook utilizing ",[188,1009,1010],{},"window.matchMedia"," and ",[188,1013,1014],{},"useSyncExternalStore"," (React 18) for zero-overhead subscription.",[201,1017,1018,1019,1022,1023,1011,1026,721],{},"Attach ",[188,1020,1021],{},"change"," listeners to ",[188,1024,1025],{},"prefers-reduced-motion",[188,1027,1028],{},"prefers-contrast",[201,1030,1031,1032,721],{},"Implement a priority chain: ",[188,1033,1034],{},"User Override > System Preference > App Default",[201,1036,1037],{},"Defer media query evaluation to client-side only to prevent SSR hydration mismatches.",[234,1039,1041],{"className":236,"code":1040,"language":238,"meta":239,"style":239},"import { useSyncExternalStore } from 'react';\n\nfunction subscribeToMediaQuery(query: string, callback: (matches: boolean) => void) {\n const mql = window.matchMedia(query);\n const handler = (e: MediaQueryListEvent) => callback(e.matches);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n\nexport function useSystemMediaQuery(query: string): boolean {\n return useSyncExternalStore(\n (callback) => subscribeToMediaQuery(query, callback),\n () => window.matchMedia(query).matches,\n () => false \u002F\u002F Fallback for SSR\n );\n}\n\n\u002F\u002F Integration inside AccessibilityProvider\nexport const AccessibilityProvider = ({ children }: { children: ReactNode }) => {\n const systemReducedMotion = useSystemMediaQuery('(prefers-reduced-motion: reduce)');\n const systemHighContrast = useSystemMediaQuery('(prefers-contrast: more)');\n\n \u002F\u002F Merge system state with user overrides in state initialization\u002Fupdate logic\n \u002F\u002F ...\n};\n",[188,1042,1043,1056,1060,1102,1120,1149,1165,1184,1189,1193,1220,1230,1245,1258,1270,1274,1278,1282,1287,1319,1337,1355,1359,1364,1369],{"__ignoreMap":239},[243,1044,1045,1047,1050,1052,1054],{"class":245,"line":246},[243,1046,268],{"class":267},[243,1048,1049],{"class":253}," { useSyncExternalStore } ",[243,1051,274],{"class":267},[243,1053,277],{"class":249},[243,1055,254],{"class":253},[243,1057,1058],{"class":245,"line":257},[243,1059,261],{"emptyLinePlaceholder":260},[243,1061,1062,1065,1068,1070,1073,1075,1078,1080,1083,1085,1087,1090,1092,1094,1096,1098,1100],{"class":245,"line":264},[243,1063,1064],{"class":267},"function",[243,1066,1067],{"class":296}," subscribeToMediaQuery",[243,1069,650],{"class":253},[243,1071,1072],{"class":309},"query",[243,1074,313],{"class":267},[243,1076,1077],{"class":316}," string",[243,1079,373],{"class":253},[243,1081,1082],{"class":296},"callback",[243,1084,313],{"class":267},[243,1086,354],{"class":253},[243,1088,1089],{"class":309},"matches",[243,1091,313],{"class":267},[243,1093,317],{"class":316},[243,1095,389],{"class":253},[243,1097,392],{"class":267},[243,1099,395],{"class":316},[243,1101,699],{"class":253},[243,1103,1104,1106,1109,1111,1114,1117],{"class":245,"line":282},[243,1105,474],{"class":267},[243,1107,1108],{"class":316}," mql",[243,1110,300],{"class":267},[243,1112,1113],{"class":253}," window.",[243,1115,1116],{"class":296},"matchMedia",[243,1118,1119],{"class":253},"(query);\n",[243,1121,1122,1124,1127,1129,1131,1134,1136,1139,1141,1143,1146],{"class":245,"line":287},[243,1123,474],{"class":267},[243,1125,1126],{"class":296}," handler",[243,1128,300],{"class":267},[243,1130,354],{"class":253},[243,1132,1133],{"class":309},"e",[243,1135,313],{"class":267},[243,1137,1138],{"class":296}," MediaQueryListEvent",[243,1140,389],{"class":253},[243,1142,392],{"class":267},[243,1144,1145],{"class":296}," callback",[243,1147,1148],{"class":253},"(e.matches);\n",[243,1150,1151,1154,1157,1159,1162],{"class":245,"line":306},[243,1152,1153],{"class":253}," mql.",[243,1155,1156],{"class":296},"addEventListener",[243,1158,650],{"class":253},[243,1160,1161],{"class":249},"'change'",[243,1163,1164],{"class":253},", handler);\n",[243,1166,1167,1169,1171,1173,1175,1178,1180,1182],{"class":245,"line":322},[243,1168,739],{"class":267},[243,1170,896],{"class":253},[243,1172,392],{"class":267},[243,1174,1153],{"class":253},[243,1176,1177],{"class":296},"removeEventListener",[243,1179,650],{"class":253},[243,1181,1161],{"class":249},[243,1183,1164],{"class":253},[243,1185,1186],{"class":245,"line":334},[243,1187,1188],{"class":253},"}\n",[243,1190,1191],{"class":245,"line":346},[243,1192,261],{"emptyLinePlaceholder":260},[243,1194,1195,1197,1200,1203,1205,1207,1209,1211,1214,1216,1218],{"class":245,"line":400},[243,1196,290],{"class":267},[243,1198,1199],{"class":267}," function",[243,1201,1202],{"class":296}," useSystemMediaQuery",[243,1204,650],{"class":253},[243,1206,1072],{"class":309},[243,1208,313],{"class":267},[243,1210,1077],{"class":316},[243,1212,1213],{"class":253},")",[243,1215,313],{"class":267},[243,1217,317],{"class":316},[243,1219,303],{"class":253},[243,1221,1222,1224,1227],{"class":245,"line":406},[243,1223,739],{"class":267},[243,1225,1226],{"class":296}," useSyncExternalStore",[243,1228,1229],{"class":253},"(\n",[243,1231,1232,1234,1236,1238,1240,1242],{"class":245,"line":411},[243,1233,354],{"class":253},[243,1235,1082],{"class":309},[243,1237,389],{"class":253},[243,1239,392],{"class":267},[243,1241,1067],{"class":296},[243,1243,1244],{"class":253},"(query, callback),\n",[243,1246,1247,1249,1251,1253,1255],{"class":245,"line":444},[243,1248,896],{"class":253},[243,1250,392],{"class":267},[243,1252,1113],{"class":253},[243,1254,1116],{"class":296},[243,1256,1257],{"class":253},"(query).matches,\n",[243,1259,1260,1262,1264,1267],{"class":245,"line":449},[243,1261,896],{"class":253},[243,1263,392],{"class":267},[243,1265,1266],{"class":316}," false",[243,1268,1269],{"class":765}," \u002F\u002F Fallback for SSR\n",[243,1271,1272],{"class":245,"line":464},[243,1273,917],{"class":253},[243,1275,1276],{"class":245,"line":469},[243,1277,1188],{"class":253},[243,1279,1280],{"class":245,"line":510},[243,1281,261],{"emptyLinePlaceholder":260},[243,1283,1284],{"class":245,"line":556},[243,1285,1286],{"class":765},"\u002F\u002F Integration inside AccessibilityProvider\n",[243,1288,1289,1291,1293,1295,1297,1299,1301,1303,1305,1307,1309,1311,1313,1315,1317],{"class":245,"line":568},[243,1290,290],{"class":267},[243,1292,474],{"class":267},[243,1294,477],{"class":296},[243,1296,300],{"class":267},[243,1298,482],{"class":253},[243,1300,485],{"class":309},[243,1302,488],{"class":253},[243,1304,313],{"class":267},[243,1306,493],{"class":253},[243,1308,485],{"class":309},[243,1310,313],{"class":267},[243,1312,500],{"class":296},[243,1314,503],{"class":253},[243,1316,392],{"class":267},[243,1318,303],{"class":253},[243,1320,1321,1323,1326,1328,1330,1332,1335],{"class":245,"line":578},[243,1322,474],{"class":267},[243,1324,1325],{"class":316}," systemReducedMotion",[243,1327,300],{"class":267},[243,1329,1202],{"class":296},[243,1331,650],{"class":253},[243,1333,1334],{"class":249},"'(prefers-reduced-motion: reduce)'",[243,1336,441],{"class":253},[243,1338,1339,1341,1344,1346,1348,1350,1353],{"class":245,"line":588},[243,1340,474],{"class":267},[243,1342,1343],{"class":316}," systemHighContrast",[243,1345,300],{"class":267},[243,1347,1202],{"class":296},[243,1349,650],{"class":253},[243,1351,1352],{"class":249},"'(prefers-contrast: more)'",[243,1354,441],{"class":253},[243,1356,1357],{"class":245,"line":594},[243,1358,261],{"emptyLinePlaceholder":260},[243,1360,1361],{"class":245,"line":599},[243,1362,1363],{"class":765}," \u002F\u002F Merge system state with user overrides in state initialization\u002Fupdate logic\n",[243,1365,1366],{"class":245,"line":644},[243,1367,1368],{"class":765}," \u002F\u002F ...\n",[243,1370,1371],{"class":245,"line":661},[243,1372,403],{"class":253},[166,1374,1375,1377,1378,1011,1380,1382],{},[978,1376,980],{}," Use browser DevTools device emulation to toggle ",[188,1379,1025],{},[188,1381,1028],{},". Confirm state updates propagate to the context without full page reloads or hydration warnings.",[180,1384,1386],{"id":1385},"consumer-implementation-hook-abstraction","Consumer Implementation & Hook Abstraction",[166,1388,1389,1390,1393],{},"Abstract ",[188,1391,1392],{},"useContext"," into a custom hook that enforces provider boundaries and returns memoized slices. This prevents null-context errors and isolates component subscriptions.",[193,1395,196],{"id":1396},"implementation-steps-2",[198,1398,1399,1406,1409],{},[201,1400,1401,1402,1405],{},"Export a ",[188,1403,1404],{},"useAccessibility"," hook that throws a descriptive error if called outside the provider.",[201,1407,1408],{},"Return the full context object, allowing consumers to destructure only required keys.",[201,1410,1411],{},"Ensure the hook does not recompute values on every call; rely on context referential stability.",[234,1413,1415],{"className":236,"code":1414,"language":238,"meta":239,"style":239},"export const useAccessibility = (): AccessibilityPrefs => {\n const context = useContext(AccessibilityContext);\n if (!context) {\n throw new Error('useAccessibility must be used within an AccessibilityProvider');\n }\n return context;\n};\n\n\u002F\u002F Usage Example\nexport const AnimatedCard = ({ children }: { children: React.ReactNode }) => {\n const { reducedMotion } = useAccessibility();\n const animationClass = reducedMotion ? 'fade-in-static' : 'slide-in-animated';\n \n return \u003Cdiv className={animationClass}>{children}\u003C\u002Fdiv>;\n};\n",[188,1416,1417,1439,1454,1466,1484,1488,1495,1499,1503,1508,1547,1565,1591,1596,1619],{"__ignoreMap":239},[243,1418,1419,1421,1423,1426,1428,1431,1433,1435,1437],{"class":245,"line":246},[243,1420,290],{"class":267},[243,1422,474],{"class":267},[243,1424,1425],{"class":296}," useAccessibility",[243,1427,300],{"class":267},[243,1429,1430],{"class":253}," ()",[243,1432,313],{"class":267},[243,1434,297],{"class":296},[243,1436,656],{"class":267},[243,1438,303],{"class":253},[243,1440,1441,1443,1446,1448,1451],{"class":245,"line":257},[243,1442,474],{"class":267},[243,1444,1445],{"class":316}," context",[243,1447,300],{"class":267},[243,1449,1450],{"class":296}," useContext",[243,1452,1453],{"class":253},"(AccessibilityContext);\n",[243,1455,1456,1458,1460,1463],{"class":245,"line":264},[243,1457,682],{"class":267},[243,1459,354],{"class":253},[243,1461,1462],{"class":267},"!",[243,1464,1465],{"class":253},"context) {\n",[243,1467,1468,1471,1474,1477,1479,1482],{"class":245,"line":282},[243,1469,1470],{"class":267}," throw",[243,1472,1473],{"class":267}," new",[243,1475,1476],{"class":296}," Error",[243,1478,650],{"class":253},[243,1480,1481],{"class":249},"'useAccessibility must be used within an AccessibilityProvider'",[243,1483,441],{"class":253},[243,1485,1486],{"class":245,"line":287},[243,1487,733],{"class":253},[243,1489,1490,1492],{"class":245,"line":306},[243,1491,739],{"class":267},[243,1493,1494],{"class":253}," context;\n",[243,1496,1497],{"class":245,"line":322},[243,1498,403],{"class":253},[243,1500,1501],{"class":245,"line":334},[243,1502,261],{"emptyLinePlaceholder":260},[243,1504,1505],{"class":245,"line":346},[243,1506,1507],{"class":765},"\u002F\u002F Usage Example\n",[243,1509,1510,1512,1514,1517,1519,1521,1523,1525,1527,1529,1531,1533,1536,1538,1541,1543,1545],{"class":245,"line":400},[243,1511,290],{"class":267},[243,1513,474],{"class":267},[243,1515,1516],{"class":296}," AnimatedCard",[243,1518,300],{"class":267},[243,1520,482],{"class":253},[243,1522,485],{"class":309},[243,1524,488],{"class":253},[243,1526,313],{"class":267},[243,1528,493],{"class":253},[243,1530,485],{"class":309},[243,1532,313],{"class":267},[243,1534,1535],{"class":296}," React",[243,1537,721],{"class":253},[243,1539,1540],{"class":296},"ReactNode",[243,1542,503],{"class":253},[243,1544,392],{"class":267},[243,1546,303],{"class":253},[243,1548,1549,1551,1553,1556,1558,1560,1562],{"class":245,"line":406},[243,1550,474],{"class":267},[243,1552,493],{"class":253},[243,1554,1555],{"class":316},"reducedMotion",[243,1557,839],{"class":253},[243,1559,529],{"class":267},[243,1561,1425],{"class":296},[243,1563,1564],{"class":253},"();\n",[243,1566,1567,1569,1572,1574,1577,1580,1583,1586,1589],{"class":245,"line":411},[243,1568,474],{"class":267},[243,1570,1571],{"class":316}," animationClass",[243,1573,300],{"class":267},[243,1575,1576],{"class":253}," reducedMotion ",[243,1578,1579],{"class":267},"?",[243,1581,1582],{"class":249}," 'fade-in-static'",[243,1584,1585],{"class":267}," :",[243,1587,1588],{"class":249}," 'slide-in-animated'",[243,1590,254],{"class":253},[243,1592,1593],{"class":245,"line":444},[243,1594,1595],{"class":253}," \n",[243,1597,1598,1600,1602,1606,1609,1611,1614,1616],{"class":245,"line":449},[243,1599,739],{"class":267},[243,1601,936],{"class":253},[243,1603,1605],{"class":1604},"s9eBZ","div",[243,1607,1608],{"class":296}," className",[243,1610,529],{"class":267},[243,1612,1613],{"class":253},"{animationClass}>{children}\u003C\u002F",[243,1615,1605],{"class":1604},[243,1617,1618],{"class":253},">;\n",[243,1620,1621],{"class":245,"line":464},[243,1622,403],{"class":253},[166,1624,1625,1627,1628,1630,1631,1634],{},[978,1626,980],{}," Render a component tree with isolated state updates. Verify that components consuming only ",[188,1629,1555],{}," do not re-render when ",[188,1632,1633],{},"highContrast"," changes.",[180,1636,1638],{"id":1637},"performance-optimization-memoization","Performance Optimization & Memoization",[166,1640,1641],{},"Context updates trigger re-renders for all subscribed components. In large-scale applications, implement granular subscriptions and memoization to isolate render cascades.",[193,1643,196],{"id":1644},"implementation-steps-3",[198,1646,1647,1660,1669,1679],{},[201,1648,1649,1652,1653,373,1656,1659],{},[978,1650,1651],{},"Context Splitting:"," Divide monolithic context into focused providers (e.g., ",[188,1654,1655],{},"MotionContext",[188,1657,1658],{},"ThemeContext",") when preference domains operate independently.",[201,1661,1662,1665,1666,1668],{},[978,1663,1664],{},"Selective Subscriptions:"," Use ",[188,1667,1014],{}," for external state managers (Zustand, Redux) if context becomes a bottleneck.",[201,1670,1671,1674,1675,1678],{},[978,1672,1673],{},"Memoize Derivatives:"," Wrap computed UI states in ",[188,1676,1677],{},"useMemo"," at the consumer level.",[201,1680,1681,1684,1685,1688],{},[978,1682,1683],{},"Component Boundaries:"," Apply ",[188,1686,1687],{},"React.memo"," to leaf components that consume preferences, ensuring they only update when their specific slice changes.",[234,1690,1692],{"className":236,"code":1691,"language":238,"meta":239,"style":239},"\u002F\u002F Optimized consumer with React.memo\nexport const OptimizedCard = React.memo(({ children }: { children: React.ReactNode }) => {\n const { reducedMotion } = useAccessibility();\n const animationClass = useMemo(\n () => reducedMotion ? 'fade-in-static' : 'slide-in-animated',\n [reducedMotion]\n );\n \n return \u003Cdiv className={animationClass}>{children}\u003C\u002Fdiv>;\n});\n",[188,1693,1694,1699,1743,1759,1771,1789,1794,1798,1802,1820],{"__ignoreMap":239},[243,1695,1696],{"class":245,"line":246},[243,1697,1698],{"class":765},"\u002F\u002F Optimized consumer with React.memo\n",[243,1700,1701,1703,1705,1708,1710,1713,1716,1719,1721,1723,1725,1727,1729,1731,1733,1735,1737,1739,1741],{"class":245,"line":257},[243,1702,290],{"class":267},[243,1704,474],{"class":267},[243,1706,1707],{"class":316}," OptimizedCard",[243,1709,300],{"class":267},[243,1711,1712],{"class":253}," React.",[243,1714,1715],{"class":296},"memo",[243,1717,1718],{"class":253},"(({ ",[243,1720,485],{"class":309},[243,1722,488],{"class":253},[243,1724,313],{"class":267},[243,1726,493],{"class":253},[243,1728,485],{"class":309},[243,1730,313],{"class":267},[243,1732,1535],{"class":296},[243,1734,721],{"class":253},[243,1736,1540],{"class":296},[243,1738,503],{"class":253},[243,1740,392],{"class":267},[243,1742,303],{"class":253},[243,1744,1745,1747,1749,1751,1753,1755,1757],{"class":245,"line":264},[243,1746,474],{"class":267},[243,1748,493],{"class":253},[243,1750,1555],{"class":316},[243,1752,839],{"class":253},[243,1754,529],{"class":267},[243,1756,1425],{"class":296},[243,1758,1564],{"class":253},[243,1760,1761,1763,1765,1767,1769],{"class":245,"line":282},[243,1762,474],{"class":267},[243,1764,1571],{"class":316},[243,1766,300],{"class":267},[243,1768,883],{"class":296},[243,1770,1229],{"class":253},[243,1772,1773,1775,1777,1779,1781,1783,1785,1787],{"class":245,"line":287},[243,1774,896],{"class":253},[243,1776,392],{"class":267},[243,1778,1576],{"class":253},[243,1780,1579],{"class":267},[243,1782,1582],{"class":249},[243,1784,1585],{"class":267},[243,1786,1588],{"class":249},[243,1788,565],{"class":253},[243,1790,1791],{"class":245,"line":306},[243,1792,1793],{"class":253}," [reducedMotion]\n",[243,1795,1796],{"class":245,"line":322},[243,1797,917],{"class":253},[243,1799,1800],{"class":245,"line":334},[243,1801,1595],{"class":253},[243,1803,1804,1806,1808,1810,1812,1814,1816,1818],{"class":245,"line":346},[243,1805,739],{"class":267},[243,1807,936],{"class":253},[243,1809,1605],{"class":1604},[243,1811,1608],{"class":296},[243,1813,529],{"class":267},[243,1815,1613],{"class":253},[243,1817,1605],{"class":1604},[243,1819,1618],{"class":253},[243,1821,1822],{"class":245,"line":400},[243,1823,1824],{"class":253},"});\n",[166,1826,1827,1829],{},[978,1828,980],{}," Profile component renders using React DevTools Profiler. Record a baseline, toggle a preference, and verify that only subscribed components register render commits.",[180,1831,1833],{"id":1832},"integration-with-live-regions-announcements","Integration with Live Regions & Announcements",[166,1835,1836],{},"Map global preference state to ARIA live regions to control verbosity, timing, and announcement behavior. This ensures screen reader users receive appropriate feedback without interrupting critical interactions.",[193,1838,196],{"id":1839},"implementation-steps-4",[198,1841,1842,1853,1871],{},[201,1843,1844,1845,1848,1849,1852],{},"Create an ",[188,1846,1847],{},"AriaLiveRegion"," component that consumes ",[188,1850,1851],{},"screenReaderMode"," and verbosity preferences.",[201,1854,1855,1856,354,1859,1862,1863,1866,1867,1870],{},"Dynamically adjust ",[188,1857,1858],{},"aria-live",[188,1860,1861],{},"polite"," vs ",[188,1864,1865],{},"assertive",") and ",[188,1868,1869],{},"aria-atomic"," based on context state.",[201,1872,1873],{},"Implement a throttled announcement queue to prevent speech synthesis overload during rapid state changes.",[234,1875,1877],{"className":236,"code":1876,"language":238,"meta":239,"style":239},"import { useState, useEffect, useRef } from 'react';\nimport { useAccessibility } from '.\u002Fhooks\u002FuseAccessibility';\n\nexport const LiveAnnouncer = ({ message }: { message: string }) => {\n const { screenReaderMode } = useAccessibility();\n const [announcement, setAnnouncement] = useState('');\n const timerRef = useRef\u003CNodeJS.Timeout | null>(null);\n\n useEffect(() => {\n if (!screenReaderMode) return;\n \n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setAnnouncement(message), 300);\n \n return () => { if (timerRef.current) clearTimeout(timerRef.current); };\n }, [message, screenReaderMode]);\n\n return (\n \u003Cdiv \n aria-live=\"polite\" \n aria-atomic=\"true\" \n className=\"sr-only\"\n role=\"status\"\n >\n {announcement}\n \u003C\u002Fdiv>\n );\n};\n",[188,1878,1879,1892,1906,1910,1944,1960,1987,2021,2025,2035,2051,2055,2068,2093,2097,2117,2122,2126,2132,2140,2152,2164,2173,2183,2188,2193,2201,2205],{"__ignoreMap":239},[243,1880,1881,1883,1886,1888,1890],{"class":245,"line":246},[243,1882,268],{"class":267},[243,1884,1885],{"class":253}," { useState, useEffect, useRef } ",[243,1887,274],{"class":267},[243,1889,277],{"class":249},[243,1891,254],{"class":253},[243,1893,1894,1896,1899,1901,1904],{"class":245,"line":257},[243,1895,268],{"class":267},[243,1897,1898],{"class":253}," { useAccessibility } ",[243,1900,274],{"class":267},[243,1902,1903],{"class":249}," '.\u002Fhooks\u002FuseAccessibility'",[243,1905,254],{"class":253},[243,1907,1908],{"class":245,"line":264},[243,1909,261],{"emptyLinePlaceholder":260},[243,1911,1912,1914,1916,1919,1921,1923,1926,1928,1930,1932,1934,1936,1938,1940,1942],{"class":245,"line":282},[243,1913,290],{"class":267},[243,1915,474],{"class":267},[243,1917,1918],{"class":296}," LiveAnnouncer",[243,1920,300],{"class":267},[243,1922,482],{"class":253},[243,1924,1925],{"class":309},"message",[243,1927,488],{"class":253},[243,1929,313],{"class":267},[243,1931,493],{"class":253},[243,1933,1925],{"class":309},[243,1935,313],{"class":267},[243,1937,1077],{"class":316},[243,1939,503],{"class":253},[243,1941,392],{"class":267},[243,1943,303],{"class":253},[243,1945,1946,1948,1950,1952,1954,1956,1958],{"class":245,"line":287},[243,1947,474],{"class":267},[243,1949,493],{"class":253},[243,1951,1851],{"class":316},[243,1953,839],{"class":253},[243,1955,529],{"class":267},[243,1957,1425],{"class":296},[243,1959,1564],{"class":253},[243,1961,1962,1964,1966,1969,1971,1974,1976,1978,1980,1982,1985],{"class":245,"line":306},[243,1963,474],{"class":267},[243,1965,515],{"class":253},[243,1967,1968],{"class":316},"announcement",[243,1970,373],{"class":253},[243,1972,1973],{"class":316},"setAnnouncement",[243,1975,526],{"class":253},[243,1977,529],{"class":267},[243,1979,532],{"class":296},[243,1981,650],{"class":253},[243,1983,1984],{"class":249},"''",[243,1986,441],{"class":253},[243,1988,1989,1991,1994,1996,1999,2001,2004,2006,2009,2011,2014,2016,2019],{"class":245,"line":322},[243,1990,474],{"class":267},[243,1992,1993],{"class":316}," timerRef",[243,1995,300],{"class":267},[243,1997,1998],{"class":296}," useRef",[243,2000,368],{"class":253},[243,2002,2003],{"class":296},"NodeJS",[243,2005,721],{"class":253},[243,2007,2008],{"class":296},"Timeout",[243,2010,429],{"class":267},[243,2012,2013],{"class":316}," null",[243,2015,435],{"class":253},[243,2017,2018],{"class":316},"null",[243,2020,441],{"class":253},[243,2022,2023],{"class":245,"line":334},[243,2024,261],{"emptyLinePlaceholder":260},[243,2026,2027,2029,2031,2033],{"class":245,"line":346},[243,2028,772],{"class":296},[243,2030,775],{"class":253},[243,2032,392],{"class":267},[243,2034,303],{"class":253},[243,2036,2037,2039,2041,2043,2046,2049],{"class":245,"line":400},[243,2038,682],{"class":267},[243,2040,354],{"class":253},[243,2042,1462],{"class":267},[243,2044,2045],{"class":253},"screenReaderMode) ",[243,2047,2048],{"class":267},"return",[243,2050,254],{"class":253},[243,2052,2053],{"class":245,"line":406},[243,2054,1595],{"class":253},[243,2056,2057,2059,2062,2065],{"class":245,"line":411},[243,2058,682],{"class":267},[243,2060,2061],{"class":253}," (timerRef.current) ",[243,2063,2064],{"class":296},"clearTimeout",[243,2066,2067],{"class":253},"(timerRef.current);\n",[243,2069,2070,2073,2075,2078,2080,2082,2085,2088,2091],{"class":245,"line":444},[243,2071,2072],{"class":253}," timerRef.current ",[243,2074,529],{"class":267},[243,2076,2077],{"class":296}," setTimeout",[243,2079,775],{"class":253},[243,2081,392],{"class":267},[243,2083,2084],{"class":296}," setAnnouncement",[243,2086,2087],{"class":253},"(message), ",[243,2089,2090],{"class":316},"300",[243,2092,441],{"class":253},[243,2094,2095],{"class":245,"line":449},[243,2096,1595],{"class":253},[243,2098,2099,2101,2103,2105,2107,2110,2112,2114],{"class":245,"line":464},[243,2100,739],{"class":267},[243,2102,896],{"class":253},[243,2104,392],{"class":267},[243,2106,493],{"class":253},[243,2108,2109],{"class":267},"if",[243,2111,2061],{"class":253},[243,2113,2064],{"class":296},[243,2115,2116],{"class":253},"(timerRef.current); };\n",[243,2118,2119],{"class":245,"line":469},[243,2120,2121],{"class":253}," }, [message, screenReaderMode]);\n",[243,2123,2124],{"class":245,"line":510},[243,2125,261],{"emptyLinePlaceholder":260},[243,2127,2128,2130],{"class":245,"line":556},[243,2129,739],{"class":267},[243,2131,930],{"class":253},[243,2133,2134,2136,2138],{"class":245,"line":568},[243,2135,936],{"class":253},[243,2137,1605],{"class":1604},[243,2139,1595],{"class":253},[243,2141,2142,2145,2147,2150],{"class":245,"line":578},[243,2143,2144],{"class":296}," aria-live",[243,2146,529],{"class":267},[243,2148,2149],{"class":249},"\"polite\"",[243,2151,1595],{"class":253},[243,2153,2154,2157,2159,2162],{"class":245,"line":588},[243,2155,2156],{"class":296}," aria-atomic",[243,2158,529],{"class":267},[243,2160,2161],{"class":249},"\"true\"",[243,2163,1595],{"class":253},[243,2165,2166,2168,2170],{"class":245,"line":594},[243,2167,1608],{"class":296},[243,2169,529],{"class":267},[243,2171,2172],{"class":249},"\"sr-only\"\n",[243,2174,2175,2178,2180],{"class":245,"line":599},[243,2176,2177],{"class":296}," role",[243,2179,529],{"class":267},[243,2181,2182],{"class":249},"\"status\"\n",[243,2184,2185],{"class":245,"line":644},[243,2186,2187],{"class":253}," >\n",[243,2189,2190],{"class":245,"line":661},[243,2191,2192],{"class":253}," {announcement}\n",[243,2194,2195,2197,2199],{"class":245,"line":679},[243,2196,959],{"class":253},[243,2198,1605],{"class":1604},[243,2200,964],{"class":253},[243,2202,2203],{"class":245,"line":702},[243,2204,917],{"class":253},[243,2206,2207],{"class":245,"line":730},[243,2208,403],{"class":253},[166,2210,2211,2213],{},[978,2212,980],{}," Validate with VoiceOver (macOS\u002FiOS) and NVDA (Windows). Confirm announcements respect verbosity settings, queue properly, and do not interrupt form input or navigation.",[180,2215,2217],{"id":2216},"debugging-workflows-ci-configuration","Debugging Workflows & CI Configuration",[193,2219,2221],{"id":2220},"local-debugging","Local Debugging",[198,2223,2224,2233,2261],{},[201,2225,2226,2229,2230,2232],{},[978,2227,2228],{},"React DevTools Profiler:"," Enable \"Record why each component rendered\" to trace context-driven updates. Filter by ",[188,2231,206],{}," to identify unnecessary subscriptions.",[201,2234,2235,2238,2239,2242,2243,2246,2247,68,2250,2252,2253,2256,2257,2260],{},[978,2236,2237],{},"Hydration Mismatch Detection:"," Run ",[188,2240,2241],{},"next dev"," and monitor the console for ",[188,2244,2245],{},"Text content did not match"," warnings. Ensure all ",[188,2248,2249],{},"window",[188,2251,217],{}," reads are deferred to ",[188,2254,2255],{},"useEffect"," or wrapped in ",[188,2258,2259],{},"typeof window !== 'undefined'"," guards.",[201,2262,2263,1665,2266,1011,2269,2272],{},[978,2264,2265],{},"Assistive Technology Simulation:",[188,2267,2268],{},"axe DevTools",[188,2270,2271],{},"Lighthouse"," accessibility audits alongside manual screen reader testing to verify ARIA attribute mapping.",[193,2274,2276],{"id":2275},"citesting-pipeline","CI\u002FTesting Pipeline",[234,2278,2282],{"className":2279,"code":2280,"language":2281,"meta":239,"style":239},"language-yaml shiki shiki-themes github-light github-dark","# .github\u002Fworkflows\u002Fa11y.yml\nname: Accessibility & Context Validation\non: [push, pull_request]\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - uses: actions\u002Fcheckout@v4\n - run: npm ci\n - name: Run Unit Tests\n run: npm run test -- --coverage --testPathPattern=\"accessibility\"\n - name: Run E2E Accessibility Checks\n run: npx playwright test --grep \"a11y\"\n - name: Lighthouse CI\n run: npx lhci autorun\n env:\n LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_TOKEN }}\n","yaml",[188,2283,2284,2289,2300,2319,2323,2331,2338,2348,2355,2368,2380,2391,2401,2412,2421,2432,2441,2448],{"__ignoreMap":239},[243,2285,2286],{"class":245,"line":246},[243,2287,2288],{"class":765},"# .github\u002Fworkflows\u002Fa11y.yml\n",[243,2290,2291,2294,2297],{"class":245,"line":257},[243,2292,2293],{"class":1604},"name",[243,2295,2296],{"class":253},": ",[243,2298,2299],{"class":249},"Accessibility & Context Validation\n",[243,2301,2302,2305,2308,2311,2313,2316],{"class":245,"line":264},[243,2303,2304],{"class":316},"on",[243,2306,2307],{"class":253},": [",[243,2309,2310],{"class":249},"push",[243,2312,373],{"class":253},[243,2314,2315],{"class":249},"pull_request",[243,2317,2318],{"class":253},"]\n",[243,2320,2321],{"class":245,"line":282},[243,2322,261],{"emptyLinePlaceholder":260},[243,2324,2325,2328],{"class":245,"line":287},[243,2326,2327],{"class":1604},"jobs",[243,2329,2330],{"class":253},":\n",[243,2332,2333,2336],{"class":245,"line":306},[243,2334,2335],{"class":1604}," test",[243,2337,2330],{"class":253},[243,2339,2340,2343,2345],{"class":245,"line":322},[243,2341,2342],{"class":1604}," runs-on",[243,2344,2296],{"class":253},[243,2346,2347],{"class":249},"ubuntu-latest\n",[243,2349,2350,2353],{"class":245,"line":334},[243,2351,2352],{"class":1604}," steps",[243,2354,2330],{"class":253},[243,2356,2357,2360,2363,2365],{"class":245,"line":346},[243,2358,2359],{"class":253}," - ",[243,2361,2362],{"class":1604},"uses",[243,2364,2296],{"class":253},[243,2366,2367],{"class":249},"actions\u002Fcheckout@v4\n",[243,2369,2370,2372,2375,2377],{"class":245,"line":400},[243,2371,2359],{"class":253},[243,2373,2374],{"class":1604},"run",[243,2376,2296],{"class":253},[243,2378,2379],{"class":249},"npm ci\n",[243,2381,2382,2384,2386,2388],{"class":245,"line":406},[243,2383,2359],{"class":253},[243,2385,2293],{"class":1604},[243,2387,2296],{"class":253},[243,2389,2390],{"class":249},"Run Unit Tests\n",[243,2392,2393,2396,2398],{"class":245,"line":411},[243,2394,2395],{"class":1604}," run",[243,2397,2296],{"class":253},[243,2399,2400],{"class":249},"npm run test -- --coverage --testPathPattern=\"accessibility\"\n",[243,2402,2403,2405,2407,2409],{"class":245,"line":444},[243,2404,2359],{"class":253},[243,2406,2293],{"class":1604},[243,2408,2296],{"class":253},[243,2410,2411],{"class":249},"Run E2E Accessibility Checks\n",[243,2413,2414,2416,2418],{"class":245,"line":449},[243,2415,2395],{"class":1604},[243,2417,2296],{"class":253},[243,2419,2420],{"class":249},"npx playwright test --grep \"a11y\"\n",[243,2422,2423,2425,2427,2429],{"class":245,"line":464},[243,2424,2359],{"class":253},[243,2426,2293],{"class":1604},[243,2428,2296],{"class":253},[243,2430,2431],{"class":249},"Lighthouse CI\n",[243,2433,2434,2436,2438],{"class":245,"line":469},[243,2435,2395],{"class":1604},[243,2437,2296],{"class":253},[243,2439,2440],{"class":249},"npx lhci autorun\n",[243,2442,2443,2446],{"class":245,"line":510},[243,2444,2445],{"class":1604}," env",[243,2447,2330],{"class":253},[243,2449,2450,2453,2455],{"class":245,"line":556},[243,2451,2452],{"class":1604}," LHCI_GITHUB_APP_TOKEN",[243,2454,2296],{"class":253},[243,2456,2457],{"class":249},"${{ secrets.LHCI_TOKEN }}\n",[166,2459,2460,2461,1011,2463,2465,2466,2468],{},"Configure Playwright to inject mock ",[188,2462,1116],{},[188,2464,217],{}," states before hydration. Assert that context values propagate correctly and that ",[188,2467,1858],{}," regions update without DOM thrashing.",[180,2470,2472],{"id":2471},"common-pitfalls","Common Pitfalls",[2474,2475,2476,2482,2494,2500,2509],"ul",{},[201,2477,2478,2481],{},[978,2479,2480],{},"Full-Tree Re-renders:"," Updating the entire context object instead of granular slices breaks referential equality and forces all consumers to re-render.",[201,2483,2484,2487,2488,2490,2491,2493],{},[978,2485,2486],{},"SSR Hydration Mismatches:"," Reading ",[188,2489,1010],{}," or ",[188,2492,217],{}," during server rendering causes hydration failures and layout shifts.",[201,2495,2496,2499],{},[978,2497,2498],{},"Preference Override Traps:"," Overriding system-level preferences without providing a clear UI toggle to revert changes violates WCAG 2.1 SC 1.4.8 and user agency.",[201,2501,2502,2505,2506,2508],{},[978,2503,2504],{},"Inefficient Initialization:"," Using ",[188,2507,2255],{}," for preference initialization instead of lazy state initialization delays state hydration and causes visual flicker.",[201,2510,2511,2514],{},[978,2512,2513],{},"Unmemoized Derivatives:"," Failing to memoize computed preference values or passing inline functions to context triggers unnecessary component updates.",[180,2516,2518],{"id":2517},"faq","FAQ",[166,2520,2521,2524,2525,373,2527,2530,2531,2533,2534,2536],{},[978,2522,2523],{},"How do I prevent React Context from causing performance bottlenecks when accessibility preferences change?","\nSplit the monolithic context into multiple focused providers (e.g., ",[188,2526,1655],{},[188,2528,2529],{},"ContrastContext",") and utilize ",[188,2532,1014],{}," for external state subscriptions. Always memoize context values and wrap consumer components with ",[188,2535,1687],{}," to isolate re-renders to only the components that depend on the changed preference.",[166,2538,2539,2542,2543,2545,2546,2549],{},[978,2540,2541],{},"Should I prioritize system-level media queries or stored user preferences?","\nSystem-level media queries should serve as the initial baseline, but explicit user overrides stored in ",[188,2544,217],{}," or a database must take precedence. Implement a fallback chain: ",[188,2547,2548],{},"user override > system preference > application default",", and provide a clear UI control to reset to system defaults.",[166,2551,2552,2555,2556,2558,2559,2561,2562,2564],{},[978,2553,2554],{},"How does this pattern integrate with Next.js App Router and Server Components?","\nSince React Context requires client-side execution, wrap your client component provider in a ",[188,2557,250],{}," directive and place it at the root of your ",[188,2560,227],{},". Pass server-rendered content as ",[188,2563,485],{}," to the provider to avoid serializing client state across the server-client boundary, ensuring seamless hydration.",[2566,2567,2568],"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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}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 .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":239,"searchDepth":257,"depth":257,"links":2570},[2571,2574,2577,2580,2583,2586,2590,2591],{"id":182,"depth":257,"text":183,"children":2572},[2573],{"id":195,"depth":264,"text":196},{"id":988,"depth":257,"text":989,"children":2575},[2576],{"id":998,"depth":264,"text":196},{"id":1385,"depth":257,"text":1386,"children":2578},[2579],{"id":1396,"depth":264,"text":196},{"id":1637,"depth":257,"text":1638,"children":2581},[2582],{"id":1644,"depth":264,"text":196},{"id":1832,"depth":257,"text":1833,"children":2584},[2585],{"id":1839,"depth":264,"text":196},{"id":2216,"depth":257,"text":2217,"children":2587},[2588,2589],{"id":2220,"depth":264,"text":2221},{"id":2275,"depth":264,"text":2276},{"id":2471,"depth":257,"text":2472},{"id":2517,"depth":257,"text":2518},null,"Use React Context to centralize accessibility preferences like motion and contrast while keeping state predictable across large apps.","md",{},false,{"title":97,"description":2593},"-sozPR8q8MH2sHFXwZEc3Y3g7FH4QPX7bTgodI8i2LE",[2600,2630,2631],{"title":5,"path":6,"stem":7,"children":2601},[2602,2603,2606,2609,2615,2621,2627],{"title":10,"path":6,"stem":11},{"title":13,"path":14,"stem":15,"children":2604},[2605],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21,"children":2607},[2608],{"title":19,"path":20,"stem":21},{"title":25,"path":26,"stem":27,"children":2610},[2611,2612],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":2613},[2614],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":2616},[2617,2618],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45,"children":2619},[2620],{"title":43,"path":44,"stem":45},{"title":49,"path":50,"stem":51,"children":2622},[2623,2624],{"title":49,"path":50,"stem":51},{"title":55,"path":56,"stem":57,"children":2625},[2626],{"title":55,"path":56,"stem":57},{"title":61,"path":62,"stem":63,"children":2628},[2629],{"title":61,"path":62,"stem":63},{"title":67,"path":68,"stem":69},{"title":71,"path":72,"stem":73,"children":2632},[2633,2634,2640,2646,2649,2658,2667],{"title":76,"path":72,"stem":77},{"title":79,"path":80,"stem":81,"children":2635},[2636,2637],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87,"children":2638},[2639],{"title":85,"path":86,"stem":87},{"title":91,"path":92,"stem":93,"children":2641},[2642,2643],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99,"children":2644},[2645],{"title":97,"path":98,"stem":99},{"title":103,"path":104,"stem":105,"children":2647},[2648],{"title":103,"path":104,"stem":105},{"title":109,"path":110,"stem":111,"children":2650},[2651,2652,2655],{"title":109,"path":110,"stem":111},{"title":115,"path":116,"stem":117,"children":2653},[2654],{"title":115,"path":116,"stem":117},{"title":121,"path":122,"stem":123,"children":2656},[2657],{"title":121,"path":122,"stem":123},{"title":127,"path":128,"stem":129,"children":2659},[2660,2661,2664],{"title":127,"path":128,"stem":129},{"title":133,"path":134,"stem":135,"children":2662},[2663],{"title":133,"path":134,"stem":135},{"title":139,"path":140,"stem":141,"children":2665},[2666],{"title":139,"path":140,"stem":141},{"title":145,"path":146,"stem":147,"children":2668},[2669,2670],{"title":145,"path":146,"stem":147},{"title":151,"path":152,"stem":153,"children":2671},[2672],{"title":151,"path":152,"stem":153},1778094796361]