Token导航 LogoToken导航

Agent Skill · 前端设计

form-accessibility(表单可访问性)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

form-accessibility 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证为 MIT,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 3,930。

总安装 1,058周安装 45GitHub Stars 8下载 371核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:form-accessibility(表单可访问性)
来源仓库:https://github.com/bbeierle12/skill-mcp-claude
仓库路径:skills/form-accessibility
安装命令:
npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill form-accessibility
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill form-accessibility

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

form-accessibility 用于辅助前端页面、组件、样式和交互逻辑的开发与维护,提升可访问性。适用于 React、Next.js、Vue、Tailwind、CSS 等项目中的表单组件开发与审查。通过 npx skills add 命令从指定 GitHub 仓库安装,需结合项目现有设计系统和构建方式使用。

涉及页面改动时应配合本地预览和构建检查确认视觉效果,避免生成孤立片段。该技能归类为前端设计类,当前维护状态尚不明确,建议进一步核实稳定性。

来源仓库内路径:skills/form-accessibility

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill form-acces…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要操作浏览器,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

form-accessibility 怎么安装?

在终端执行 npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill form-accessibility。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

form-accessibility 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

form-accessibility 需要什么权限?

权限级别是操作浏览器。该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

form-accessibility 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

form-accessibility 用的人多吗?

公开数据是累计安装 1,058 次,近一周安装 45 次,下载 371 次,GitHub 8 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

form-accessibility 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
form-accessibility

表单可访问性 · 本页

1,0588操作浏览器MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

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
<div className="form-field">
  {/* 1. Visible label (never placeholder-only) */}
  <label htmlFor="email">
    Email
    <span className="required" aria-hidden="true">*</span>
  </label>

  {/* 2. Hint text (separate from label) */}
  <span id="email-hint" className="hint">
    We'll send your confirmation here
  </span>

  {/* 3. Input with full ARIA binding */}
  <input
    id="email"
    type="email"
    autoComplete="email"
    aria-required="true"
    aria-invalid={hasError}
    aria-describedby={hasError ? "email-error email-hint" : "email-hint"}
  />

  {/* 4. Error message (announced by screen readers) */}
  {hasError && (
    <span id="email-error" className="error" role="alert">
      Please enter a valid email address
    </span>
  )}
</div>

WCAG 2.2 Form Requirements

Critical Criteria

CriterionLevelRequirementImplementation
1.3.1 Info & RelationshipsAStructure conveyed programmatically<label>, <fieldset>, aria-describedby
1.3.5 Identify Input PurposeAAInput purpose identifiableautocomplete attributes
2.1.1 KeyboardAAll functionality via keyboardTab order, focus management
2.4.6 Headings & LabelsAALabels describe purposeDescriptive, visible labels
2.4.11 Focus Not ObscuredAAFocus not hidden by other contentScroll behavior, sticky elements
2.5.8 Target SizeAA24×24px minimum touch targetButton/input sizing
3.3.1 Error IdentificationAErrors identified and describedaria-invalid, error messages
3.3.2 Labels or InstructionsALabels providedVisible labels, not just placeholders
3.3.3 Error SuggestionAASuggestions for fixing errorsActionable error messages
3.3.7 Redundant EntryADon't re-ask for info already providedForm state management
3.3.8 Accessible AuthenticationAANo cognitive function testsNo 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
<input name="email" />
<input name="confirmEmail" />

// ✅ GOOD: Ask once, show confirmation
<input name="email" />
<p>Confirmation will be sent to: {email}</p>

3.3.8 Accessible Authentication (AA)

// ❌ BAD: CAPTCHA requiring text recognition
<img src="captcha.png" alt="Enter the text shown" />

// ✅ GOOD: Alternative verification methods
<button type="button" onClick={sendVerificationEmail}>
  Send verification code to email
</button>

ARIA Patterns

Error Message Binding

// Pattern: aria-describedby links input to error
<input
  id="email"
  aria-invalid={hasError ? "true" : "false"}
  aria-describedby={hasError ? "email-error" : undefined}
/>

{hasError && (
  <span id="email-error" role="alert">
    {errorMessage}
  </span>
)}

Multiple Descriptions

// Pattern: Combine hint + error in aria-describedby
<input
  id="password"
  aria-describedby={[
    "password-hint",
    hasError && "password-error"
  ].filter(Boolean).join(" ")}
/>

<span id="password-hint">Must be at least 8 characters</span>
{hasError && <span id="password-error" role="alert">{error}</span>}

Required Fields

// Pattern: Announce required status
<label htmlFor="name">
  Name
  <span className="required" aria-hidden="true">*</span>
  {/* Visual indicator hidden from SR, aria-required announces it */}
</label>

<input
  id="name"
  aria-required="true"
/>

// Alternative: Required in label (simpler)
<label htmlFor="name">Name (required)</label>
<input id="name" required />

Field Groups

// Pattern: fieldset + legend for related fields
<fieldset>
  <legend>Shipping Address</legend>

  <label htmlFor="street">Street</label>
  <input id="street" autoComplete="street-address" />

  <label htmlFor="city">City</label>
  <input id="city" autoComplete="address-level2" />
</fieldset>

Radio/Checkbox Groups

// Pattern: fieldset groups options, legend is the question
<fieldset>
  <legend>Preferred contact method</legend>

  <label>
    <input type="radio" name="contact" value="email" />
    Email
  </label>

  <label>
    <input type="radio" name="contact" value="phone" />
    Phone
  </label>
</fieldset>

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
<h2 id="step-2-heading" tabIndex={-1}>Shipping Address</h2>

Skip Links

// Allow skipping to form
<a href="#main-form" className="skip-link">
  Skip to form
</a>

<form id="main-form">
  {/* Form content */}
</form>

// 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<HTMLDivElement>(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 <div ref={trapRef}>{children}</div>;
}

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 (
    <span className={`indicator ${state}`} aria-hidden="true">
      {state === 'valid' && '✓'}
      {state === 'invalid' && '✗'}
    </span>
  );
}

Keyboard Navigation

Tab Order

// Natural tab order (no positive tabindex needed)
// ❌ BAD: Manual tab order
<input tabIndex={2} />
<input tabIndex={1} />
<input tabIndex={3} />

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

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 <div role="dialog" aria-modal="true">{children}</div>;
}

Enter to Submit

// Forms submit on Enter by default
// For buttons that shouldn't submit:
<button type="button" onClick={handleAction}>
  Add Item
</button>

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

Live Regions

Error Announcements

// Announce errors when they appear
<div aria-live="polite" aria-atomic="true" className="sr-only">
  {errorCount > 0 && `${errorCount} errors in form`}
</div>

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

Loading States

// Announce loading state
<button type="submit" disabled={isLoading}>
  {isLoading ? (
    <>
      <span aria-hidden="true">Loading...</span>
      <span className="sr-only">Submitting form, please wait</span>
    </>
  ) : (
    'Submit'
  )}
</button>

// Or use aria-busy
<form aria-busy={isLoading}>
  {/* ... */}
</form>

Success Messages

// Announce successful submission
{isSuccess && (
  <div role="status" aria-live="polite">
    Form submitted successfully!
  </div>
)}

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(<LoginForm />);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

test('error state is accessible', async () => {
  const { container } = render(<LoginForm />);

  // 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

平台分布

Claude Code

30.76%
按下载量换算114

OpenCode

24.39%
按下载量换算90

Antigravity

20.28%
按下载量换算75

windsurf

11.57%
按下载量换算43

Gemini CLI

7.72%
按下载量换算29

Codex

3.56%
按下载量换算13

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills