Skip to content

Forms

The Forms system provides a comprehensive set of accessible form components with built-in progressive enhancement validation. All components follow WCAG 2.2 AA guidelines and work together to create inclusive form experiences that function with or without JavaScript.

The form system automatically handles validation, error messaging, focus management, and screen reader announcements. It includes protection against common security vulnerabilities like ReDoS attacks and provides both built-in and custom validation patterns.

Key features include:

  • Progressive enhancement - Forms work without JavaScript and enhance when available
  • WCAG 2.2 AA compliance with proper ARIA attributes and focus management
  • Built-in validation for common input types (email, password, tel, url)
  • Custom validation patterns and functions
  • Accessible error handling with live regions and error summaries
  • Group validation for checkboxes and radio buttons
  • Security protection against ReDoS and pattern injection attacks

Use the form components when you need:

  • Contact forms with email validation and required fields
  • Registration forms with password requirements and field validation
  • Survey forms with grouped checkboxes and radio button selections
  • Feedback forms with textarea inputs and custom validation
  • Newsletter signups with email validation and accessibility features
  • Multi-step forms that require robust validation and error handling
  • Forms that must work without JavaScript for maximum accessibility
---
import { Form, Input, Button } from 'accessible-astro-components';
---
<Form action="/submit" method="post">
<Input
name="email"
label="Email address"
type="email"
required
data-validation="Please provide a valid email address"
/>
<Button type="submit">Submit form</Button>
</Form>
<Form>
<!-- Text input with custom validation -->
<Input
name="username"
label="Username"
type="text"
required
data-validation-pattern="^[a-zA-Z0-9]{3,20}$"
data-validation="Username must be 3-20 characters, letters and numbers only"
/>
<!-- Email with built-in validation -->
<Input
name="email"
label="Email address"
type="email"
required
/>
<!-- Password with custom requirements -->
<Input
name="password"
label="Password"
type="password"
required
data-validation="Password must be at least 8 characters long"
/>
</Form>
<Form>
<Textarea
name="message"
label="Your message"
required
rows={5}
data-validation="Please provide your message (required)"
/>
</Form>
<Form>
<Fieldset name="preferences" legend="Newsletter preferences" required>
<Checkbox name="newsletter" label="Weekly newsletter" value="weekly" />
<Checkbox name="newsletter" label="Monthly updates" value="monthly" />
<Checkbox name="newsletter" label="Special offers" value="offers" />
</Fieldset>
<Fieldset name="contact-method" legend="Preferred contact method" required>
<Radio name="contact" label="Email" value="email" />
<Radio name="contact" label="Phone" value="phone" />
<Radio name="contact" label="Mail" value="mail" />
</Fieldset>
</Form>
---
// Define custom validation function
---
<script>
// Custom validation function available globally
window.validatePhoneNumber = (value) => {
// Custom phone number validation logic
const phoneRegex = /^(\+1|1)?[-.\s]?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}$/;
return phoneRegex.test(value);
};
</script>
<Form>
<Input
name="phone"
label="Phone number"
type="tel"
required
data-validation-fn="validatePhoneNumber"
data-validation="Please provide a valid US phone number"
/>
</Form>
PropTypeDefaultDescription
classstringundefinedAdditional CSS classes
actionstringundefinedForm action URL
namestringundefinedForm name attribute
method'get' | 'post''post'HTTP method for form submission
enctype'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/plain''application/x-www-form-urlencoded'Encoding type for form data
target'_self' | '_blank' | '_parent' | '_top''_self'Target for form submission
autocomplete'on' | 'off''on'Autocomplete behavior
PropTypeDefaultDescription
namestring-Required. Name attribute for form submission
labelstring-Required. Label text for the input
data-validationstringAuto-generatedCustom error message
type'text' | 'email' | 'password' | 'tel' | 'url''text'Input type with built-in validation
requiredbooleanfalseWhether the field is required
data-validation-patternstringundefinedCustom regex validation pattern
data-validation-fnstringundefinedCustom validation function name
valuestringundefinedDefault value
disabledbooleanfalseWhether the field is disabled
readonlybooleanfalseWhether the field is readonly
autocompletestring'on'Autocomplete attribute value
PropTypeDefaultDescription
namestring-Required. Name attribute for form submission
labelstring-Required. Label text for the textarea
data-validationstringAuto-generatedCustom error message
requiredbooleanfalseWhether the field is required
data-validation-patternstringundefinedCustom regex validation pattern
data-validation-fnstringundefinedCustom validation function name
rowsnumberundefinedNumber of visible text lines
colsnumberundefinedNumber of visible text columns
placeholderstringundefinedPlaceholder text
PropTypeDefaultDescription
namestring-Required. Name attribute for form submission
labelstring-Required. Label text for the checkbox
valuestringundefinedValue attribute for the checkbox
checkedbooleanfalseWhether checked by default
disabledbooleanfalseWhether the field is disabled
PropTypeDefaultDescription
namestring-Required. Name attribute shared within group
labelstring-Required. Label text for the radio button
valuestring-Required. Value attribute for the radio button
checkedbooleanfalseWhether checked by default
disabledbooleanfalseWhether the field is disabled
PropTypeDefaultDescription
namestring-Required. Name attribute for group validation
legendstring-Required. Legend text for the fieldset
requiredbooleanfalseWhether at least one selection is required
data-validationstringAuto-generatedCustom error message for group validation
variant'default' | 'minimal''default'Visual style variant

The form system is designed with accessibility as a priority and meets WCAG 2.2 AA standards:

  • Tab navigation through all form controls in logical order
  • Enter key submits forms when focused on submit buttons
  • Arrow keys navigate between radio buttons in the same group
  • Space key toggles checkboxes and selects radio buttons
  • Proper labeling with <label> elements associated via for attributes
  • Fieldset legends provide group context for checkboxes and radio buttons
  • Live regions announce validation errors using aria-live="polite"
  • Error summaries with focus management for failed validation
  • Descriptive error messages linked via aria-describedby
  • aria-invalid="true" applied to fields with validation errors
  • aria-describedby links inputs to their validation messages
  • role="alert" used for critical error notifications
  • Proper aria-live regions for dynamic error announcements
  • Progressive enhancement ensures forms work without JavaScript
  • Error summaries appear at form submission with focusable links
  • Inline validation messages appear below each field
  • Visual and programmatic error indicators for all users
  • Automatic focus management to error summary on validation failure
  • Email validation with helpful error messages
  • Password strength requirements (minimum 8 characters)
  • Phone number format validation
  • URL format validation with protocol requirements
  • Required field validation with clear messaging

Form components use CSS custom properties for easy theming while maintaining accessibility requirements.

/* Custom form styling */
:global(.form) {
--color-default-border: hsl(210, 20%, 80%);
--color-error-border: hsl(0, 70%, 60%);
--space-xs: 1rem;
--space-2xs: 0.75rem;
--radius-s: 0.375rem;
}
/* Focus styles (maintain for accessibility) */
:global(.input-group input:focus) {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Error state styling */
:global(.input-group:has([aria-invalid='true']) input) {
border-color: var(--color-error-border);
box-shadow: 0 0 0 1px var(--color-error-border);
}
/* Validation message styling */
:global(.input-group small) {
color: var(--color-error-text);
font-size: 0.875rem;
}
<!-- Username validation with specific requirements -->
<Input
name="username"
label="Username"
type="text"
required
data-validation-pattern="^[a-zA-Z0-9_]{3,20}$"
data-validation="Username must be 3-20 characters (letters, numbers, underscore only)"
/>
<!-- Credit card number validation -->
<Input
name="card-number"
label="Credit card number"
type="text"
required
data-validation-pattern="^[0-9]{4}[\s-]?[0-9]{4}[\s-]?[0-9]{4}[\s-]?[0-9]{4}$"
data-validation="Please enter a valid 16-digit credit card number"
/>
<script>
// Advanced validation function
window.validatePassword = (value) => {
const hasUpperCase = /[A-Z]/.test(value);
const hasLowerCase = /[a-z]/.test(value);
const hasNumbers = /\d/.test(value);
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value);
const isLongEnough = value.length >= 8;
return hasUpperCase && hasLowerCase && hasNumbers && hasSpecialChar && isLongEnough;
};
</script>
<Input
name="password"
label="Password"
type="password"
required
data-validation-fn="validatePassword"
data-validation="Password must be at least 8 characters with uppercase, lowercase, number, and special character"
/>
What are you interested in? (required)
Your experience level (required)
Terms and conditions (required)

The form system includes built-in security protections:

  • ReDoS protection - Custom regex patterns are validated for safety and length-limited
  • Pattern sanitization - Invalid patterns are escaped as literal strings
  • XSS prevention - All user input is properly escaped
  • Length limits - Validation patterns are limited to 200 characters
  • Safe fallbacks - Invalid validation functions fail gracefully