From dh
Reviews web frontend code for accessibility, XSS prevention, performance, CSS patterns, and form labeling. Framework-agnostic for HTML, CSS, JSX files.
npx claudepluginhub jamie-bitflight/claude_skills --plugin development-harnessThis skill uses the workspace's default tool permissions.
Stack-specific rules loaded by `dh:code-reviewer` when `*.html`, `*.css`, or `*.jsx` (browser-targeted) files are detected.
Audits web UI code for accessibility, performance, responsive design, and best practices using A11Y/PERF/RD guidelines. Outputs file:line — [RULE_ID] findings.
Audits and fixes HTML accessibility issues including ARIA labels, keyboard navigation, focus management, color contrast, and form errors. Use for interactive controls, forms, dialogs, or WCAG compliance reviews.
Audits and fixes HTML accessibility issues including ARIA labels, keyboard navigation, focus management, color contrast, and form errors. Use for interactive controls, forms, dialogs, or WCAG compliance reviews.
Share bugs, ideas, or general feedback.
Stack-specific rules loaded by dh:code-reviewer when *.html, *.css, or *.jsx (browser-targeted) files are detected.
aria-label, or aria-labelledbyaria-label or a visually-hidden text spanfor/id pairing or aria-labelledby — proximity alone is not sufficientalt text; decorative images use alt=""element.innerHTML = userValue is a blocking finding — use textContent for plain textdangerouslySetInnerHTML (React) or equivalent without sanitization is a blocking findingeval(), Function(), or setTimeout(string) are a blocking findinghref, src, or action attributes must be validated against an allowlist of schemes (block javascript:, data:)offsetWidth, getBoundingClientRect) inside a loop that also writes styles — is a blocking findingwidth and height attributes to prevent layout shift (CLS)loading="lazy" — eager loading of off-screen images delays critical rendering<head> without defer or async are a blocking findingrender, Vue template expressions) without memoization are a blocking finding!important without an explanatory comment is a blocking finding--color-primary) — hardcoded hex values and px values are non-blocking but flaggedz-index values without a documented z-index scale are a blocking finding — use named tokens (z-index: var(--z-modal))position: fixed or position: sticky without overflow and scroll container awareness is flagged* selectors in component styles that may bleed into child components are a blocking finding<input>, <select>, and <textarea> must have an associated <label> (either wrapping or via for/id)autocomplete attributes must be set on inputs that collect personal data (name, email, address, payment) — required for WCAG 1.3.5aria-describedby — color alone is not sufficient to communicate errorsdocument.addEventListener without a corresponding removeEventListener in the cleanup lifecycle is a blocking findingAbortController is preferred for fetch-and-cleanup patterns — pass the signal and abort on cleanup<!-- WRONG: no label, no accessible name -->
<input type="text" placeholder="Search..." />
<!-- RIGHT: associated label -->
<label for="search">Search</label>
<input type="text" id="search" autocomplete="off" />
<!-- WRONG: XSS vector -->
<div id="output"></div>
<script>
document.getElementById("output").innerHTML = userInput;
</script>
<!-- RIGHT: safe text insertion -->
<script>
document.getElementById("output").textContent = userInput;
</script>
/* WRONG: magic z-index */
.modal { z-index: 9999; }
/* RIGHT: design token */
.modal { z-index: var(--z-modal); }
/* WRONG: unexplained !important */
.button { color: red !important; }
/* RIGHT: explained override */
/* Overrides third-party widget styles that cannot be targeted more specifically */
.widget-container .button { color: red !important; }