react-accessibility-performance
DEPRECATED for new standalone React/TypeScript work; use react-agent-skills / react-accessibility + react-performance instead. Select only to maintain existing work during the deprecation window. Use
SKILL.mdskills/react-accessibility-performance/SKILL.md
GitHubReact Accessibility and Performance
Purpose
Treat accessibility and rendering performance as explicit behavioral constraints instead of cleanup tasks.
Activate when
- adding interactive controls or custom widgets;
- fixing keyboard, focus, or screen-reader behavior;
- investigating unnecessary renders;
- introducing memoization or virtualization.
Repository inspection
Inspect semantic HTML, focus utilities, design-system primitives, profiler evidence, list sizes, data identity, and existing performance budgets.
Decision rules
- Prefer semantic native elements.
- Keyboard and focus behavior are part of the component contract.
- Do not memoize by reflex; identify a real identity or workload problem.
- Fix state ownership and unstable identities before broad memoization.
- Justify virtualization using workload characteristics.
- Preserve accessible names, labels, visible focus, and announced state.
Implementation procedure
- Identify interaction and rendering workload.
- Verify semantics before custom behavior.
- Define focus transitions.
- Measure render hotspots.
- Fix ownership and identity issues before memoization.
- Add focused accessibility and performance regression checks.
Anti-patterns / failure modes
- clickable divs used instead of buttons;
- focus traps without recovery;
- arbitrary memoization;
- virtualization that breaks interaction semantics;
- performance claims without evidence.
Reference example
Type-checked with tsc --strict (plus noUncheckedIndexedAccess and exactOptionalPropertyTypes).
import { useDeferredValue, useId, useState } from "react";
// Labeled input, announced result count, and keyboard-reachable controls.
// useDeferredValue keeps typing responsive for a list measured to be slow;
// add it after profiling, not by default.
export function ProductFilter({ products }: { products: readonly string[] }) {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query);
const inputId = useId();
const matches = products.filter((name) => name.toLowerCase().includes(deferredQuery.toLowerCase()));
return (
<div>
<label htmlFor={inputId}>Filter products</label>
<input id={inputId} value={query} onChange={(event) => setQuery(event.target.value)} />
<p role="status" aria-live="polite">
{matches.length} {matches.length === 1 ? "result" : "results"}
</p>
<ul>
{matches.map((name) => (
<li key={name}>
<button type="button">{name}</button>
</li>
))}
</ul>
</div>
);
}
Agent review checklist
- Are native semantics preferred?
- Are keyboard and focus transitions explicit?
- What evidence justifies memoization or virtualization?
- Are accessibility regressions tested at the owning boundary?
Verification
Use keyboard tests, accessible-role assertions, browser/integration checks when needed, and profiler or benchmark evidence for performance claims.
Source foundation
- React Learn: https://react.dev/learn
- WAI-ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
- React memo: https://react.dev/reference/react/memo