name: Step by step navigation description: A series of expanding/collapsing steps designed to navigate a user through a process body: | Step by step navigations show a sequence of steps towards a specific goal, such as 'learning to drive'. Each step can contain one or more links to pages. User research suggested that each step should be collapsed by default so that users are not overwhelmed with information. If JavaScript is disabled the step by step navigation expands fully. All of the functionality (including the icons and aria attributes) are added using JavaScript. This component is based on the accordion component in collections, but has been altered. This is for two reasons. - step by step navigations are needed throughout GOV.UK and extending the accordion to be this component would require it to be moved out of that application, which would break integration testing - creating a new component allows further iteration without impacting the accordion Background information relating to the testing and research behind this component can be found on the [Modelling Services wiki](https://gov-uk.atlassian.net/wiki/spaces/MS/pages) in Q2 to Q4, 2017/18. accessibility_criteria: | The step by step navigation must: - indicate to users that each step can be expanded and collapsed - inform the user when a step has been expanded or collapsed - be usable with a keyboard - allow users to show or hide all steps at once - inform the user which step a link belongs to - inform the user which step the current page is in - be readable when only the text of the page is zoomed - achieved for the numbers and logic elements by their text being wrapped in several elements that give them a white background and ensure the text when zoomed expands to the left, not to the right, where it would obscure the step titles The show/hide all button only needs to list the first panel id in the aria-controls attribute, rather than all of them. Step headings must use a button element: - so that steps can be toggled with the space and enter keys - so that steps can't be opened in a new tab or window When JavaScript is unavailable the component must: - be fully expanded - not be marked as expandable shared_accessibility_criteria: - link examples: default: data: steps: [ { title: "Do a thing", contents: [ { type: 'paragraph', text: 'This is a paragraph of text.' }, { type: 'paragraph', text: 'This is also a paragraph of text that intentionally contains lots of words in order to fill the width of the page successfully to check layout and so forth.' } ] }, { title: "Do another thing", logic: "and", contents: [ { type: 'paragraph', text: 'Some more text.' }, ] }, { title: "Do something else", contents: [ { type: 'paragraph', text: 'This is yet another paragraph.' } ] } ] with_unique_tracking: description: | In order to identify the step by step navigation the component is part of, we need to track a unique ID of the navigation in Google Analytics. This ID should be the same across all pages that are linked from and are part of that navigation. Its value is included in any tracking events, specifically in dimension96. It refers to the ID of the step nav page. This includes show/hide all, show/hide step and any link clicks. data: tracking_id: 'this-is-the-tracking-id' steps: [ { title: 'Unique tracking id', contents: [ { type: 'list', contents: [ { href: '#', text: 'This is a link' } ] } ] } ] with_a_different_heading_level: description: Steps have a H2 by default, but this can be changed. The heading level does not change any styling. data: heading_level: 3 steps: [ { title: 'This is a heading 3', contents: [ { type: 'paragraph', text: 'This is yet another paragraph.' } ] }, { title: 'This is also a heading 3', contents: [ { type: 'paragraph', text: 'This is yet another paragraph.' } ] } ] open_a_step_by_default: description: Pass the index of the step to open by default. This is the nth step in the list, regardless of the number shown next to the step. Note that in the example below, the third step is open by default, not the step numbered '3'. data: show_step: 3 steps: [ { title: 'Closed by default', contents: [ { type: 'paragraph', text: 'Well, open now, obviously.' } ] }, { title: 'Also closed by default', contents: [ { type: 'paragraph', text: 'Hello.' } ] }, { title: 'Open by default', logic: "and", contents: [ { type: 'paragraph', text: 'Hello!' } ] }, { title: 'And again closed by default', contents: [ { type: 'paragraph', text: 'Goodbye...' } ] } ] remember_last_opened_step: description: | If steps are opened their IDs are added to an array in sessionStorage, so that if the user returns to this page in the same session, those steps will be opened on page load. This option can technically be used together with the option to open a step by default, but this is not recommended as it could confuse users. data: remember_last_step: true steps: [ { title: 'Remember this', contents: [ { type: 'paragraph', text: 'Hello!' } ] }, { title: 'Or this', contents: [ { type: 'paragraph', text: 'Hello!' } ] } ] with_links: description: | Links can have the following attributes: - style, an attribute on the parent list that controls its appearance. Defaults to optional but can be set to 'choice' (adds indent and bullets to the list) - context, an optional text field to show some extra information after the link, usually a monetary value - active, whether to make the link highlighted (to indicate the current page) - highlight_step, a general option to highlight the step. Usually the active link would be in the active step, but in some circumstances there might be an active step but no highlighted link. data: highlight_step: 2 show_step: 2 steps: [ { title: 'Links and paragraphs', contents: [ { type: 'paragraph', text: 'These links represent tasks that are required.' }, { type: 'paragraph', text: 'Spacing between a paragraph and a list of links should be smaller than the spacing between two paragraphs, in order to visually connect the two.' }, { type: 'list', contents: [ { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Obtain a driving licence prior to driving a car' }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Acquire food before attempting to cook', context: '1p to £20' }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Maintain contact with the ground at all times' } ] }, { type: 'paragraph', text: 'These links represent a choice:' }, { type: 'list', style: 'choice', contents: [ { href: '/component-guide/step_by_step_navigation/', text: 'Leave school at sixteen' }, { href: '/component-guide/step_by_step_navigation/', text: 'Continue into higher education', context: '£9,500' } ] } ] }, { title: 'Active step and links', contents: [ { type: 'list', contents: [ { href: '/component-guide/step_by_step_navigation/', text: 'Check the reasons' }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Make the decisions based on available data and the reasonable assumptions that are possible at the time', context: '1p to £20', active: true }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Do the things' } ] }, ] } ] or_then: description: Some of the more complex things in a step by step navigation require an option for laying out links in a clear structure. If a link in a list is not given a href, only the text is displayed, allowing for structures like the one shown below. data: show_step: 1 steps: [ { title: "Get a court to decide your child arrangements", contents: [ { type: 'paragraph', text: "You can only apply for a court to make a decision if you've tried mediation or your family are at risk, for example domestic abuse." }, { type: 'list', contents: [ { href: 'http://solicitors.lawsociety.org.uk/', text: 'Hire a lawyer to represent you', context: '£110 to £410 per hour' }, { text: 'or', }, { href: 'http://localhost:3000/represent-yourself-in-court', text: 'Represent yourself in court' } ] }, { type: 'paragraph', text: 'then' }, { type: 'list', contents: [ { href: '/looking-after-children-divorce/apply-for-court-order', text: 'Apply for a court order', context: '£215' }, { href: 'https://courttribunalfinder.service.gov.uk/search/', text: 'Find the right court to send your application' }, { href: '/get-help-with-court-fees', text: 'Get help with court fees' } ] }, { type: 'paragraph', text: "The court will send you a date for your first hearing 4 to 6 weeks after your application. You'll be told when and where your hearing will take place." } ] } ] solve_the_double_dot_problem: description: | As shown, options can be passed to the component to highlight one step, expand one step by default, and highlight multiple links. These options should only be used when the component is in the sidebar. The step that is highlighted and expanded will be referred to as the active step (even though they are separate options, it is assumed that they will normally be applied to the same step). If a link is in a step by step navigation more than once and the user is on that page, the backend doesn't know which link to highlight, so it highlights both of them. JavaScript is included in the component to solve this. It uses sessionStorage to capture the data-position attribute of non-external links when clicked, and then uses this value to decide which link to highlight after the new page loads. It uses the value of the tracking_id option to uniquely identify the current step nav in the session (if this is not passed to the component this may result in other step navs having the wrong link highlighted). If a user has not clicked a link (i.e. has visited the page without first clicking on a step by step navigation) only the first duplicate link will be highlighted. If that link is not in the active step, the JS makes the highlighted link's parent the active step. If there is no active step, the first active link will be highlighted (but there should always be an active step). The example below will show all non-external links highlighted if JS is disabled. In the real world no more than two or three links are likely to be highlighted at once. Changes to the active step and highlighted link are also applied on click, if the user clicks one of the other links that is to the same page (they are amended by the component to be jump links to the top of the page). Open this example using the 'preview' link and try clicking on the 'internal' links to see how it behaves. data: highlight_step: 2 show_step: 2 tracking_id: "example-id" steps: [ { title: "The active step", contents: [ { type: 'list', contents: [ { href: 'http://google.com', text: 'External link not set to active' }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Internal link set to active', active: true }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Internal link set to active', active: true }, { href: 'http://google.com', text: 'External link not set to active' } ] } ] }, { title: "Not the active step", contents: [ { type: 'list', contents: [ { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Internal link set to active - in the active step, should be set by default until another link is clicked', active: true }, { href: '/component-guide/step_by_step_navigation/with_links/preview', text: 'Internal link set to active', active: true }, { href: 'http://google.com', text: 'External link not set to active' } ] } ] } ] with_optional_steps: description: | Steps can be optional. This is controlled by two parameters, 'optional' and 'logic'. - Optional steps used to have a dotted line down the side but this was removed as it confused users. In some cases we may still need to record if a step is optional, so if this parameter is applied, GA tracking events will have 'optional' appended to the end of the eventLabel. - Logic will change the number next to a step to the word 'and' or the word 'or'. If a step is optional this should be conveyed by the text within that step. data: steps: [ { title: "Drive to work", contents: [ { type: paragraph, text: 'If you do not have a car, you will need to choose an alternative.' } ] }, { title: "Walk to work", optional: true, logic: 'or', contents: [ { type: 'paragraph', text: 'Walking is healthy but may not be practical where large distances are concerned.' } ] }, { title: "Get public transport to work", optional: true, logic: 'or', contents: [ { type: 'paragraph', text: 'Public transport includes buses, trains and boats.' } ] }, { title: "Do work", contents: [ { type: 'paragraph', text: 'Once you have reached your destination you should be able to start work.' } ] }, { title: "Get paid", logic: 'and', contents: [ { type: 'paragraph', text: 'Your employer should pay you for hours worked.' } ] } ] test_all_the_things: description: This component is very complicated so here is an example containing as many of the options available as possible. data: step_nav_url: "/learn-to-setup-standup" highlight_step: 3 steps: [ { title: 'Get the TV ready', contents: [ { type: 'paragraph', text: 'Configure the television so it is ready for the standup. You will also need a laptop.' }, { type: 'list', contents: [ { href: 'https://en.wikipedia.org/wiki/HDMI', text: 'Remove the Chromebit from HDMI 1 on the TV' } ] } ] }, { title: 'Plug everything in', logic: "and", contents: [ { type: 'paragraph', text: 'Connect the relevant cables between the various devices.' }, { type: 'list', contents: [ { href: 'https://www.google.co.uk/', text: 'Run the HDMI - MINI DVI cable from the TV to the facilitators laptop' }, { href: 'https://www.jabra.co.uk/', text: 'Plug the Jabra into the facilitators laptop' } ] } ] }, { title: 'Configure the catchbox', contents: [ { type: 'paragraph', text: 'These steps are required.' }, { type: 'list', contents: [ { href: 'http://www.google.com', text: 'Ensure the catchbox transmitter is plugged in at the mains wall' }, { href: 'http://www.google.com', text: 'Turn on the transmitter and wait for the switch to blink green' }, { href: 'http://www.google.com', text: 'Plug the transmitter USB cable into the facilitators laptop', active: true }, { href: 'http://www.google.com', text: 'Twist and pull the black piece of foam out of the catchbox' }, { href: 'http://www.google.com', text: 'Turn on the catchbox and wait for the LED to turn green' }, { href: 'http://www.google.com', text: 'Wait for the transmitter light to turn solid green' } ] }, { type: 'substep', optional: true, contents: [ { type: 'heading', text: 'Optional steps' }, { type: 'paragraph', text: 'These steps are not required.' }, { type: 'list', style: 'choice', contents: [ { href: 'https://www.google.co.uk/', text: "Get annoyed when it doesn't work" }, { href: 'http://www.google.com', text: 'Try to find someone else who knows how to do it', context: '1 to 10 minutes' } ] } ] } ] }, { title: 'Join and configure the standup', show_help_link: true, contents: [ { type: 'paragraph', text: 'Join the hangout and present to those on it.' }, { type: 'list', contents: [ { href: 'http://www.google.com', text: 'Connect to standup hangout via the calendar invite' }, { text: 'or' }, { href: 'http://www.google.com', text: 'Connect to standup hangout via the link in the team slack' } ] }, { type: 'paragraph', text: 'then' }, { type: 'list', contents: [ { href: 'http://www.google.com', text: 'Click the three dots in the bottom hand corner to open settings' }, { href: 'http://www.google.com', text: 'Set speaker to "Jabra"' }, { href: 'http://www.google.com', text: 'Set microphone to "C Media USB"' }, { href: 'http://www.google.com', text: 'Click "present to meeting"' }, ] } ] }, { title: 'Clear up', contents: [ { type: 'paragraph', text: 'Disconnect from the hangout and disconnect any cables.' }, { type: 'paragraph', text: 'Most importantly, remember to switch off the catchbox to save the battery.' } ] }, { title: 'Get someone else to clear up', logic: 'or', optional: true, contents: [ { type: 'paragraph', text: 'Schedule another meeting for right after the standup and force someone else to sort everything out.' } ] } ] small: description: Designed to fit in the sidebar of a page. Note that the small version of the component should not become smaller on mobile, and the large version on mobile should be the same size as the small version. This example is a copy of the one above for comparison. data: small: true remember_last_step: true step_nav_url: "/learn-to-setup-standup" highlight_step: 3 steps: [ { title: 'Get the TV ready (small)', contents: [ { type: 'paragraph', text: 'Configure the television so it is ready for the standup. You will also need a laptop.' }, { type: 'list', contents: [ { href: 'https://en.wikipedia.org/wiki/HDMI', text: 'Remove the Chromebit from HDMI 1 on the TV' } ] } ] }, { title: 'Plug everything in (small)', logic: "and", contents: [ { type: 'paragraph', text: 'Connect the relevant cables between the various devices.' }, { type: 'list', contents: [ { href: 'https://www.google.co.uk/', text: 'Run the HDMI - MINI DVI cable from the TV to the facilitators laptop' }, { href: 'https://www.jabra.co.uk/', text: 'Plug the Jabra into the facilitators laptop' } ] } ] }, { title: 'Configure the catchbox (small)', contents: [ { type: 'paragraph', text: 'These steps are required.' }, { type: 'list', contents: [ { href: 'http://www.google.com', text: 'Ensure the catchbox transmitter is plugged in at the mains wall' }, { href: 'http://www.google.com', text: 'Turn on the transmitter and wait for the switch to blink green' }, { href: 'http://www.google.com', text: 'Plug the transmitter USB cable into the facilitators laptop', active: true }, { href: 'http://www.google.com', text: 'Twist and pull the black piece of foam out of the catchbox' }, { href: 'http://www.google.com', text: 'Turn on the catchbox and wait for the LED to turn green' }, { href: 'http://www.google.com', text: 'Wait for the transmitter light to turn solid green' } ] }, { type: 'substep', optional: true, contents: [ { type: 'heading', text: 'Optional steps' }, { type: 'paragraph', text: 'These steps are not required.' }, { type: 'list', style: 'choice', contents: [ { href: 'https://www.google.co.uk/', text: "Get annoyed when it doesn't work" }, { href: 'http://www.google.com', text: 'Try to find someone else who knows how to do it', context: '1 to 10 minutes' } ] } ] } ] }, { title: 'Join and configure the standup (small)', show_help_link: true, contents: [ { type: 'paragraph', text: 'Join the hangout and present to those on it.' }, { type: 'list', contents: [ { href: 'http://www.google.com', text: 'Connect to standup hangout via the calendar invite' }, { text: 'or' }, { href: 'http://www.google.com', text: 'Connect to standup hangout via the link in the team slack' } ] }, { type: 'paragraph', text: 'then' }, { type: 'list', contents: [ { href: 'http://www.google.com', text: 'Click the three dots in the bottom hand corner to open settings' }, { href: 'http://www.google.com', text: 'Set speaker to "Jabra"' }, { href: 'http://www.google.com', text: 'Set microphone to "C Media USB"' }, { href: 'http://www.google.com', text: 'Click "present to meeting"' }, ] } ] }, { title: 'Clear up (small)', contents: [ { type: 'paragraph', text: 'Disconnect from the hangout and disconnect any cables.' }, { type: 'paragraph', text: 'Most importantly, remember to switch off the catchbox to save the battery.' } ] }, { title: 'Get someone else to clear up (small)', logic: 'or', optional: true, contents: [ { type: 'paragraph', text: 'Schedule another meeting for right after the standup and force someone else to sort everything out.' } ] } ]