Task List
Show the user activities they have completed and what they have left to do.
-
Content:
@use 'sass:math'; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/spacing.variables' as spacing; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/colours.variables' as colours; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/2-tools/functions/global.functions' as globalFunctions; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/breakpoints.variables' as breakpoints; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/2-tools/placeholder/focus.placeholders' as placeholders; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/font-weights.variables' as fontWeights; @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/global.variables' as globalVariables; .ontario-task-list { border-top: globalFunctions.px-to-rem(2) solid colours.$ontario-greyscale-20; margin-left: spacing.$spacing-0; padding: spacing.$spacing-0; max-width: 48rem; li:last-child { padding-bottom: globalFunctions.px-to-rem(19); } } .ontario-task { border-bottom: globalFunctions.px-to-rem(2) solid colours.$ontario-greyscale-20; padding: globalFunctions.px-to-rem(19) spacing.$spacing-0; list-style: none; &__content { display: flex; justify-content: space-between; align-items: center; @media screen and (max-width: breakpoints.$small-breakpoint) { display: flex; flex-direction: column; align-items: flex-start; } } &__label { text-align: left; margin: spacing.$spacing-0; font-size: globalFunctions.px-to-rem(19); font-weight: fontWeights.$ontario-font-weights-semi-bold; display: inline-block; @media screen and (max-width: breakpoints.$small-breakpoint) { margin-bottom: spacing.$spacing-2; } a { text-decoration: none; color: inherit; &:hover { text-decoration: underline; } } } &__link { display: block; text-decoration: none; color: colours.$ontario-colour-link; font-weight: normal; } &__hint-text--true { margin-bottom: spacing.$spacing-2; } &--error { padding-left: spacing.$spacing-4; border-left: globalFunctions.px-to-rem(4) solid colours.$ontario-colour-alert; margin-left: globalFunctions.px-to-rem(-2); } .ontario-hint { margin-bottom: spacing.$spacing-0; @media screen and (max-width: breakpoints.$small-breakpoint) { margin-top: spacing.$spacing-2; } } } .ontario-task__link { .ontario-task__label { text-decoration: underline; } } .ontario-task__link:focus { outline: none; box-shadow: none; .ontario-task__label { @extend %ontario-focus; box-shadow: 0 0 0 4px colours.$ontario-colour-focus inset; } } .ontario-task:has(.ontario-task__link) { &:hover { background-color: colours.$ontario-greyscale-5; } } @mixin link-states { &:visited .ontario-task__label { color: colours.$ontario-colour-link--visited; } &:hover .ontario-task__label { color: colours.$ontario-colour-link--hover; } &:active .ontario-task__label { color: colours.$ontario-colour-link--active; } } .ontario-task { &--status-completed, &--status-inprogress, &--status-notstarted, &--status-optional, &--status-error { .ontario-task__link { .ontario-task__label { color: colours.$ontario-colour-link; text-decoration: underline; } @include link-states; } } } .ontario-badge { text-decoration: none; .ontario-task-status--not-started & { background-color: colours.$ontario-colour-information-light; } .ontario-task-status--in-progress & { background-color: colours.$ontario-colour-information; color: colours.$ontario-colour-white; } .ontario-task-status--error & { background-color: colours.$ontario-colour-alert; color: colours.$ontario-colour-white; } .ontario-task-status--complete & { background-color: colours.$ontario-colour-white; border: globalFunctions.px-to-rem(1) solid colours.$ontario-greyscale-70; } .ontario-task-status--optional & { background-color: colours.$ontario-greyscale-5; } .ontario-task-status--cannot-start-yet & { background-color: colours.$ontario-greyscale-20; } }
- URL: /components/raw/task-list/task-list.scss
- Filesystem Path: fractal/components/components/task-list/task-list.scss
- Size: 4.1 KB
-
Content:
.ontario-task__link:focus .ontario-task__label{box-shadow:0 0 0 4px #009adb;outline:4px solid transparent;transition:box-shadow .1s ease-in-out}.ontario-task-list{border-top:.125rem solid #ccc;margin-left:0;padding:0;max-width:48rem}.ontario-task-list li:last-child{padding-bottom:1.1875rem}.ontario-task{border-bottom:.125rem solid #ccc;padding:1.1875rem 0;list-style:none}.ontario-task__content{display:flex;justify-content:space-between;align-items:center}@media screen and (max-width: 40em){.ontario-task__content{display:flex;flex-direction:column;align-items:flex-start}}.ontario-task__label{text-align:left;margin:0;font-size:1.1875rem;font-weight:600;display:inline-block}@media screen and (max-width: 40em){.ontario-task__label{margin-bottom:.5rem}}.ontario-task__label a{text-decoration:none;color:inherit}.ontario-task__label a:hover{text-decoration:underline}.ontario-task__link{display:block;text-decoration:none;color:#06c;font-weight:normal}.ontario-task__hint-text--true{margin-bottom:.5rem}.ontario-task--error{padding-left:1rem;border-left:.25rem solid #cd0000;margin-left:-0.125rem}.ontario-task .ontario-hint{margin-bottom:0}@media screen and (max-width: 40em){.ontario-task .ontario-hint{margin-top:.5rem}}.ontario-task__link .ontario-task__label{text-decoration:underline}.ontario-task__link:focus{outline:none;box-shadow:none}.ontario-task__link:focus .ontario-task__label{box-shadow:0 0 0 4px #009adb inset}.ontario-task:has(.ontario-task__link):hover{background-color:#f2f2f2}.ontario-task--status-completed .ontario-task__link .ontario-task__label,.ontario-task--status-inprogress .ontario-task__link .ontario-task__label,.ontario-task--status-notstarted .ontario-task__link .ontario-task__label,.ontario-task--status-optional .ontario-task__link .ontario-task__label,.ontario-task--status-error .ontario-task__link .ontario-task__label{color:#06c;text-decoration:underline}.ontario-task--status-completed .ontario-task__link:visited .ontario-task__label,.ontario-task--status-inprogress .ontario-task__link:visited .ontario-task__label,.ontario-task--status-notstarted .ontario-task__link:visited .ontario-task__label,.ontario-task--status-optional .ontario-task__link:visited .ontario-task__label,.ontario-task--status-error .ontario-task__link:visited .ontario-task__label{color:#551a8b}.ontario-task--status-completed .ontario-task__link:hover .ontario-task__label,.ontario-task--status-inprogress .ontario-task__link:hover .ontario-task__label,.ontario-task--status-notstarted .ontario-task__link:hover .ontario-task__label,.ontario-task--status-optional .ontario-task__link:hover .ontario-task__label,.ontario-task--status-error .ontario-task__link:hover .ontario-task__label{color:#00478f}.ontario-task--status-completed .ontario-task__link:active .ontario-task__label,.ontario-task--status-inprogress .ontario-task__link:active .ontario-task__label,.ontario-task--status-notstarted .ontario-task__link:active .ontario-task__label,.ontario-task--status-optional .ontario-task__link:active .ontario-task__label,.ontario-task--status-error .ontario-task__link:active .ontario-task__label{color:#002142}.ontario-badge{text-decoration:none}.ontario-task-status--not-started .ontario-badge{background-color:#e2f0f4}.ontario-task-status--in-progress .ontario-badge{background-color:#1080a6;color:#fff}.ontario-task-status--error .ontario-badge{background-color:#cd0000;color:#fff}.ontario-task-status--complete .ontario-badge{background-color:#fff;border:.0625rem solid #4d4d4d}.ontario-task-status--optional .ontario-badge{background-color:#f2f2f2}.ontario-task-status--cannot-start-yet .ontario-badge{background-color:#ccc}
- URL: /components/raw/task-list/task-list.css
- Filesystem Path: fractal/components/components/task-list/task-list.css
- Size: 3.7 KB
Guiding principle: Design for everyone.
About this component
The task list is a way to display a collection of steps. It appears at the beginning of a complex form/application process to help users understand:
- the steps required to complete the form
- track completed and pending tasks
- follow a required order for certain tasks
Each task clearly sets expectations and breaks the process into manageable steps, allowing users to focus on one section at a time.
The task list serves as:
- a “home page” that the user returns to after they complete each task
- a way to navigate to specific sections of the form that may need to be updated, reviewed or completed later
When to use this component
Consider using a task list when a user:
- may need multiple sessions to complete a form
- needs flexibility to complete a task in their preferred order
- would need to know all of the sections in advance (for example, to prepare users to gather the information they need ahead of time)
When not to use this component
Best practice: Try to simplify the service before you use a task list
For common forms which follow a linear process, a task list is typically not required.
For a lengthy, multi-step form, use a step indicator to indicate progress.
Component features
Example
Task name
The tasks should be short and descriptive to help users understand the activity involved to complete the task.
Optional hint
Hints provide more information about what the task involves. Use brief, single sentences so they are easier to navigate for screen reader users.
Status badge
Status badges give users a quick overview of what state they’re in. Each task should have a status badge to help users understand their progress.
Available statuses
Status | CSS Class Name | Usage |
---|---|---|
Not started | `ontario-task-status--not-started` | Tasks ready to be started |
In progress | `ontario-task-status--in-progress` | Tasks that have been started but have not been completed |
Completed | `ontario-task-status--completed` | Completed tasks |
Cannot start yet | `ontario-task-status--cannot-start-yet` | Tasks that require other tasks to be completed first |
Optional | `ontario-task-status--optional` | Tasks that are optional |
Error | `ontario-task-status--error` | Task errors that occur after they are completed |
Note: It’s required to assign the appropriate status class name to the <li class="ontario-task">
element. This ensures that the corresponding badge color is applied, as defined in our CSS.
How it works
General overview
Example
- Introduce users to the task list at the beginning of a complex form/application process. The initial view (“home page”) should show all the steps and their statuses.
- When the user clicks into an eligible task, they will be sent to the task form pages.
- Once the user reaches the end of the form, best practice is to have a form section review page and to let the user decide when a task is complete.
- The user should be brought back to the task list home page once completed and the task list statuses should be updated.
Task list considerations
Task order
The order that tasks and steps appear should be based on what makes sense for the application. For example, you could use the first task to ask eligibility questions to filter out or pre-screen users.
Users typically follow the presented order, so number tasks if a specific sequence is required.
Where possible, let the user complete tasks in any order, so that they can complete sections in their preferred order.
Grouping tasks
To improve the user experience, divide the form into smaller tasks to help make the process more manageable. This helps them progress through the form in stages.
Group the tasks into separate lists and place each one under a heading.
Example
Let the user decide when a task is complete
Sometimes it is helpful to let the user indicate when they have finished each task. You can do this by adding a required question that asks if they have completed a section.
Example
Marking tasks that are in progress
A task should have the “In progress” status badge if a user:
- begins a task but does not complete it (by accidentally or intentionally leaving a page)
- marks their task as still in progress in the review section
Best practice: answers left by the user in the form are saved. Refer to the saving data section for more details.
Errors
Some cases need an error state for a task.
For example: “The information entered does not match, please revisit the error labelled sections.”
Use an error badge and pair it with a page alert at the top of the page to direct users to the task that needs correction.
Example
When the user is ready to submit the form
Example
Once all eligible tasks are complete, allow the user to submit the form with a submission button. If a user attempts to review and submit an incomplete form, flag and link to the missing sections with a page alert.
Upon submission, the page should load a final form review so users can verify and/or change their responses before submitting their application.
A confirmation screen should be shown once the entire application has been submitted.
Technical Specifications
Accessibility
It’s essential to follow specific accessibility requirements to ensure a seamless experience for all.
Semantic HTML considerations
List-item element
Each task is wrapped in an <li>
tag with role="group"
, signaling to assistive technologies that the content is part of a larger set, such as a task list.
-
aria-labelledby
: Must reference the id of the heading element (task label) to ensure a clear relationship. -
aria-describedby
: Should reference the id of the hint text<p>
element if provided.
Task name
The main task name is represented with a heading element. This ensures semantic hierarchy and provides a descriptive label for screen readers.
- Add an
id
to the heading (e.g.,task-label
) so it can be referenced byaria-labelledby
in the<li>
.
Task status
The task’s current status is displayed inside a <div>
with role="status"
. This announces dynamic status updates to assistive technologies.
- The
aria-label
on the status badge must include a descriptive text (e.g., “Task status: In Progress”).
Saving data
When implementing auto-save in task list components, consider this flexible approach following general recommendations to balance functionality, user experience, and security (depending on your specific use case).
For logged-in users,
Best practice:
- Autosaving securely saves progress by linking data to accounts. Regular saves prevent data loss, and encryption keeps information safe.
- Offering a manual save option gives users control, while versioning allows them to restore previous states.
- Sessions should expire after inactivity to protect user data. Autosaving can also update statuses in the task list.
For anonymous users,
Best practice:
- Use sessionStorage to temporarily store progress, as it clears when the browser is closed.
- Avoid localStorage for sensitive data to reduce security risks. If server-side saving is needed, anonymize data and use expiring session tokens.
- Clearly notify users about autosaving, minimize stored data, handle errors effectively, and meet compliance with privacy laws.
If you have any questions or feedback, please get in touch.