accessibility-patterns
WCAG 2.2 AA compliance, ARIA patterns, keyboard navigation, screen reader optimization
React Hook Form + Zod integration, multi-step forms, optimistic validation, server-side error mapping, and file upload patterns.
Claude Code
$ npx -y skills add vibeeval/vibecosystem --skill form-validation --agent claude-code
Codex
$ npx skills add vibeeval/vibecosystem --skill form-validation -a codex -y
Cursor
$ npx skills add vibeeval/vibecosystem --skill form-validation -a cursor -y
Gemini CLI
$ npx skills add vibeeval/vibecosystem --skill form-validation -a gemini-cli -y
GitHub Copilot
$ npx skills add vibeeval/vibecosystem --skill form-validation -a github-copilot -y
OpenCode
$ npx skills add vibeeval/vibecosystem --skill form-validation -a opencode -y
Windsurf
$ npx skills add vibeeval/vibecosystem --skill form-validation -a windsurf -y
name: form-validation description: React Hook Form + Zod integration, multi-step forms, optimistic validation, server-side error mapping, and file upload patterns.
React Hook Form + Zod patterns for robust, accessible forms.
// Install: npm install react-hook-form zod @hookform/resolvers
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
// 1. Define schema
const TaskSchema = z.object({
title: z.string().min(1, 'Title is required').max(200),
description: z.string().max(2000).optional(),
priority: z.enum(['low', 'medium', 'high']),
dueDate: z.string().date('Invalid date').optional(),
})
type TaskFormData = z.infer<typeof TaskSchema>
// 2. Use in component
export function TaskForm({ onSubmit }: { onSubmit: (data: TaskFormData) => Promise<void> }) {
const {
register,
handleSubmit,
formState: { errors, isSubmitting, isDirty },
setError,
reset,
} = useForm<TaskFormData>({
resolver: zodResolver(TaskSchema),
defaultValues: { priority: 'medium' },
})
const submit = handleSubmit(async (data) => {
try {
await onSubmit(data)
reset()
} catch (err) {
// Map server errors to fields (see Server-Side Error Mapping)
setError('title', { message: 'A task with this title already exists' })
}
})
return (
<form onSubmit={submit} noValidate>
<div>
<label htmlFor="title">Title *</label>
<input
id="title"
{...register('title')}
aria-invalid={!!errors.title}
aria-describedby={errors.title ? 'title-error' : undefined}
/>
{errors.title && (
<p id="title-error" role="alert" className="text-red-600 text-sm">
{errors.title.message}
</p>
)}
</div>
<button type="submit" disabled={isSubmitting || !isDirty}>
{isSubmitting ? 'Saving...' : 'Save Task'}
</button>
</form>
)
}import { z } from 'zod'
// Common field patterns
const emailField = z.string().email('Invalid email address').toLowerCase()
const passwordField = z.string()
.min(8, 'At least 8 characters')
.regex(/[A-Z]/, 'Must contain uppercase letter')
.regex(/[0-9]/, 'Must contain a number')
const urlField = z.string().url('Must be a valid URL').optional().or(z.literal(''))
const phoneField = z.string()
.regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number')
.optional()
// Cross-field validation (refine)
const PasswordChangeSchema = z
.object({
password: passwordField,
confirmPassword: z.string(),
})
.refine(data => data.password === data.confirmPassword, {
message: 'Passwords do not match',
path: ['confirmPassword'], // error attached to confirmPassword field
})
// Conditional fields (superRefine)
const EventSchema = z
.object({
type: z.enum(['online', 'in-person']),
url: z.string().url().optional(),
address: z.string().optional(),
})
.superRefine((data, ctx) => {
if (data.type === 'online' && !data.url) {
ctx.addIssue({ code: 'custom', message: 'URL required for online events', path: ['url'] })
}
if (data.type === 'in-person' && !data.address) {
ctx.addIssue({ code: 'custom', message: 'Address required', path: ['address'] })
}
})import { useState } from 'react'
import { useForm, FormProvider } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
const steps = ['Personal', 'Details', 'Review'] as const
type Step = (typeof steps)[number]
// Each step has its own schema
const Step1Schema = z.object({ name: z.string().min(1), email: emailField })
const Step2Schema = z.object({ company: z.string().min(1), role: z.string().min(1) })
const FullSchema = Step1Schema.merge(Step2Schema)
type FormData = z.infer<typeof FullSchema>
export function MultiStepForm() {
const [currentStep, setCurrentStep] = useState(0)
const methods = useForm<FormData>({
resolver: zodResolver(FullSchema),
mode: 'onTouched',
})
const stepSchemas = [Step1Schema, Step2Schema]
const next = async () => {
// Validate only current step's fields
const fieldsToValidate = Object.keys(stepSchemas[currentStep].shape) as (keyof FormData)[]
const valid = await methods.trigger(fieldsToValidate)
if (valid) setCurrentStep(s => s + 1)
}
const submit = methods.handleSubmit(async (data) => {
await createUser(data)
})
return (
<FormProvider {...methods}>
{/* Progress indicator */}
<nav aria-label="Form steps">
{steps.map((step, i) => (
<span key={step} aria-current={i === currentStep ? 'step' : undefined}>
{step}
</span>
))}
</nav>
<form onSubmit={submit}>
{currentStep === 0 && <Step1Fields />}
{currentStep === 1 && <Step2Fields />}
{currentStep === 2 && <ReviewStep />}
<div className="flex gap-2">
{currentStep > 0 && (
<button type="button" onClick={() => setCurrentStep(s => s - 1)}>Back</button>
)}
{currentStep < steps.length - 1 ? (
<button type="button" onClick={next}>Next</button>
) : (
<button type="submit">Submit</button>
)}
</div>
</form>
</FormProvider>
)
}import { useForm } from 'react-hook-form'
// API returns: { errors: { field: string[] } }
interface ApiError {
errors?: Record<string, string[]>
message?: string
}
export function RegistrationForm() {
const { register, handleSubmit, setError, formState: { errors } } = useForm<FormData>()
const submit = handleSubmit(async (data) => {
try {
await registerUser(data)
} catch (err) {A focused runtime for Claude Code. A bounded worker for Codex. Catalog (in repo): Default core: vibecosystem packages agents, skills and hooks for software work.
WCAG 2.2 AA compliance, ARIA patterns, keyboard navigation, screen reader optimization
axe-core integration, WCAG 2.2 AA checklist, keyboard navigation testing, screen reader testing, and ARIA pattern validation.
Steam-style achievement system with XP, levels, streaks, and skill trees. Gamifies the development workflow. 25 achievements…
Framework for measuring and tracking agent response quality over time. Detects regressions before they reach production. Use when…
Agent ve skill dosyalarinin yapisal dogrulamasi. Frontmatter kontrol, naming convention, zorunlu bolum kontrolu, tutarlilik…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.