Examples
This component mirrors user input as formatted "hint text" after the label to provide visual feedback about the data as the user is typing. The text in the input field itself will not be formatted until the field loses focus, which is when we know the user has finished typing.
Because the hinting isn't being applied to the input itself, it's less distracting and obtrusive to screen reader users, providing a quieter and more usable experience for everyone. It is an updated alternative to our Masked Field.
The label-mask currently has five built-in implementations: currency, phone number, Social Security Number, ZIP code, and date. The date mask is implemented by the Calendar Picker and Single-Input Date Field components, while the rest are available for direct use with the Text Field component.
Currency
Phone number
Social Security number
ZIP code
Guidance
When to use
- In fields with a specific expected format like Social Security Number or ZIP code, a label mask allows you to constrain and shape the information being entered without impairing the user's ability to copy/paste or correct mistyping
When to consider alternatives
- When the input requires a free-form field that doesn't use a common input pattern, masking is not appropriate.
- When the pattern is too complicated to allow for a valid label mask. A pattern like email, with many possible scenarios for input, is not a good candidate for masking. Allow the user to enter their email address (or other complicated data) and have your validation library confirm before form submission.
Usage
- Only show error validation messages or stylings after a user has interacted with a particular field
Accessibility
For general accessibility guidance, refer to the TextField
component documentation.
Accessibility testing
For mobile devices, text fields should work in both portrait and landscape orientation with no loss of functionality.
Keyboard navigation
- Users must be able to use only a keyboard to navigate to the text field, type in it, and navigate away from it.
- Focus indicators must be clearly visible around the text fields.
Screen reader
- Screen readers must announce text fields and their labels in the same order they appear visually on the page.
- Screen readers must announce the purpose of each text field (e.g., “Edit, blank. Type in text. ”).
- Screen readers must announce associated labels and instructions when a text field receives focus (e.g., “Enter first name.”).
Zoom magnification
- When zoomed to 200%, text fields must remain legible, functional, and properly sized.
Code
React
Passing a labelMask
prop into a TextField
component with a valid masking function will turn it into a label mask. You can either import one of the named, built-in mask functions (SSN_MASK
, ZIP_MASK
, PHONE_MASK
, or CURRENCY_MASK
), or you can provide a custom mask function. The following table shows the TextField
prop that is specific to label masks:
Review Storybook for React guidance of this component.
Handling input changes
When tracking state in a parent component, treat the value as a raw input string, which is updated by the onChange
handler. Do not try to unmask or clean the value before passing it back to the TextField
component instance. The intention with this is to keep the API and behavior of the component as simple as possible. You don't need to handle onBlur
separately from onChange
. You only need to update your value when onChange
is called, and it will be called whenever the value of the input changes, including on blur. A more appropriate place to clean the input would be in your validation code.
// A simplified example of change handling. This is not a recommendation
// for how to structure error messages or validation code but serves only
// to illustrate how to set and get values from the label-masked field.
import { useState } from "react";
import { Button, TextField, SSN_MASK } from '@cmsgov/design-system';
export const MyForm = () => {
const [value, setValue] = useState('');
const [error, setError] = useState();
function validate() {
if (!isValidSsn(value)) {
e.preventDefault();
setError('You have entered an invalid SSN.');
}
}
return (
<form onSubmit={validate}>
{error && <Alert variation="error">{error}<Alert>}
<TextField
label="Social security number (SSN)"
labelMask={SSN_MASK}
name="ssn_example"
value={value}
onChange={setValue}
/>
<Button type="submit">Submit</Button>
</form>
)
};
Learn more
- labelmask, a blog post by Brad Frost - the inspiration for this component
Component maturity
For more information about how we tested and validated our work for each checklist item, read our component maturity documentation.