Form Elements
All common form elements
Form Elements Sample(s):
Checkboxes
Default and error states for common form checkboxes. Checkboxes are validated on-blur to give feedback as soon as a user exits a form field. Make sure to include the required and aria-required attributes only when a field is required.
The aria-checked attribute of a checkbox indicates whether the input is checked (true), unchecked (false), or represents a group of elements that have a mixture of checked and unchecked values (mixed). Many checkboxes do not use the mixed value, and thus are effectively boolean checkboxes.
<form action="" class="validate">
<div class="flex-col checkbox-group default-form mb-8">
<input type="checkbox" id="terms_agreement" name="selectables" value="terms_agreement" required="">
<label for="terms_agreement" class="mr-6 d-ib lh-5">I agree to the terms and conditions</label>
</div>
</form>Input Elements
Default and error states for common form inputs. Inputs are validated on-blur to give feedback as soon as a user exits a form field. Make sure to include the required and aria-required attributes only when a field is required.
A form may be a mix of host language form controls, scripted controls, and hyperlinks. Authors are reminded to use native host language semantics to create form controls, whenever possible. For search facilities, authors SHOULD use the search role and not the generic form role. Authors SHOULD provide a visible label for the form referenced with aria-labelledby. If an author uses a script to submit a form based on a user action that would otherwise not trigger an onsubmit event (for example, a form submission triggered by the user changing a form element's value), the author SHOULD provide the user with advance notification of the behavior.
Date Input
<form action="" class="validate">
<div class="form-group">
<label for="coverage_start_date">Please select the date you would like your coverage to start</label>
<div class="flex w-full">
<div class="flex bg-cyan-100 rounded h-10 w-10 items-center justify-center mr-3" aria-hidden="true">
<svg class="flex h-6 w-6 fill-white">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icons-calendar"></use>
</svg>
</div>
<div class="flex-auto">
<label for="coverage_start_date" class="screen-reader">Date</label>
<input class="w-full" type="date" pattern="(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))" name="coverage_start_date" id="coverage_start_date" required="" aria-required="true">
</div>
</div>
<p class="form-info">Additional information about this form field. This is not a required content block.</p>
</div>
</form><template>
<form action="">
<div class="form-group">
<label for="coverage_start_date">Please select the date you would like your coverage to start</label>
<div class="flex w-full">
<div class="flex bg-cyan-100 rounded h-10 w-10 items-center justify-center mr-3" aria-hidden="true">
<Calendar class="calendar-icon" />
</div>
<div class="flex-auto">
<label for="coverage_start_date" class="screen-reader">Date</label>
<input class="w-full" type="date" id="coverage_start_date"
v-model="form.coverage_start_date"
@blur="$v.form.coverage_start_date.$touch()"
:class="{error: appendErrorClass($v.form.coverage_start_date)}"
placeholder="MM/DD/YYYY">
</div>
</div>
<div v-if="$v.form.coverage_start_date.$error" class="error-message w-full">Please enter a date.</div>
<p class="form-info">Additional information about this form field. This is not a required content block.</p>
</div>
</form>
</template>
<script>
import { required } from 'vuelidate/lib/validators';
import Calendar from '<PATH_TO>/calendar.svg';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
export default {
components: {
Calendar
},
data() {
return {
form: {
coverage_start_date: null
}
};
},
mixins: [appendErrorClass],
validations() {
return {
form: {
coverage_start_date: { required }
}
}
}
};
</script>
Email Input
<form action="" class="validate">
<div class="form-group">
<label for="email_address">Please enter your email address</label>
<input type="email" pattern="^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*(\.\w{2,})+$"
name="email_address" id="email_address" required="" aria-required="true">
</div>
</form><template>
<div class="form-group">
<label for="email_address">Please enter your email address</label>
<input type="email" id="email_address"
v-model="form.email_address"
@blur="$v.form.email_address.$touch()"
:class="{error: appendErrorClass($v.form.email_address)}">
<div class="w-full" v-if="$v.form.email_address.$error">
<div v-if="!$v.form.email_address.required" class="error-message">An email is required to continue</div>
<div v-else-if="!$v.form.email_address.email" class="error-message">Please use a valid email address.</div>
</div>
</div>
</template>
<script>
import { required, email } from 'vuelidate/lib/validators';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
export default {
data() {
return {
form: {
email_address: null
}
};
},
mixins: [ appendErrorClass ],
validations() {
return {
form: {
email_address: {
email,
required
},
}
};
}
};
</script>Number Input
<form action="" class="validate">
<div class="form-group">
<label for="years_in_profession">How many years have you been in this profession?</label>
<input type="number" name="years_in_profession" id="years_in_profession" min="1"
max="100" required="" aria-required="true">
</div>
</form><template>
<div class="form-group">
<label for="years_in_profession">How many years have you been in this profession?</label>
<input type="number" id="years_in_profession" placeholder="0"
v-model="form.years_in_profession"
@blur="$v.form.years_in_profession.$touch()"
:class="{error: appendErrorClass($v.form.years_in_profession)}">
<div class="w-full" v-if="$v.form.years_in_profession.$error">
<div v-if="!$v.form.years_in_profession.required" class="error-message w-full">Please fill out this field.</div>
<div v-else-if="!$v.form.years_in_profession.between" class="error-message w-full">Please select a value that is no more than 100.</div>
</div>
</div>
</template>
<script>
import { required, between } from 'vuelidate/lib/validators';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
export default {
data() {
return {
form: {
years_in_profession: null
}
};
},
mixins: [ appendErrorClass ],
validations() {
return {
form: {
years_in_profession: {
between: between(1, 100),
required
},
}
};
}
};
</script>Password Input
<form action="" class="validate">
<div class="form-group">
<label for="password">Create Password</label>
<input type="password" name="password" id="password" minlength="7" pattern="^(?=.*[a-zA-Z])(?=.*\d).+$"
required="" aria-required="true">
<p class="form-info">Must be at least 7 characters and contain both a number and a letter</p>
</div>
</form>Telephone Input
<form action="" class="validate">
<div class="form-group">
<label for="tel_primary">Phone Number</label>
<input type="tel" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" name="tel_primary" id="tel_primary" placeholder="(123) 123-1234"
required="" aria-required="true">
</div>
</form><template>
<div class="form-group">
<label for="tel_primary">Phone Number</label>
<input type="tel" id="tel_primary" placeholder="(123) 123-1234"
@change="phoneFormat"
v-model="form.tel_primary"
@blur="$v.form.tel_primary.$touch();"
:class="{error: appendErrorClass($v.form.tel_primary)}">
<div v-if="$v.form.tel_primary.$error" class="error-message w-full">Please enter a telephone number.</div>
</div>
</template>
<script>
import { required } from 'vuelidate/lib/validators';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
const PHONE_NUMBER_REGEX = /^\(\d{3}\)\s\d{3}\-\d{4}$/;
export default {
data() {
return {
form: {
tel_primary: null
}
}
},
methods: {
phoneFormat: function() {
if (PHONE_NUMBER_REGEX.test(this.form.tel_primary)){
return;
}
this.form.tel_primary = this.form.tel_primary.replace(/[^\d]+/g, '');
if (10 > this.form.tel_primary){
return;
}
let truncated = this.form.tel_primary.substring(0,10);
this.form.tel_primary = truncated.replace(/(\d{3})(\d{3})(\d{4})/g, '($1) $2-$3');
},
},
mixins: [ appendErrorClass ],
validations() {
return {
form: {
tel_primary: {
required,
minLength: minLength(14)
},
}
}
},
}
</script>Text Input
<form action="" class="validate">
<div class="form-group">
<label for="first_name">First Name</label>
<input type="text" name="first_name" id="first_name" required="" aria-required="true">
</div>
</form><template>
<div class="form-group">
<label for="first_name">Full name</label>
<input type="text" id="first_name"
v-model="form.first_name"
@blur="$v.form.first_name.$touch()"
:class="{error: appendErrorClass($v.form.first_name)}">
<div v-if="$v.form.first_name.$error" class="error-message w-full">Please fill out this field.</div>
</div>
</template>
<script>
import { required } from 'vuelidate/lib/validators';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
export default {
data() {
return {
form: {
first_name: null
}
};
},
mixins: [ appendErrorClass ],
validations() {
return {
form: {
first_name: {
required
},
}
};
}
};
</script>Radio Buttons
Default and error states for common and advanced form radio buttons. Radio buttons are validated on-blur to give feedback as soon as a user exits a form field. Make sure to include the required and aria-required attributes only when a field is required.
A checkable input in a group of elements with the same role, only one of which can be checked at a time. Authors SHOULD ensure that elements with role radio are explicitly grouped in order to indicate which ones affect the same value. This is achieved by enclosing the radio elements in an element with role radiogroup. If it is not possible to make the radio buttons DOM children of the radiogroup, authors SHOULD use the aria-owns attribute on the radiogroup element to indicate the relationship to its children.
Default Form Radio Buttons
<form action="" class="validate">
<div class="flex-col form-group radio-button-group default-form">
<div class="mb-5">
<p class="font-semibold mb-0">Do you or your firm use standard written contracts for all real estate transactions?</p>
</div>
<input type="radio" id="standard_written_contracts_yes" name="standard_written_contracts" value="standard_written_contracts_yes"
required="">
<label for="standard_written_contracts_yes" class="mr-5">Yes</label>
<input type="radio" id="standard_written_contracts_no" name="standard_written_contracts" value="standard_written_contracts_no"
required="">
<label for="standard_written_contracts_no" class="mr-5">No</label>
</div>
</form><template>
<div class="flex-col form-group radio-button-group default-form">
<div class="mb-5">
<p class="font-semibold mb-0">How do you prefer to be contacted?</p>
</div>
<div class="flex"
:class="{'p-3 bg-lt-red rounded': appendErrorClass($v.form.standard_written_contracts)}">
<input type="radio" id="standard_written_contracts_yes"
value="standard_written_contracts_yes"
v-model="form.standard_written_contracts"
@blur="$v.form.standard_written_contracts.$touch()"
:class="{error: appendErrorClass($v.form.standard_written_contracts)}">
<label for="standard_written_contracts_yes" class="mr-5 mr-5 w-auto">Yes</label>
<input type="radio" id="standard_written_contracts_no"
value="standard_written_contracts_no"
v-model="form.standard_written_contracts"
@blur="$v.form.standard_written_contracts.$touch()"
:class="{error: appendErrorClass($v.form.standard_written_contracts)}">
<label for="standard_written_contracts_no" class="mr-5 mr-5 w-auto">No</label>
</div>
<div v-if="$v.form.standard_written_contracts.$error" class="error-message w-full">Please select from the above.</div>
</div>
</template>
<script>
import { required } from 'vuelidate/lib/validators';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
export default {
data() {
return {
form: {
standard_written_contracts: null
}
};
},
mixins: [ appendErrorClass ],
validations() {
return {
form: {
standard_written_contracts: {
required
},
}
};
}
};
</script>Advanced Form Radio Buttons
<form action="" class="validate">
<div class="radio-button-advanced-wrapper radio-button-group radio-button-advanced-group">
<div class="radio-button-advanced">
<input class="absolute inset-0 zi-10" type="radio" id="limits-of-liability_pc_6" name="limits-of-liability" value="limits-of-liability_pc_6"
required="">
<label for="limits-of-liability_pc_250_agg_500">
<span class="visuallyhidden">$250K per claim, $500K Aggregate</span>
</label>
<div class="radio-button-content-wrapper">
<div class="radio-button-content">
<div class="lg:mb-3">
<p class="text-xs text-lt-black mb-1">Per Claim</p>
<p class="font-semibold text-cyan-100 m-0">$250K</p>
</div>
<div>
<p class="text-xs text-lt-black mb-1">Aggregate</p>
<p class="font-semibold text-cyan-100 m-0">$500K</p>
</div>
</div>
</div>
<div class="most-common zi-50 text-xs leading-loose font-semibold">Most Common
<span class="lh-5">â–¾</span>
</div>
</div>
</div>
</form>Alternative Advanced Form Radio Buttons
<form action="" class="validate">
<div class="radio-button-advanced-wrapper radio-button-group radio-button-advanced-group">
<div class="radio-button-advanced radio-button-advanced-alt">
<input type="radio" id="button-name" name="limits-of-liability" value="button-name"
required="">
<label for="button-name">
<span class="visuallyhidden">Some Sort of Label for Screen Readers</span>
</label>
<div class="radio-button-content-wrapper">
<div class="radio-button-content">
<p class="text-xs text-lt-black">Per Claim</p>
<p class="text-xs text-lt-black">Some additional content here.</p>
</div>
</div>
</div>
</div>
</form>Select Boxes
Default and error states for common form select boxes. Select boxes are validated on-blur to give feedback as soon as a user exits a form field. Make sure to include the required and aria-required attributes only when a field is required.
A form widget that allows the user to make selections from a set of choices.
<form action="" class="validate">
<div class="form-group select-box-group">
<label for="work">Where do you work?</label>
<select name="work" id="work" class="ih-5 br-sm b-s-md bc-steel-grey ph-5 ts-lg" required="">
<option value="" class="placeholder" hidden="">Choose...</option>
<option value="GOOG">Google</option>
<option value="FB">Facebook</option>
<option value="TW">Twitter</option>
<option value="LI">LinkedIn</option>
<option value="IG">Instagram</option>
</select>
</div>
</form><template>
<div class="form-group select-box-group">
<label for="employment_type">Where do you work?</label>
<select id="employment_type"
v-model="form.employment_type"
@blur="$v.form.employment_type.$touch()"
:class="{error: appendErrorClass($v.form.employment_type)}">
<option value="" class="placeholder" hidden="">Choose...</option>
<option v-for="(item, index) in employmentType" :value="item.value">{{item.text}}</option>
</select>
<div v-if="$v.form.employment_type.$error" class="error-message w-full">Please fill out this field.</div>
</div>
</template>
<script>
import { required } from 'vuelidate/lib/validators';
import appendErrorClass from '<PATH_TO>/mixins/appendErrorClassMixin.js';
export default {
data() {
return {
form: {
employment_type: null
}
};
},
mixins: [ appendErrorClass ],
validations() {
return {
employmentType: [
{"value": "google", "text": "Google"},
{"value": "facebook", "text": "Facebook"},
{"value": "twitter", "text": "Twitter"},
{"value": "linkin_in", "text": "Linked In"},
{"value": "instagram", "text": "Instagram"}
],
form: {
employment_type: {
required
},
}
};
}
};
</script>Form Submit Buttons
Default Form Submit
<form action="">
<div class="flex items-center border-t border-lt-grey-100 py-5 my-12 justify-between">
<a href="/quote/account" class="flex flex-auto items-center no-underline text-cyan-100 hover:text-navy-100">
<svg class="h-3 w-3 fill-cyan-100" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icons-arrow-left"></use>
</svg>
<strong class="ml-3">Go Back</strong>
</a>
<button class="btn btn-primary" type="submit">Continue</button>
</div>
</form>