Our npm namespace has changed. Developers should update their projects to continue accessing our components.

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


Example of the features of a single task list row. Features include a task name, a status badge, and an optional hint label. The entire row should be clickable.

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

                                                                                                                                                                                             
StatusCSS Class NameUsage
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


Diagram shows a flow of a task list updating after each form page is completed and each form section is reviewed.
  1. 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.
  2. When the user clicks into an eligible task, they will be sent to the task form pages.
  3. 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.
  4. 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


Example of the features of an entire task list component. Features include a section heading, a task list title and a set of tasks.

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


A form section review screen featuring the user’s answers and a question asking if the user has completed this section using “yes” or “no” options.

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


A task in an error state. A page alert above the task list specifies the error, and accompanying text underneath the task name also specifies the error. The badge status is set to error.

When the user is ready to submit the form

Example


User flow demonstrates moving from a completed task list to the final form review screen., Then from the final form review screen to a confirmation screen.

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 by aria-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.