Cookies on ons.gov.uk

Cookies are small files stored on your device when you visit a website. We use some essential cookies to make this website work.

We would like to set additional cookies to remember your settings and understand how you use the site. This helps us to improve our services.

You have accepted all additional cookies. You have rejected all additional cookies. You can change your cookie preferences at any time.

Skip to main content

Timeout modal

Overview

A timeout warning that lets users extend the amount of time they have to complete a task.

Example Timeout Modal contents

Nunjucks

{% from "components/timeout-modal/_macro.njk" import onsTimeoutModal %}

<div style="min-height:20rem;">
    {{
        onsTimeoutModal({
            "showModalTimeInSeconds": 60,
            "redirectUrl": "#!",
            "title": "You will be signed out soon",
            "textFirstLine": "It appears you have been inactive for a while.",
            "countdownText": "To protect your information, your progress will be saved and you will be signed out in",
            "countdownExpiredText": "You are being signed out.",
            "btnText": "Continue survey",
            "minutesTextSingular": "minute",
            "minutesTextPlural": "minutes",
            "secondsTextSingular": "second",
            "secondsTextPlural": "seconds",
            "endWithFullStop": true
        })
    }}
</div>

Nunjucks macro options

NameTypeRequiredDescription
showModalTimeInSecondsintegertrueNumber of seconds the modal will be displayed for
redirectUrlstringtrueThe URL to redirect to when session times out
sessionExpiresAtstringtrueInitial expiry time set by server on page load in ISO format
serverSessionExpiryEndpointstringtrueEndpoint to send requests to get or update the expiry time
titlestringtrueTitle text for the <h1> heading for the modal. Used by the aria-labelledby attribute on the <dialog> element.
textFirstLinestringtrueFirst paragraph of content in the modal’s body, for example “It appears you have been inactive for a while.”
countdownTextstringtrueThe leading line of text to prefix the countdown timer, for example “To protect your information, your progress will be saved and you will be signed out in 59 seconds.”.
countdownExpiredTextstringtrueText briefly displayed after countdown timer ends and redirect is taking place, for example, “You are being signed out”.
btnTextstringtrueThe text label for the primary button for the timeout modal, for example, “Continue survey”.
minutesTextSingularstringtrueTime unit displayed in countdown timer when between 1 and 2 minutes is remaining, for example “1 minute 59 seconds”.
minutesTextPluralstringtrueTime unit displayed in countdown timer when more than 1 minutes are remaining, for example “2 minutes 59 seconds”.
secondsTextSingularstringtrueTime unit displayed in countdown timer when the number of seconds remaining equals 1, for example “2 minutes 1 second”.
secondsTextPluralstringtrueTime unit displayed in countdown timer when more than 1 seconds are remaining, for example “1 minute 59 seconds”.
endWithFullStopbooleanfalseSet to “true” to end the countdown timer text with full stop

HTML

<div style="min-height:20rem;">
  <dialog class="ons-modal ons-js-modal ons-js-timeout-modal" id="dialog" role="dialog"
    aria-labelledby="ons-modal-title" data-redirect-url="#!" data-server-session-expires-at="" data-show-modal-time="60"
    data-server-session-expiry-endpoint=""
    data-countdown-text="To protect your information, your progress will be saved and you will be signed out in"
    data-countdown-expired-text="You are being signed out." data-minutes-text-singular="minute"
    data-minutes-text-plural="minutes" data-seconds-text-singular="second" data-seconds-text-plural="seconds"
    data-full-stop="true" aria-describedby="timeout-time-remaining">
    <div class="ons-modal__content">
      <h2 id="ons-modal-title" class="ons-modal__title">You will be signed out soon</h2>
      <div class="ons-modal__body">
        <p>It appears you have been inactive for a while.</p>
        <p class="ons-js-timeout-timer" aria-hidden="true" aria-relevant="additions"></p>
        <p class="ons-js-timeout-timer-acc ons-u-vh" role="status" id="timeout-time-remaining"></p>
      </div>
      <button type="submit" class="ons-btn ons-js-modal-btn ons-u-mt-s">
        <span class="ons-btn__inner"><span class="ons-btn__text">Continue survey</span></span>
      </button>
    </div>
  </dialog>
</div>

When to use this component

Use this component when a service sets a session expiry time to protect the user’s information.

There is specific guidance on how to help users extend a session.

How to use this component

The content of the timeout modal is set using the parameters shown in the macro options table in the previous example.

You will also need to set the parameters:

  • showModalTimeInSeconds with the number of seconds the modal should show for before the session expiry time (this should be at least 60 seconds)
  • sessionExpiresAt with the current expiry time in ISO format on page load
  • serverSessionExpiryEndpoint with a relative url to the server’s API endpoint for the component to send requests to
  • redirectUrl with a url to the session timed out error page the user is directed to when the session has timed out

Server requirements

The timeout modal component requires an API endpoint that handles two request methods and returns a JSON object containing the key expires_at with a value for the session expiry time in ISO format.

1. A request to reset the expiry time

When a request using a PATCH method is received the session expiry time should be reset to the original session length from the current time, and the response should contain the new expiry time.

A request to reset the expiry time will be sent when:

  • the modal is closed by the user
  • the user interacts with the page in any way, for example, by moving the cursor

To efficiently handle the number of requests made when the user interacts with the page, the requests are "throttled" so only one is sent every minute, and others in the queue are cleared.

2. A request for the current expiry time

When a request using a GET method is received, the response should contain the current expiry time.

The request is made to check if the same session is being interacted with in another tab. If the expiry time has changed, the timeout will be restarted against the expiry time in the response.

A request to get the current expiry time will be sent when the following happens:

  • before the modal opens
  • at 20-second intervals while the modal is open

Failure responses from the server

If the response status does not have a successful 200 code, the component will handle the response as a session expiry and redirect the user to the url set in the redirectUrl parameter.

Accessibility

This component helps services meet WCAG 2.1 success criterion 2.2.1 (Timing Adjustable). This requires services to warn users before a timeout occurs and allow them to extend it.

This component and it's accessibility features are based on the GDS timeout modal prototype and research (opens in a new tab)  . We will be carrying out our own accessibility testing to validate it.

Accessibility requirements

The WCAG guidelines state:

  • there should be no limit to the number of times a user can extend their session
  • the timeout modal should announce the remaining time at appropriate intervals to assistive technology
  • when the modal is closed the previously focused element on the page must be put back in focus

Accessibility attributes on the component’s elements

ElementAttribute and valueDescription
<dialog>aria-labelledby=”ons-modal-title”To make the contained heading be read out as the title of the modal
<dialog>role="dialog"Makes sure the modal is backwards compatible if the screen reader does not support the html element
<dialog>aria-describedby="timeout-time-remaining"Reads out the live timer at 15-second intervals
Countdown timeraria-hidden="true"Visible countdown timer is hidden from screen readers because it would be too interruptive
Countdown timeraria-relevant=”additions”A workaround for aria-hidden for unsupported JAWS screen reader versions 17 and 18
Hidden interval timerrole="status"To make sure the hidden interval timer is read out for iOS
Hidden interval timeraria-live="polite"To make sure the hidden interval timer does not interrupt other content being read out

Google analytics

Optionally pass event tracking data attributes for Google Analytics by providing enableGA: true. Data attributes will be dynamically set for the following events:

  • When the modal opens via timed or click event
  • When the modal is closed via timed or click event
  • When the modal is closed via Escape keypress

The following attributes will be set

  • data-ga-category="{modalType} modal"
  • data-ga-action="Modal {action} by {eventType}"
  • data-ga-label="{modalType} modal {action}"

Help improve this page

Let us know how we could improve this page, or share your user research findings. Discuss the ‘Timeout modal’ component on GitHub (opens in a new tab)