WCAG 2.2 SC 4.1.2 (Name, Role, Value) and SC 2.1.1 (Keyboard) require that all interactive controls be operable without a mouse and expose their purpose to assistive technology. A star rating built from styled <div> elements with only onClick handlers is invisible to screen readers and completely unreachable by keyboard — failing Section 508 2018 Refresh 502.3.1 as well. Users who navigate by keyboard or rely on VoiceOver/NVDA cannot leave a rating at all, which is a measurable drop in review volume and a legal exposure under ADA and EAA for US and EU stores.
Medium because the inaccessible input excludes keyboard and screen-reader users from submitting reviews without enabling a security or data-integrity attack.
Replace click-only star elements with native radio inputs inside a role="radiogroup" container in components/AccessibleStarInput.tsx. Native radios give keyboard navigation (arrow keys), visible focus, and screen-reader announcements for free.
// components/AccessibleStarInput.tsx
export function StarInput({ value, onChange }: { value: number; onChange: (v: number) => void }) {
return (
<div role="radiogroup" aria-label="Star rating">
{[1, 2, 3, 4, 5].map(star => (
<label key={star} className="star-label">
<input
type="radio"
name="rating"
value={star}
checked={value === star}
onChange={() => onChange(star)}
aria-label={`${star} star${star > 1 ? 's' : ''}`}
className="sr-only"
/>
<span aria-hidden="true">★</span>
</label>
))}
</div>
)
}
Add CSS focus-visible styles on .star-label:has(input:focus-visible) so the focus ring is visible without cluttering mouse interactions.
ID: ecommerce-reviews.review-collection.star-input-accessible
Severity: medium
What to look for: Before evaluating, quote the star rating component's JSX or HTML markup. Count the number of accessibility features present: (1) aria-label or aria-labelledby, (2) role="radiogroup" or radio inputs, (3) keyboard navigation (onKeyDown handler or native radio behavior), (4) visible focus indicator (outline, ring, or border style on focus).
Pass criteria: The star rating input has at least 3 of 4 accessibility features: ARIA labels (aria-label, role="radio" or role="radiogroup"), keyboard navigation via arrow keys or Tab+Enter, and a visible focus indicator with CSS focus styles. Report even on pass: state which 3-4 of 4 features are present.
Fail criteria: The star rating input has fewer than 3 of 4 accessibility features, is click-only with no keyboard navigation, or lacks ARIA labels/roles making it invisible to screen readers.
Skip (N/A) when: No review submission form exists (submission-form-exists already failed or skipped).
Detail on fail: "Star rating has 1 of 4 accessibility features (aria-label only). Missing: role=radiogroup, keyboard handler, focus indicator." or "Stars are styled divs with onClick only — 0 of 4 accessibility features."
Remediation: Build an accessible star input in components/AccessibleStarInput.tsx using radio buttons or ARIA roles:
// components/AccessibleStarInput.tsx
export function StarInput({ value, onChange }) {
return (
<div role="radiogroup" aria-label="Rating">
{[1, 2, 3, 4, 5].map(star => (
<label key={star}>
<input
type="radio"
name="rating"
value={star}
checked={value === star}
onChange={(e) => onChange(parseInt(e.target.value))}
aria-label={`${star} stars`}
/>
<span>★</span>
</label>
))}
</div>
)
}