Ask users for Durations
Overview
This pattern should be used when you need to collect a duration from a user such as asking how long someone has lived at an address.
How to use this pattern
Duration inputs can be created by using the duration component. For example:
Example Duration contents
Nunjucks
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}
{%
call onsQuestion({
"title": "How long have you lived at this address?",
"description": "<p>Enter “0” into the years field if you have lived at this address for less than a year</p>",
"legendIsQuestionTitle": true
})
%}
{{
onsDuration({
"id": "address-duration-example",
"dontWrap": true,
"field1": {
"id": "address-duration-years-example",
"name": "address-duration-years",
"suffix": {
"text": "Years",
"id": "address-duration-years-suffix-example"
},
"attributes": {
"autocomplete": "off"
}
},
"field2": {
"id": "address-duration-months-example",
"name": "address-duration-months",
"suffix": {
"text": "Months",
"id": "address-duration-months-suffix-example"
},
"attributes": {
"autocomplete": "off"
}
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
field1 | Object<DurationField> | true | Settings for the first duration field |
field2 | Object<DurationField> | false | Settings for the second duration field |
id | string | false | The HTML id attribute for the field. Applied if only a single field is used |
dontWrap | boolean | false | Prevents the date inputs from being wrapped in the fieldset component |
legendIsQuestionTitle | boolean | false | Creates an h1 inside the legend. Use when the duration is the only fieldset on the page |
mutuallyExclusive | MutuallyExclusive (ref) | false | Settings object if the duration is a mutually exclusive answer |
legendOrLabel | string | true | Text content for the <legend> . If only a single field is used, a <label> is created using the value from this parameter |
legendClasses | string | false | Classes for the <legend> |
description | string | false | The hint text for the duration fields |
error | Error (ref) | false | Settings for validation errors for the whole component |
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id attribute for the input |
name | string | false | The HTML name attribute for the input |
value | string | false | The HTML value for the input to set a preset value for the field |
suffix | object <InputSuffix> | true | Settings for the input suffix |
attributes | object | false | HTML attributes (for example, data attributes) to add to the element |
error | boolean | false | If set to true will style this specific field as if it has an error |
Name | Type | Required | Description |
---|---|---|---|
text | string | true | The visible text label for the prefix or suffix, for example, “Minutes“ |
title | string | false | The HTML title attribute for the <abbr> element, required if the visible text label is an abbreviation. Use to write out the long form of an abbreviated prefix or suffix. For example, if text is “mins”, title should be “Minutes”. |
id | string | true | The HTML id of the element used for the prefix or suffix. Used for the input’s aria-labelledby attribute. |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend aria-describedBy="legend-description"
class="ons-fieldset__legend ons-u-mb-no ons-fieldset__legend--with-description">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">How long have you lived at this address?</h1>
</legend>
<div id="legend-description" class="ons-fieldset__description ons-fieldset__description--title ons-u-mb-l">
<p>Enter “0” into the years field if you have lived at this address for less than a year</p>
</div>
<div class="ons-input-items">
<div class="ons-field-group">
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="address-duration-years-example"
class="ons-input ons-input--text ons-input-type__input ons-input-number--w-2"
aria-labelledby="address-duration-years-suffix-example"
aria-labelledby="address-duration-years-example address-duration-years-suffix-example"
name="address-duration-years" pattern="[0-9]*" inputmode="numeric" autocomplete="off" />
<span id="address-duration-years-suffix-example" class="ons-input-type__type ons-js-input-abbr"
aria-label="" role="figure">Years</span>
</span>
</span>
</div>
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="address-duration-months-example"
class="ons-input ons-input--text ons-input-type__input ons-input-number--w-2"
aria-labelledby="address-duration-months-suffix-example"
aria-labelledby="address-duration-months-example address-duration-months-suffix-example"
name="address-duration-months" pattern="[0-9]*" inputmode="numeric" autocomplete="off" />
<span id="address-duration-months-suffix-example" class="ons-input-type__type ons-js-input-abbr"
aria-label="" role="figure">Months</span>
</span>
</span>
</div>
</div>
</div>
</fieldset>
</div>
</div>
How to check durations
To help users enter a valid duration, you should:
- check they have entered something in the duration fields
- check that what they have entered is valid
- show an error message if they have not entered anything in one of the fields or what they have entered is not valid
Error messages
Use the correct errors pattern and show the error details above the duration fields.
Example Duration Error contents
Nunjucks
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}
{{
onsDuration({
"id": "address-duration-error-example",
"legendOrLabel": 'How long have you lived at this address?',
"legendClasses": 'ons-u-vh',
"field1": {
"id": "address-duration-years-error-example",
"name": "address-duration-years",
"suffix": {
"text": "Years",
"id": "address-duration-years-suffix-error-example"
}
},
"field2": {
"id": "address-duration-months-error-example",
"name": "address-duration-months",
"suffix": {
"text": "Months",
"id": "address-duration-months-suffix-error-example"
}
},
"error": {
"id": "address-duration-error-example",
"text": "Enter how long you have lived at this address"
}
})
}}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
field1 | Object<DurationField> | true | Settings for the first duration field |
field2 | Object<DurationField> | false | Settings for the second duration field |
id | string | false | The HTML id attribute for the field. Applied if only a single field is used |
dontWrap | boolean | false | Prevents the date inputs from being wrapped in the fieldset component |
legendIsQuestionTitle | boolean | false | Creates an h1 inside the legend. Use when the duration is the only fieldset on the page |
mutuallyExclusive | MutuallyExclusive (ref) | false | Settings object if the duration is a mutually exclusive answer |
legendOrLabel | string | true | Text content for the <legend> . If only a single field is used, a <label> is created using the value from this parameter |
legendClasses | string | false | Classes for the <legend> |
description | string | false | The hint text for the duration fields |
error | Error (ref) | false | Settings for validation errors for the whole component |
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id attribute for the input |
name | string | false | The HTML name attribute for the input |
value | string | false | The HTML value for the input to set a preset value for the field |
suffix | object <InputSuffix> | true | Settings for the input suffix |
attributes | object | false | HTML attributes (for example, data attributes) to add to the element |
error | boolean | false | If set to true will style this specific field as if it has an error |
Name | Type | Required | Description |
---|---|---|---|
text | string | true | The visible text label for the prefix or suffix, for example, “Minutes“ |
title | string | false | The HTML title attribute for the <abbr> element, required if the visible text label is an abbreviation. Use to write out the long form of an abbreviated prefix or suffix. For example, if text is “mins”, title should be “Minutes”. |
id | string | true | The HTML id of the element used for the prefix or suffix. Used for the input’s aria-labelledby attribute. |
HTML
<div class="ons-panel ons-panel--error ons-panel--no-title" id="address-duration-error-example">
<span class="ons-panel__assistive-text ons-u-vh">Error: </span>
<div class="ons-panel__body">
<p class="ons-panel__error">
<strong>Enter how long you have lived at this address</strong>
</p>
<fieldset id="address-duration-error-example" class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-vh"><span class="ons-fieldset__legend-title ons-u-pb-no">How long have
you lived at this address?</span></legend>
<div class="ons-field-group">
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="address-duration-years-error-example"
class="ons-input ons-input--text ons-input-type__input ons-input--error ons-input-number--w-2"
aria-labelledby="address-duration-years-suffix-error-example"
aria-labelledby="address-duration-years-error-example address-duration-years-suffix-error-example"
name="address-duration-years" pattern="[0-9]*" inputmode="numeric" />
<span id="address-duration-years-suffix-error-example" class="ons-input-type__type ons-js-input-abbr"
aria-label="" role="figure">Years</span>
</span>
</span>
</div>
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="address-duration-months-error-example"
class="ons-input ons-input--text ons-input-type__input ons-input--error ons-input-number--w-2"
aria-labelledby="address-duration-months-suffix-error-example"
aria-labelledby="address-duration-months-error-example address-duration-months-suffix-error-example"
name="address-duration-months" pattern="[0-9]*" inputmode="numeric" />
<span id="address-duration-months-suffix-error-example" class="ons-input-type__type ons-js-input-abbr"
aria-label="" role="figure">Months</span>
</span>
</span>
</div>
</div>
</fieldset>
</div>
</div>
If only one of the duration fields is causing a validation error, you can add error styling to just that single field by setting the additional error
parameter.
Example Duration Error For Single Field contents
Nunjucks
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}
{{
onsDuration({
"id": "travel-time",
"legendOrLabel": 'How long do you spend travelling to and from work each day?',
"legendClasses": 'ons-u-vh',
"error": {
"text": "Enter a number of minutes that is less than 60",
"id": "duration-error"
},
"field1": {
"id": "travel-time-hours",
"name": "travel-time-hours",
"suffix": {
"text": "Hours",
"id": "address-time-hours-suffix"
},
"value": "2"
},
"field2": {
"id": "travel-time-minutes",
"name": "travel-time-minutes",
"suffix": {
"text": "Minutes",
"id": "address-time-minutes-suffix"
},
"value": "60",
"error": true
}
})
}}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
field1 | Object<DurationField> | true | Settings for the first duration field |
field2 | Object<DurationField> | false | Settings for the second duration field |
id | string | false | The HTML id attribute for the field. Applied if only a single field is used |
dontWrap | boolean | false | Prevents the date inputs from being wrapped in the fieldset component |
legendIsQuestionTitle | boolean | false | Creates an h1 inside the legend. Use when the duration is the only fieldset on the page |
mutuallyExclusive | MutuallyExclusive (ref) | false | Settings object if the duration is a mutually exclusive answer |
legendOrLabel | string | true | Text content for the <legend> . If only a single field is used, a <label> is created using the value from this parameter |
legendClasses | string | false | Classes for the <legend> |
description | string | false | The hint text for the duration fields |
error | Error (ref) | false | Settings for validation errors for the whole component |
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id attribute for the input |
name | string | false | The HTML name attribute for the input |
value | string | false | The HTML value for the input to set a preset value for the field |
suffix | object <InputSuffix> | true | Settings for the input suffix |
attributes | object | false | HTML attributes (for example, data attributes) to add to the element |
error | boolean | false | If set to true will style this specific field as if it has an error |
Name | Type | Required | Description |
---|---|---|---|
text | string | true | The visible text label for the prefix or suffix, for example, “Minutes“ |
title | string | false | The HTML title attribute for the <abbr> element, required if the visible text label is an abbreviation. Use to write out the long form of an abbreviated prefix or suffix. For example, if text is “mins”, title should be “Minutes”. |
id | string | true | The HTML id of the element used for the prefix or suffix. Used for the input’s aria-labelledby attribute. |
HTML
<div class="ons-panel ons-panel--error ons-panel--no-title" id="duration-error">
<span class="ons-panel__assistive-text ons-u-vh">Error: </span>
<div class="ons-panel__body">
<p class="ons-panel__error">
<strong>Enter a number of minutes that is less than 60</strong>
</p>
<fieldset id="travel-time" class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-vh"><span class="ons-fieldset__legend-title ons-u-pb-no">How long do you
spend travelling to and from work each day?</span></legend>
<div class="ons-field-group">
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="travel-time-hours"
class="ons-input ons-input--text ons-input-type__input ons-input-number--w-2"
aria-labelledby="address-time-hours-suffix"
aria-labelledby="travel-time-hours address-time-hours-suffix" name="travel-time-hours" value="2"
pattern="[0-9]*" inputmode="numeric" />
<span id="address-time-hours-suffix" class="ons-input-type__type ons-js-input-abbr" aria-label=""
role="figure">Hours</span>
</span>
</span>
</div>
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="travel-time-minutes"
class="ons-input ons-input--text ons-input-type__input ons-input--error ons-input-number--w-2"
aria-labelledby="address-time-minutes-suffix"
aria-labelledby="travel-time-minutes address-time-minutes-suffix" name="travel-time-minutes" value="60"
pattern="[0-9]*" inputmode="numeric" />
<span id="address-time-minutes-suffix" class="ons-input-type__type ons-js-input-abbr" aria-label=""
role="figure">Minutes</span>
</span>
</span>
</div>
</div>
</fieldset>
</div>
</div>
If all fields are empty
Use “Enter [whatever the duration is]”. For example, “Enter how long you have lived at this address”.
If one of the fields is empty
Use “Enter the number of [whatever the duration is]”.
For example, “Enter the number of years”.
If what is entered in one of the fields is not a number
Use “Enter a number for [invalid field], for example, [appropriate number]”.
For example, “Enter a number for months, for example, 7”.
If what is entered in a field is above the maximum value for that field
Use “Enter a number that is less than [whatever the maximum is for the duration]”.
For example, “Enter a number that is less than 12” for months.
Help improve this page
Let us know how we could improve this page, or share your user research findings. Discuss the ‘Durations’ pattern on GitHub (opens in a new tab)