Question

Demonstration

Enter your email address and we can send you a link to this page to help you get back to it when you’re ready.

Code

Questions request information from a user to guide them into completing a form. This pattern follows the usage guidelines of the U.S. Web Design System (USWDS) Form Component. Forms use different types of questions to gather specific pieces of information. These usually correlate with native form element input types such as text or radio buttons. However, differing native form elements may be used or combined to collect specific types of information.

Below are common Opportunity Standard Questions, interpreting or extending the guidance from their counterparts in the USWDS. Guidance to inform additional scenarios can be found on the USWDS site.

General Question

The General Question collects text-based information such as numbers, emails, phone numbers, or long-form content. The appropriate input type and validation pattern attributes should be set based on the requested information type.


The label element should be used for the question and tied to the input using its id attribute. Further guidance on text inputs can be found on the USWDS site .


The inputmode attribute can be set to an appropriate value to display a virtual keyboard suggesting the data input. Further guidance on the inputmode attribute can be found MDN Web Docs.

Validation and Accessibility

Proper markup and aria labeling are required for elements within the question component. While they may appear similar stylistically, there is a difference in the markup between questions with one or multiple inputs. Proper id, name, and aria attributes are also required for labels, option inputs, SVG icons, and validation messages.


Questions use validation from the Patterns Scripts utility library. This script will display visual feedback regarding missing or invalid answers and toggle appropriate aria attributes for announcing feedback to screen readers. The aria-live="polite" attribute on the message declares error messages that are not visible in the default state. Additionally, the aria-invalid="true" attribute illustrates to screen readers that the input is not valid, and the aria-describedby attribute indicates the input’s error description.


Validation occurs on the blur event or when the user shifts focus away from the input.


The Form Utility uses the Constraint Validation API to assess validity based on the input attributes required and pattern. If any validity constraints are not met, then the localized validationMessage is displayed. Examples include “This field is required” or “Please provide a valid …”

Demonstration
Which of the following options applies best to you?

Please choose one of the options below.

Code

The Radio Question collects a single input from a short, predefined list of options. Options can be displayed in a single or double column, depending on the length of the option label. Use the c-question__container-cols class on the c-question__container element to display a two-column layout for desktop browsers.


If the list of options is long and can’t be truncated visually, the Select Question should be used instead.


Option Questions use the fieldset and legend element combination to group the available options; the question is wrapped in a fieldset element, while the question label uses the legend element.

Further guidance can be found on the USWDS site .

Demonstration
Which of the following options applies best to you?

Feel free to choose as many as you like.

Code

The Checkbox Question collects multiple inputs from a predefined list of options. Options can be displayed in a single or double column, depending on the length of the option label. Use the c-question__container-cols class on the c-question__container element to display a two-column layout for desktop browsers.


Option Questions use the fieldset and legend element combination to group the available options.


Further guidance can be found on the USWDS site .

Demonstration
Which of the following options applies best to you?

Feel free to choose as many as you like.

Code

Use the c-question__container-rows class to display a single column of options that span the full width of the parent container.

Demonstration
Do you have an income?

This includes money from jobs, alimony, investments, or gifts.

Code

The Toggle Question collects input such as yes or no, true or false, or another binary set of options.


Toggle Questions use the fieldset and legend element combination to group the available options.

Demonstration

Answer the best you can. You will be able to include additional types of income. The more you include, the more accurate your results will be.

Code

The Select Question collects a single input from a long, predefined list of options. The Checkbox Option Question or Radio Option Question is preferred for short lists of options. For binary options (yes or no, true or false) use the Toggle Question.

Further guidance can be found on the USWDS site .

Demonstration

Many benefit programs are meant for people of a specific age group. Sharing your age will help us choose the programs that will be most helpful to you right now. The information you share for the purposes of public benefits screening will be anonymous.

Code

While a visible inline description is preferred, the Popover can be used to provide additional information or context about the question without a fully visible paragraph description after the label.

Demonstration

Enter a 10-digit, U.S. only phone number and we can send you a link to this page to help you get back to it when you’re ready.

Please include your case number which appears in the format CL-###### in your application documents. Enter the number
without the CL prefix.

Code

Questions with a common and recognizable prefix can help users more quickly infer the required input type or format. The prefix should not interfere with the user’s ability to access the input.


Icons can also be used to prefix questions, such as using the User Interface (UI) Icon set dollar sign or calendar icons. More examples can be found on the Input with Prefix or Suffix example.


Input Masks are recommended to help users type commonly formatted types such as telephone numbers, following guidance from the U.S. Web Design System’s Input Mask. The open source library Cleave.js is included as a dependency of the Opportunity Standard to provide input masking support.


Further guidance on prefixed inputs can be found on the USWDS site .

Demonstration
Code

Monetary Questions may be aligned to the end of the input. The US dollar sign may be a UI icon prefix or a masked element (auto-formatting the input as the user types) inputs as it may reside in the text field and inherit the input’s alignment.


The field should should only permit entering numbers. The inputmode attribute can be set to decimal to display a number pad for virtual keyboards.


It is recommended to add input masking to automatically format the input as the user types, adding the decimal with cents and commas for values greater than or equal to 1,000.

Demonstration

Use the format month, day, year or mm/dd/yyyy.

Code

The Date Question uses a date type input element to provide a native date picker. Date pickers are best used for scheduling or choosing other unfamiliar dates.


Further guidance on date input and date pickers can be found on the USWDS site .

Demonstration

Select a month and enter the day (dd) and year (yyyy).

Code

Guidance on memorable date pickers can be found on the USWDS site .

Demonstration
Code
Global Script

Forms require JavaScript for validation and accessibility. To use validation through the global script use the following code. An optional selector targeting the form may be supplied as the first argument to the .validate() method. The second optional argument is a function that handles the form data after it passes validation.

<form data-js="validate" action="/my/action/" method="post">
  <!-- Form questions here -->
</form>

<script src="@nycopportunity/standard/dist/js/default.js"></script>

<script>
  var Standard = new Default();

  Standard.validate();

  // or

  // Accepts a selector string (argument one) and function (argument two) for submission handling
  Standard.validate('[data-js="validate"]', function(event) {
    event.preventDefault();

    // Add your own custom submission handler here
  });
</script>

Validation messages will appear when the user…

  • leaves a required question blank,

  • enters an answer doesn’t match the specified input type,

  • enters an answer that does not match a specified pattern,

  • or tries to submit the form without filling out any required fields.

For any of these conditions to be met…

Module Import

The form validation source exists in the Patterns Scripts utility library. Install the @nycopportunity/pttrn-scripts module to import the module. This method allows the specification of watching for input errors on blur, setting the error container’s selector, and other customizations. Refer to the source for details.

import Forms from '@nycopportunity/patterns-scripts/src/forms/forms';

this.form = new Forms(document.querySelector('[data-js="validate"]'));

this.form.submit = (event) => {
  event.preventDefault();
  // Submission handler
};

this.form.selectors.ERROR_MESSAGE_PARENT = '.c-question__container';

this.form.watch();

The open source library Cleave.js is included as a dependency of the Opportunity Standard to provide input masking support.

Global Script

To initialize supported masking utilities for dollars and phone numbers from the global script use the following code:

<!-- Global Script -->
<script src="https://cdn.jsdelivr.net/gh/nycopportunity/standard@v0.0.20/dist/js/default.js"></script>

<script>
  var Standard = new Default();

  Standard.masks();
</script>
Module Import

For module imports, import the mask utilities from the source and instantiate masks for dollars and phone numbers

import MaskDollars from '@nycopportunity/standard/src/utilities/mask/mask-dollars.js';
import MaskPhone from '@nycopportunity/standard/src/utilities/mask/mask-phone.js';

new MaskDollars
new MaskPhone
Additional masking

To achieve additional masking support, import Cleave.js from the source and pass inputs to instances of Cleave and customize options.

import Cleave from 'cleave.js';

let inputs = document.querySelectorAll('[data-js="{{ MY_INPUT }}"]');

for (let i = 0; i < inputs.length; i++) {
  new Cleave(inputs[i], {
    // Custom Options
  });
}

More information can be found in the Cleave.js documentation.

Global Script

The Popover requires JavaScript for showing and hiding. To initialize the Popover and Disclaimer instances from the global script use the following code:

<!-- Global Script -->
<script src="https://cdn.jsdelivr.net/gh/nycopportunity/standard@v0.0.20/dist/js/default.js"></script>

<script>
  var Standard = new Default();

  Standard.popover();
</script>

This will attach event listeners for toggling the Popover.

Module Import

For module imports, import the Popover from the source. You must pass a DOM selection of each Popover to a new instance of the class. A selector reference is stored in the class.

import Popover from '@nycopportunity/standard/src/components/popover/popover';

let elements = document.querySelectorAll(Popover.selector);

elements.forEach(element => {
  new Popover(element);
});