AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Form Accessibility

skill-bbeierle12-skill-mcp-claude-form-accessibility · by Bbeierle12

WCAG 2.2 AA compliance for forms, ARIA patterns, focus management, keyboard navigation, and screen reader support. Use when implementing accessible forms in any framework. The compliance foundation that ensures forms work for everyone.

— No reviews yet
0 installs
41 views
0.0% view→install

Install

$ agentstack add skill-bbeierle12-skill-mcp-claude-form-accessibility

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ✓ Network access No
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ● Environment & secrets Used
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-bbeierle12-skill-mcp-claude-form-accessibility)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Form Accessibility? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Form Accessibility

WCAG 2.2 AA compliance patterns for forms. Ensures forms work for keyboard users, screen reader users, and users with cognitive or motor disabilities.

Quick Start

// Accessible form field pattern

  {/* 1. Visible label (never placeholder-only) */}
  
    Email
    *
  
  
  {/* 2. Hint text (separate from label) */}
  
    We'll send your confirmation here
  
  
  {/* 3. Input with full ARIA binding */}
  
  
  {/* 4. Error message (announced by screen readers) */}
  {hasError && (
    
      Please enter a valid email address
    
  )}

WCAG 2.2 Form Requirements

Critical Criteria

| Criterion | Level | Requirement | Implementation | |-----------|-------|-------------|----------------| | 1.3.1 Info & Relationships | A | Structure conveyed programmatically | `, , aria-describedby | | 1.3.5 Identify Input Purpose | AA | Input purpose identifiable | autocomplete attributes | | 2.1.1 Keyboard | A | All functionality via keyboard | Tab order, focus management | | 2.4.6 Headings & Labels | AA | Labels describe purpose | Descriptive, visible labels | | 2.4.11 Focus Not Obscured | AA | Focus not hidden by other content | Scroll behavior, sticky elements | | 2.5.8 Target Size | AA | 24×24px minimum touch target | Button/input sizing | | 3.3.1 Error Identification | A | Errors identified and described | aria-invalid`, error messages | | 3.3.2 Labels or Instructions | A | Labels provided | Visible labels, not just placeholders | | 3.3.3 Error Suggestion | AA | Suggestions for fixing errors | Actionable error messages | | 3.3.7 Redundant Entry | A | Don't re-ask for info already provided | Form state management | | 3.3.8 Accessible Authentication | AA | No cognitive function tests | No CAPTCHAs requiring text recognition |

New in WCAG 2.2 (October 2023)

2.4.11 Focus Not Obscured (AA)

/* Ensure focus is never hidden by sticky headers */
.sticky-header {
  position: sticky;
  top: 0;
}

input:focus {
  /* Browser should scroll input into view above sticky elements */
  scroll-margin-top: 80px; /* Height of sticky header */
}

2.5.8 Target Size (AA)

/* Minimum 24×24px touch targets */
button,
input[type="submit"],
input[type="checkbox"],
input[type="radio"] {
  min-width: 24px;
  min-height: 24px;
}

/* Better: 44×44px for comfortable touch */
.touch-friendly {
  min-width: 44px;
  min-height: 44px;
}

3.3.7 Redundant Entry (A)

// ❌ BAD: Asking for email twice

// ✅ GOOD: Ask once, show confirmation

Confirmation will be sent to: {email}

3.3.8 Accessible Authentication (AA)

// ❌ BAD: CAPTCHA requiring text recognition

// ✅ GOOD: Alternative verification methods

  Send verification code to email

ARIA Patterns

Error Message Binding

// Pattern: aria-describedby links input to error

{hasError && (
  
    {errorMessage}
  
)}

Multiple Descriptions

// Pattern: Combine hint + error in aria-describedby

Must be at least 8 characters
{hasError && {error}}

Required Fields

// Pattern: Announce required status

  Name
  *
  {/* Visual indicator hidden from SR, aria-required announces it */}

// Alternative: Required in label (simpler)
Name (required)

Field Groups

// Pattern: fieldset + legend for related fields

  Shipping Address
  
  Street
  
  
  City
  

Radio/Checkbox Groups

// Pattern: fieldset groups options, legend is the question

  Preferred contact method
  
  
    
    Email
  
  
  
    
    Phone
  

Focus Management

Focus on First Error

// On form submit with errors, focus first invalid field
function handleSubmit(e: FormEvent) {
  e.preventDefault();
  
  const firstError = formRef.current?.querySelector('[aria-invalid="true"]');
  if (firstError) {
    (firstError as HTMLElement).focus();
    return;
  }
  
  // Submit if valid
  submitForm();
}

Focus on Step Change (Multi-step)

// Move focus to step heading when changing steps
function goToStep(stepNumber: number) {
  setCurrentStep(stepNumber);
  
  // Wait for render, then focus
  requestAnimationFrame(() => {
    const heading = document.getElementById(`step-${stepNumber}-heading`);
    heading?.focus();
  });
}

// Heading must be focusable
Shipping Address

Skip Links

// Allow skipping to form

  Skip to form

  {/* Form content */}

// CSS for skip link
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}

Focus Trap (Modals)

// Keep focus within modal form
function FocusTrap({ children }) {
  const trapRef = useRef(null);
  
  useEffect(() => {
    const trap = trapRef.current;
    if (!trap) return;
    
    const focusableElements = trap.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    const firstElement = focusableElements[0] as HTMLElement;
    const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;
    
    function handleKeyDown(e: KeyboardEvent) {
      if (e.key !== 'Tab') return;
      
      if (e.shiftKey && document.activeElement === firstElement) {
        e.preventDefault();
        lastElement.focus();
      } else if (!e.shiftKey && document.activeElement === lastElement) {
        e.preventDefault();
        firstElement.focus();
      }
    }
    
    trap.addEventListener('keydown', handleKeyDown);
    firstElement?.focus();
    
    return () => trap.removeEventListener('keydown', handleKeyDown);
  }, []);
  
  return {children};
}

Color & Contrast

Error States (Colorblind-Safe)

/* ❌ BAD: Color only */
.error {
  border-color: red;
}

/* ✅ GOOD: Color + icon + text */
.field-error {
  border-color: #dc2626;
  border-width: 2px;
}

.field-error::after {
  content: "";
  background-image: url("data:image/svg+xml,..."); /* Error icon */
}

.error-message {
  color: #dc2626;
  font-weight: 500;
}

.error-message::before {
  content: "⚠ "; /* Text indicator */
}

Focus Indicators

/* Focus must have 3:1 contrast ratio */
input:focus {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

/* For dark backgrounds */
input:focus {
  outline: 2px solid #60a5fa;
  outline-offset: 2px;
}

/* Never remove outline without replacement */
/* ❌ BAD */
input:focus {
  outline: none;
}

/* ✅ GOOD: Custom focus style */
input:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.5);
}

Validation States (Colorblind-Friendly)

// Use icons + text, not just color
function ValidationIndicator({ state }: { state: 'valid' | 'invalid' | 'idle' }) {
  if (state === 'idle') return null;
  
  return (
    
      {state === 'valid' && '✓'}
      {state === 'invalid' && '✗'}
    
  );
}

Keyboard Navigation

Tab Order

// Natural tab order (no positive tabindex needed)
// ❌ BAD: Manual tab order

// ✅ GOOD: Natural DOM order
 {/* tabIndex implicitly 0 */}

Escape Key Handling

// Allow Escape to close dropdowns, cancel modals
function Modal({ onClose, children }) {
  useEffect(() => {
    function handleEscape(e: KeyboardEvent) {
      if (e.key === 'Escape') {
        onClose();
      }
    }
    
    document.addEventListener('keydown', handleEscape);
    return () => document.removeEventListener('keydown', handleEscape);
  }, [onClose]);
  
  return {children};
}

Enter to Submit

// Forms submit on Enter by default
// For buttons that shouldn't submit:

  Add Item

// For preventing Enter submit on specific fields:
 {
    if (e.key === 'Enter') {
      e.preventDefault();
      // Do something else
    }
  }}
/>

Live Regions

Error Announcements

// Announce errors when they appear

  {errorCount > 0 && `${errorCount} errors in form`}

// Or use role="alert" for immediate announcement
{hasError && (
  {errorMessage}
)}

Loading States

// Announce loading state

  {isLoading ? (
    <>
      Loading...
      Submitting form, please wait
    
  ) : (
    'Submit'
  )}

// Or use aria-busy

  {/* ... */}

Success Messages

// Announce successful submission
{isSuccess && (
  
    Form submitted successfully!
  
)}

Screen Reader Only Content

/* Visually hidden but announced by screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Allow focus for skip links */
.sr-only-focusable:focus {
  position: static;
  width: auto;
  height: auto;
  overflow: visible;
  clip: auto;
  white-space: normal;
}

Testing Accessibility

Automated Tools

# axe-core (recommended)
npm install @axe-core/react

# In development
import React from 'react';
import ReactDOM from 'react-dom';
import axe from '@axe-core/react';

if (process.env.NODE_ENV !== 'production') {
  axe(React, ReactDOM, 1000);
}

Manual Testing Checklist

  1. Keyboard only: Can you complete the form using only Tab, Enter, Space, and Arrow keys?
  2. Screen reader: Does VoiceOver/NVDA announce labels, errors, and required status?
  3. Zoom 200%: Is the form usable at 200% browser zoom?
  4. High contrast: Is everything visible in Windows High Contrast mode?
  5. Focus visible: Can you always see which element is focused?

Testing Script

// Automated accessibility test
import { axe, toHaveNoViolations } from 'jest-axe';

expect.extend(toHaveNoViolations);

test('form is accessible', async () => {
  const { container } = render();
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

test('error state is accessible', async () => {
  const { container } = render();
  
  // Trigger error
  fireEvent.blur(screen.getByLabelText(/email/i));
  
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

File Structure

form-accessibility/
├── SKILL.md
├── references/
│   ├── wcag-2.2-forms.md       # Full WCAG criteria breakdown
│   └── aria-patterns.md        # Complete ARIA reference
└── scripts/
    ├── aria-form-wrapper.tsx   # Automatic ARIA binding
    ├── focus-manager.ts        # Focus trap, error focus
    ├── error-announcer.ts      # Live region management
    └── accessibility-validator.ts  # Runtime a11y checks

Reference

  • references/wcag-2.2-forms.md — Complete WCAG 2.2 criteria for forms
  • references/aria-patterns.md — Detailed ARIA implementation patterns

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.