govuk_publishing_components 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/Rakefile +1 -9
  4. data/app/assets/javascripts/components/task-list.js +471 -0
  5. data/app/assets/javascripts/current-location.js +10 -0
  6. data/app/assets/javascripts/govuk_publishing_components/application.js +4 -0
  7. data/app/assets/javascripts/history-support.js +8 -0
  8. data/app/assets/stylesheets/components/_task-list-header-print.scss +15 -0
  9. data/app/assets/stylesheets/components/_task-list-header.scss +36 -0
  10. data/app/assets/stylesheets/components/_task-list-print.scss +35 -0
  11. data/app/assets/stylesheets/components/_task-list-related.scss +39 -0
  12. data/app/assets/stylesheets/components/_task-list.scss +454 -0
  13. data/app/assets/stylesheets/govuk_publishing_components/application.scss +3 -0
  14. data/app/assets/stylesheets/govuk_publishing_components/print.scss +4 -0
  15. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +5 -0
  16. data/app/models/govuk_publishing_components/component_doc.rb +10 -3
  17. data/app/models/govuk_publishing_components/component_doc_resolver.rb +19 -5
  18. data/app/views/components/_task_list.html.erb +143 -0
  19. data/app/views/components/_task_list_header.html.erb +38 -0
  20. data/app/views/components/_task_list_related.html.erb +39 -0
  21. data/app/views/components/docs/task_list.yml +1032 -0
  22. data/app/views/components/docs/task_list_header.yml +33 -0
  23. data/app/views/components/docs/task_list_related.yml +54 -0
  24. data/app/views/govuk_publishing_components/component_guide/index.html.erb +14 -3
  25. data/app/views/govuk_publishing_components/component_guide/show.html.erb +1 -1
  26. data/app/views/layouts/govuk_publishing_components/application.html.erb +1 -4
  27. data/config/initializers/assets.rb +1 -0
  28. data/lib/govuk_publishing_components/config.rb +5 -1
  29. data/lib/govuk_publishing_components/version.rb +1 -1
  30. metadata +33 -3
@@ -3,6 +3,9 @@
3
3
  @import "grid_layout";
4
4
  @import "typography";
5
5
  @import "colours";
6
+ @import "../components/task-list";
7
+ @import "../components/task-list-header";
8
+ @import "../components/task-list-related";
6
9
 
7
10
  $border-color: #ccc;
8
11
 
@@ -0,0 +1,4 @@
1
+ @import "typography";
2
+
3
+ @import "../components/task-list-print";
4
+ @import "../components/task-list-header-print";
@@ -4,6 +4,7 @@ module GovukPublishingComponents
4
4
 
5
5
  def index
6
6
  @component_docs = component_documentation_resolver.all
7
+ @gem_component_docs = gem_component_documentation_resolver.all
7
8
  end
8
9
 
9
10
  def show
@@ -41,6 +42,10 @@ module GovukPublishingComponents
41
42
  @component_documentation_resolver ||= ComponentDocResolver.new
42
43
  end
43
44
 
45
+ def gem_component_documentation_resolver
46
+ @gem_component_documentation_resolver ||= ComponentDocResolver.new(gem_components: true)
47
+ end
48
+
44
49
  def index_breadcrumb
45
50
  {
46
51
  title: GovukPublishingComponents::Config.component_guide_title,
@@ -6,7 +6,8 @@ module GovukPublishingComponents
6
6
  :body,
7
7
  :accessibility_criteria,
8
8
  :accessibility_excluded_rules,
9
- :examples
9
+ :examples,
10
+ :source
10
11
 
11
12
  def initialize(
12
13
  id,
@@ -15,7 +16,8 @@ module GovukPublishingComponents
15
16
  body,
16
17
  accessibility_criteria,
17
18
  accessibility_excluded_rules,
18
- examples
19
+ examples,
20
+ source
19
21
  )
20
22
  @id = id
21
23
  @name = name
@@ -24,6 +26,7 @@ module GovukPublishingComponents
24
26
  @accessibility_criteria = accessibility_criteria
25
27
  @accessibility_excluded_rules = accessibility_excluded_rules
26
28
  @examples = examples
29
+ @source = source
27
30
  end
28
31
 
29
32
  def example
@@ -43,7 +46,11 @@ module GovukPublishingComponents
43
46
  end
44
47
 
45
48
  def partial_path
46
- "#{GovukPublishingComponents::Config.component_directory_name}/#{id}"
49
+ if source == 'gem'
50
+ "components/#{id}"
51
+ else
52
+ "#{GovukPublishingComponents::Config.component_directory_name}/#{id}"
53
+ end
47
54
  end
48
55
 
49
56
  private
@@ -1,5 +1,9 @@
1
1
  module GovukPublishingComponents
2
2
  class ComponentDocResolver
3
+ def initialize(gem_components: false)
4
+ @documentation_directory = gem_components ? gem_documentation_directory : app_documentation_directory
5
+ end
6
+
3
7
  def get(id)
4
8
  component = fetch_component_doc(id)
5
9
  build(component)
@@ -24,7 +28,8 @@ module GovukPublishingComponents
24
28
  component[:body],
25
29
  combined_accessibility_criteria(component),
26
30
  component[:accessibility_excluded_rules],
27
- examples
31
+ examples,
32
+ component[:source],
28
33
  )
29
34
  end
30
35
 
@@ -40,21 +45,30 @@ module GovukPublishingComponents
40
45
  end
41
46
 
42
47
  def fetch_component_docs
43
- doc_files = Rails.root.join(documentation_directory, "*.yml")
48
+ doc_files = Rails.root.join(@documentation_directory, "*.yml")
44
49
  Dir[doc_files].sort.map { |file| parse_documentation(file) }
45
50
  end
46
51
 
47
52
  def fetch_component_doc(id)
48
- file = Rails.root.join(documentation_directory, "#{id}.yml")
49
- parse_documentation(file)
53
+ file = Rails.root.join(@documentation_directory, "#{id}.yml")
54
+ if !file.exist?
55
+ file = gem_documentation_directory.join("#{id}.yml")
56
+ parse_documentation(file).merge(source: 'gem')
57
+ else
58
+ parse_documentation(file).merge(source: 'application')
59
+ end
50
60
  end
51
61
 
52
62
  def parse_documentation(file)
53
63
  { id: File.basename(file, ".yml") }.merge(YAML::load_file(file)).with_indifferent_access
54
64
  end
55
65
 
56
- def documentation_directory
66
+ def app_documentation_directory
57
67
  Rails.root.join("app", "views", GovukPublishingComponents::Config.component_directory_name, "docs")
58
68
  end
69
+
70
+ def gem_documentation_directory
71
+ Pathname.new(GovukPublishingComponents::Config.gem_directory).join("app", "views", "components", "docs")
72
+ end
59
73
  end
60
74
  end
@@ -0,0 +1,143 @@
1
+ <%
2
+ groups ||= false
3
+ small ||= false
4
+ heading_level ||= 2
5
+ show_step ||= false
6
+ remember_last_step ||= false
7
+ task_list_url ||= false
8
+ task_list_url_link_text ||= "Get help completing this step"
9
+ highlight_group ||= false
10
+
11
+ step_count = 0
12
+ %>
13
+ <% if groups %>
14
+ <div
15
+ data-module="gemtasklist"
16
+ class="gem-c-task-list js-hidden <% unless small %>gem-c-task-list--large<% end %>"
17
+ <% if remember_last_step %>data-remember<% end %>
18
+ >
19
+ <ol class="gem-c-task-list__groups">
20
+ <% groups.each_with_index do |group, group_index| %>
21
+ <%
22
+ group_is_active = group_index + 1 == highlight_group
23
+ %>
24
+ <li class="gem-c-task-list__group <%= 'gem-c-task-list__group--active' if group_is_active %>" <% if group_is_active %>aria-current="step"<% end %>>
25
+ <span class="gem-c-task-list__circle gem-c-task-list__circle--number">
26
+ <span class="gem-c-task-list__circle-inner">
27
+ <span class="gem-c-task-list__circle-background">
28
+ <span class="visuallyhidden">Step</span> <%= group_index + 1 %>
29
+ </span>
30
+ </span>
31
+ </span>
32
+
33
+ <% group.each_with_index do |step, step_index| %>
34
+ <%
35
+ step_count += 1
36
+ id = step[:id] || step[:title].downcase.tr(" ","-")
37
+
38
+ logic = "and"
39
+ logic = step[:logic] if ["and", "or"].include? step[:logic]
40
+ %>
41
+ <div
42
+ class="gem-c-task-list__step js-step <%= "gem-c-task-list__step--optional" if step[:optional] %>"
43
+ id="<%= id %>"
44
+ data-track-count="tasklistSection"
45
+ <%= "data-show" if step_count == show_step %>
46
+ >
47
+ <% if step_index > 0 %>
48
+ <div class="gem-c-task-list__circle gem-c-task-list__circle--logic">
49
+ <span class="gem-c-task-list__circle-inner">
50
+ <span class="gem-c-task-list__circle-background">
51
+ <%= logic %>
52
+ </span>
53
+ </span>
54
+ </div>
55
+ <% end %>
56
+
57
+ <div class="gem-c-task-list__header js-toggle-panel" data-position="<%= "#{group_index + 1}.#{step_index + 1}" %>">
58
+ <h<%= heading_level %> class="gem-c-task-list__title js-step-title">
59
+ <%= step[:title] %>
60
+ </h<%= heading_level %>>
61
+ </div>
62
+
63
+ <div class="gem-c-task-list__panel js-panel" id="step-panel-<%= id %>-<%= step_index + 1 %>">
64
+ <%
65
+ in_substep = false
66
+ link_index = 0
67
+ %>
68
+ <% step[:contents].each do |element| %>
69
+ <% if element[:type] == 'paragraph' %>
70
+ <p class="gem-c-task-list__paragraph"><%= element[:text] %></p>
71
+
72
+ <% elsif element[:type] == 'list' %>
73
+ <%
74
+ list_style = ''
75
+ list_element = 'ol'
76
+
77
+ if element[:style] == 'required'
78
+ list_style = 'gem-c-task-list__links--required'
79
+ elsif element[:style] == 'choice'
80
+ list_style = 'gem-c-task-list__links--choice'
81
+ list_element = 'ul'
82
+ end
83
+ %>
84
+
85
+ <%= content_tag(
86
+ list_element,
87
+ class: "gem-c-task-list__links #{list_style}",
88
+ data: {
89
+ length: element[:contents].length
90
+ }) do %>
91
+ <% element[:contents].each do |link| %>
92
+ <%
93
+ if link[:href]
94
+ link_href = link[:active] ? "#content" : link[:href]
95
+ link_text = link[:active] ? '<span class="visuallyhidden">You are currently viewing:</span> '.html_safe + link[:text] : link[:text]
96
+ link_active = 'gem-c-task-list__link-item--active' if link[:active]
97
+ link_rel = link_href.start_with?('http') ? 'rel=external' : ''
98
+ link_index += 1
99
+ link_position = "data-position=\"#{group_index + 1}.#{step_index + 1}.#{link_index}\""
100
+
101
+ link_tag = "<a href=\"#{link_href}\" class=\"gem-c-task-list__link-item js-link #{link_active}\" #{link_position} #{link_rel}>#{link_text}</a>".html_safe
102
+ else
103
+ link_tag = link[:text]
104
+ end
105
+ %>
106
+ <li class="gem-c-task-list__link">
107
+ <%= link_tag %>
108
+
109
+ <% if link[:context] %>
110
+ <span class="gem-c-task-list__context"><%= link[:context] %></span>
111
+ <% end %>
112
+ </li>
113
+ <% end %>
114
+ <% end %>
115
+
116
+ <% elsif element[:type] == 'substep' %>
117
+ <% if in_substep %>
118
+ </div>
119
+ <% in_substep = false %>
120
+ <% end %>
121
+ <div class="gem-c-task-list__substep <% if element[:optional] %>gem-c-task-list__substep--optional<% end %>">
122
+ <% in_substep = true %>
123
+ <% end %>
124
+ <% end %>
125
+
126
+ <% if in_substep %>
127
+ </div>
128
+ <% end %>
129
+
130
+ <% if task_list_url %>
131
+ <div class="gem-c-task-list__help">
132
+ <a href="<%= task_list_url %>#<%= id %>" class="gem-c-task-list__help-link js-link" data-position="get-help"><%= task_list_url_link_text %></a>
133
+ </div>
134
+ <% end %>
135
+ </div>
136
+
137
+ </div>
138
+ <% end %>
139
+ </li>
140
+ <% end %>
141
+ </ol>
142
+ </div>
143
+ <% end %>
@@ -0,0 +1,38 @@
1
+ <%
2
+ title ||= false
3
+ path ||= false
4
+ skip_link ||= false
5
+ skip_link_text ||= "Skip content"
6
+ %>
7
+ <% if title %>
8
+ <div class="gem-c-task-list-header" data-module="track-click">
9
+ <span class="gem-c-task-list-header__part-of">Part of</span>
10
+ <% if path %>
11
+ <a href="<%= path %>"
12
+ class="gem-c-task-list-header__title"
13
+ data-track-category="tasklistHeaderClicked"
14
+ data-track-action="top"
15
+ data-track-label="<%= path %>"
16
+ data-track-dimension="<%= title %>"
17
+ data-track-dimension-index="29">
18
+ <%= title %>
19
+ </a>
20
+ <% else %>
21
+ <span class="gem-c-task-list-header__title">
22
+ <%= title %>
23
+ </span>
24
+ <% end %>
25
+
26
+ <% if skip_link %>
27
+ <a href="<%= skip_link %>"
28
+ class="gem-c-task-list-header__skip-link"
29
+ data-track-category="tasklistHeaderClicked"
30
+ data-track-action="top"
31
+ data-track-label="<%= skip_link %>"
32
+ data-track-dimension="<%= skip_link_text %>"
33
+ data-track-dimension-index="29">
34
+ <%= skip_link_text %>
35
+ </a>
36
+ <% end %>
37
+ </div>
38
+ <% end %>
@@ -0,0 +1,39 @@
1
+ <%
2
+ links ||= false
3
+ pretitle ||= t("govuk_component.task_list_related.part_of", default: "Part of")
4
+ %>
5
+ <% if links %>
6
+ <div class="pub-c-task-list-related" data-module="track-click">
7
+ <h2 class="pub-c-task-list-related__heading">
8
+ <span class="pub-c-task-list-related__pretitle"><%= pretitle %></span>
9
+ <% if links.length == 1 %>
10
+ <a href="<%= links[0][:href] %>"
11
+ class="pub-c-task-list-related__link"
12
+ data-track-category="tasklistPartOfClicked"
13
+ data-track-action="<%= pretitle %>"
14
+ data-track-label="<%= links[0][:href] %>"
15
+ data-track-dimension="<%= links[0][:text] %>"
16
+ data-track-dimension-index="29">
17
+ <%= links[0][:text] %>
18
+ </a>
19
+ </h2>
20
+ <% else %>
21
+ </h2>
22
+ <ul class="pub-c-task-list-related__links">
23
+ <% links.each do |link| %>
24
+ <li class="pub-c-task-list-related__link-item">
25
+ <a href="<%= link[:href] %>"
26
+ class="pub-c-task-list-related__link"
27
+ data-track-category="tasklistPartOfClicked"
28
+ data-track-action="<%= pretitle %>"
29
+ data-track-label="<%= link[:href] %>"
30
+ data-track-dimension="<%= link[:text] %>"
31
+ data-track-dimension-index="29">
32
+ <%= link[:text] %>
33
+ </a>
34
+ </li>
35
+ <% end %>
36
+ </ul>
37
+ <% end %>
38
+ </div>
39
+ <% end %>
@@ -0,0 +1,1032 @@
1
+ name: Task list
2
+ description: Numbered groups containing expanding/collapsing steps
3
+ body: |
4
+ Task lists are designed to show a sequence of steps towards a specific goal, such as 'learning to drive'. Each group of a task list can contain one or more steps. 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.
5
+
6
+ If JavaScript is disabled the task list expands fully. All of the task list functionality (including the icons and aria attributes) are added using JavaScript.
7
+
8
+ The task list is based on the accordion component in collections, but has been altered. This is for two reasons.
9
+
10
+ - task lists are needed throughout GOV.UK and extending the accordion to be the task list would require promoting it to static, which would break integration testing
11
+ - creating a new component allows further iteration without impacting the accordion
12
+ accessibility_criteria: |
13
+ The task list must:
14
+
15
+ - indicate to users that each step can be expanded and collapsed
16
+ - inform the user when a step has been expanded or collapsed
17
+ - be usable with a keyboard
18
+ - allow users to show or hide all steps at once
19
+ - inform the user which step a link belongs to
20
+ - inform the user which step the current page is in, particularly where there are multiple steps in one group
21
+ - 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
22
+
23
+ The show/hide all button only needs to list the first panel id in the aria-controls attribute, rather than all of them.
24
+
25
+ Step headings must use a button element:
26
+
27
+ - so that steps can be toggled with the space and enter keys
28
+ - so that steps can't be opened in a new tab or window
29
+
30
+ When JavaScript is unavailable the task list must:
31
+
32
+ - be fully expanded
33
+ - not be marked as expandable
34
+ shared_accessibility_criteria:
35
+ - link
36
+ examples:
37
+ default:
38
+ data:
39
+ groups: [
40
+ [
41
+ {
42
+ title: "Do a thing",
43
+ contents: [
44
+ {
45
+ type: 'paragraph',
46
+ text: 'This is a paragraph of text.'
47
+ },
48
+ {
49
+ type: 'paragraph',
50
+ 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.'
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ title: "Do another thing",
56
+ contents: [
57
+ {
58
+ type: 'paragraph',
59
+ text: 'Groups can contain multiple steps, like this.'
60
+ },
61
+ ]
62
+ }
63
+ ],
64
+ [
65
+ {
66
+ title: "Do something else",
67
+ contents: [
68
+ {
69
+ type: 'paragraph',
70
+ text: 'This is yet another paragraph.'
71
+ }
72
+ ]
73
+ }
74
+ ]
75
+ ]
76
+ with_a_different_heading_level:
77
+ description: Steps have a H2 by default, but this can be changed. The heading level does not change any styling.
78
+ data:
79
+ heading_level: 3
80
+ groups: [
81
+ [
82
+ {
83
+ title: 'This is a heading 3',
84
+ contents: [
85
+ {
86
+ type: 'paragraph',
87
+ text: 'This is yet another paragraph.'
88
+ }
89
+ ]
90
+ }
91
+ ],
92
+ [
93
+ {
94
+ title: 'This is also a heading 3',
95
+ contents: [
96
+ {
97
+ type: 'paragraph',
98
+ text: 'This is yet another paragraph.'
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ ]
104
+ open_a_step_by_default:
105
+ description: Pass the index of the step to open by default. This is the nth step, regardless of group number.
106
+ data:
107
+ show_step: 3
108
+ groups: [
109
+ [
110
+ {
111
+ title: 'Closed by default',
112
+ contents: [
113
+ {
114
+ type: 'paragraph',
115
+ text: 'Well, open now, obviously.'
116
+ }
117
+ ]
118
+ }
119
+ ],
120
+ [
121
+ {
122
+ title: 'Also closed by default',
123
+ contents: [
124
+ {
125
+ type: 'paragraph',
126
+ text: 'Hello.'
127
+ }
128
+ ]
129
+ },
130
+ {
131
+ title: 'Open by default',
132
+ contents: [
133
+ {
134
+ type: 'paragraph',
135
+ text: 'Hello!'
136
+ }
137
+ ]
138
+ }
139
+ ]
140
+ ]
141
+ remember_last_opened_step:
142
+ description: |
143
+ If a step is opened its ID is appended to the end of the URL, so that if the URL is shared or the 'back' button is used, that step will be opened on page load. This was historically part of the behaviour of the accordion. By default this is turned off and cannot be used together with the option to open a step by default.
144
+
145
+ This behaviour is used with the 'links to more information' option.
146
+ data:
147
+ remember_last_step: true
148
+ groups: [
149
+ [
150
+ {
151
+ title: 'Remember this',
152
+ contents: [
153
+ {
154
+ type: 'paragraph',
155
+ text: 'Hello!'
156
+ }
157
+ ]
158
+ }
159
+ ],
160
+ [
161
+ {
162
+ title: 'Or this',
163
+ contents: [
164
+ {
165
+ type: 'paragraph',
166
+ text: 'Hello!'
167
+ }
168
+ ]
169
+ }
170
+ ]
171
+ ]
172
+ with_links:
173
+ description: |
174
+ Links can have the following attributes:
175
+
176
+ - style, an attribute on the parent list that controls its appearance, either required (bold), optional (not bold) or choice (not bold, with bullets on the list). The default is optional.
177
+ - context, an optional text field to show some extra information after the link, usually a monetary value
178
+ - active, whether to make the link highlighted (to indicate the current page)
179
+ - highlight_group, a general option to highlight a specific group of steps. Usually the active link would be in the active group, but in some circumstances there might be an active group but no highlighted link.
180
+ data:
181
+ highlight_group: 2
182
+ show_step: 2
183
+ groups: [
184
+ [
185
+ {
186
+ title: 'Links and paragraphs',
187
+ contents: [
188
+ {
189
+ type: 'paragraph',
190
+ text: 'These links represent tasks that are required.'
191
+ },
192
+ {
193
+ type: 'paragraph',
194
+ 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.'
195
+ },
196
+ {
197
+ type: 'list',
198
+ style: 'required',
199
+ contents: [
200
+ {
201
+ href: '/component-guide/task_list/with_links/preview',
202
+ text: 'Obtain a driving licence prior to driving a car',
203
+ active: true
204
+ },
205
+ {
206
+ href: '/component-guide/task_list/with_links/preview',
207
+ text: 'Acquire food before attempting to cook',
208
+ context: '1p to &pound;20',
209
+ active: true
210
+ },
211
+ {
212
+ href: '/component-guide/task_list/with_links/preview',
213
+ text: 'Maintain contact with the ground at all times',
214
+ active: true
215
+ }
216
+ ]
217
+ },
218
+ {
219
+ type: 'paragraph',
220
+ text: 'These links represent tasks that are optional.'
221
+ },
222
+ {
223
+ type: 'list',
224
+ contents: [
225
+ {
226
+ href: '/component-guide/task_list/with_links/preview',
227
+ text: 'Learn to play the saxophone',
228
+ active: true
229
+ },
230
+ {
231
+ href: '/component-guide/task_list/with_links/preview',
232
+ text: 'Develop a new method of extracting juice from oranges',
233
+ context: '&pound;0 to &pound;300',
234
+ active: true
235
+ },
236
+ {
237
+ href: '/component-guide/task_list/with_links/preview',
238
+ text: 'Buy a race car',
239
+ active: true
240
+ }
241
+ ]
242
+ },
243
+ {
244
+ type: 'paragraph',
245
+ text: 'These links represent a choice:'
246
+ },
247
+ {
248
+ type: 'list',
249
+ style: 'choice',
250
+ contents: [
251
+ {
252
+ href: '/component-guide/task_list/',
253
+ text: 'Leave school at sixteen'
254
+ },
255
+ {
256
+ href: '/component-guide/task_list/',
257
+ text: 'Continue into higher education',
258
+ context: '&pound;9,500'
259
+ }
260
+ ]
261
+ }
262
+ ]
263
+ }
264
+ ],
265
+ [
266
+ {
267
+ title: 'Active group and links',
268
+ contents: [
269
+ {
270
+ type: 'list',
271
+ style: 'required',
272
+ contents: [
273
+ {
274
+ href: '/component-guide/task_list/',
275
+ text: 'Check the reasons'
276
+ },
277
+ {
278
+ href: '/component-guide/task_list/with_links/preview',
279
+ text: 'Make the decisions based on available data and the reasonable assumptions that are possible at the time',
280
+ context: '1p to &pound;20',
281
+ active: true
282
+ },
283
+ {
284
+ href: '/component-guide/task_list/with_links/preview',
285
+ text: 'Do the things',
286
+ active: true
287
+ }
288
+ ]
289
+ },
290
+ ]
291
+ }
292
+ ]
293
+ ]
294
+ or_then:
295
+ description: Some of the more complex things in a task list 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.
296
+ data:
297
+ show_step: 1
298
+ groups: [
299
+ [
300
+ {
301
+ title: "Get a court to decide your child arrangements",
302
+ contents: [
303
+ {
304
+ type: 'paragraph',
305
+ 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."
306
+ },
307
+ {
308
+ type: 'list',
309
+ style: 'required',
310
+ contents: [
311
+ {
312
+ href: 'http://solicitors.lawsociety.org.uk/',
313
+ text: 'Hire a lawyer to represent you',
314
+ context: '&pound;110 to &pound;410 per hour'
315
+ },
316
+ {
317
+ text: 'or',
318
+ },
319
+ {
320
+ href: 'http://localhost:3000/represent-yourself-in-court',
321
+ text: 'Represent yourself in court'
322
+ }
323
+ ]
324
+ },
325
+ {
326
+ type: 'paragraph',
327
+ text: 'then'
328
+ },
329
+ {
330
+ type: 'list',
331
+ style: 'required',
332
+ contents: [
333
+ {
334
+ href: '/looking-after-children-divorce/apply-for-court-order',
335
+ text: 'Apply for a court order',
336
+ context: '&pound;215'
337
+ },
338
+ {
339
+ href: 'https://courttribunalfinder.service.gov.uk/search/',
340
+ text: 'Find the right court to send your application'
341
+ },
342
+ {
343
+ href: '/get-help-with-court-fees',
344
+ text: 'Get help with court fees'
345
+ }
346
+ ]
347
+ },
348
+ {
349
+ type: 'paragraph',
350
+ 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."
351
+ }
352
+ ]
353
+ }
354
+ ]
355
+ ]
356
+ solve_the_double_dot_problem:
357
+ description: |
358
+ If a page is in a task list more than once and a user is viewing that URL, both links to it will be highlighted as the site has no way to know which entry in the task list the user is currently viewing (highlighted links should only occur when the task list is in the sidebar).
359
+
360
+ JavaScript is included in the component to solve this. It uses sessionStorage to capture the data-position attribute of non-external links in the task list when clicked, and then uses this value to decide which link to highlight when the new page loads. This session storage data is immediately deleted after it is read on page load, mainly to prevent problems with highlighting if the user were to move between different task lists.
361
+
362
+ If a user has not clicked a link (i.e. has visited the page without first clicking on a task list) the first active link in the first active group will be highlighted. If there is no active group, the first active link will be highlighted (but there should always be an active group).
363
+
364
+ The current page in the task list is an anchor link to the top of the page. If there are more than one of these and the user clicks one that is not currently highlighted, that one will be highlighted.
365
+
366
+ The example below will show all links highlighted if JS is disabled, in the real world no more than two or three links are likely to be highlighted at once.
367
+ data:
368
+ highlight_group: 2
369
+ show_step: 2
370
+ groups: [
371
+ [
372
+ {
373
+ title: "Not the active step",
374
+ contents: [
375
+ {
376
+ type: 'list',
377
+ style: 'required',
378
+ contents: [
379
+ {
380
+ href: 'http://google.com',
381
+ text: 'External link not set to active'
382
+ },
383
+ {
384
+ href: '/component-guide/task_list/with_links/preview',
385
+ text: 'Internal link set to active',
386
+ active: true
387
+ },
388
+ {
389
+ href: '/component-guide/task_list/with_links/preview',
390
+ text: 'Internal link set to active',
391
+ active: true
392
+ },
393
+ {
394
+ href: 'http://google.com',
395
+ text: 'External link not set to active'
396
+ }
397
+ ]
398
+ }
399
+ ]
400
+ }
401
+ ],
402
+ [
403
+ {
404
+ title: "The active step",
405
+ contents: [
406
+ {
407
+ type: 'list',
408
+ style: 'required',
409
+ contents: [
410
+ {
411
+ href: '/component-guide/task_list/with_links/preview',
412
+ text: 'Internal link set to active - in the active group, should be set by default until another link is clicked',
413
+ active: true
414
+ },
415
+ {
416
+ href: '/component-guide/task_list/with_links/preview',
417
+ text: 'Internal link set to active',
418
+ active: true
419
+ },
420
+ {
421
+ href: 'http://google.com',
422
+ text: 'External link not set to active'
423
+ }
424
+ ]
425
+ }
426
+ ]
427
+ }
428
+ ]
429
+ ]
430
+ with_optional_steps:
431
+ description: |
432
+ Steps can be optional. This is controlled by two parameters for maximum flexibility, 'optional' (which causes the step to have a dotted line down the side) and 'logic', which defaults to showing the word 'and' alongside the step title, but also accepts 'or'.
433
+
434
+ If a step is optional this should be conveyed by the text within that step.
435
+ data:
436
+ groups: [
437
+ [
438
+ {
439
+ title: "Drive to work",
440
+ contents: [
441
+ {
442
+ type: paragraph,
443
+ text: 'If you do not have a car, you will need to choose an alternative.'
444
+ }
445
+ ]
446
+ },
447
+ {
448
+ title: "Walk to work",
449
+ optional: true,
450
+ logic: 'or',
451
+ contents: [
452
+ {
453
+ type: 'paragraph',
454
+ text: 'Walking is healthy but may not be practical where large distances are concerned.'
455
+ }
456
+ ]
457
+ },
458
+ {
459
+ title: "Get public transport to work",
460
+ optional: true,
461
+ logic: 'or',
462
+ contents: [
463
+ {
464
+ type: 'paragraph',
465
+ text: 'Public transport includes buses, trains and boats.'
466
+ }
467
+ ]
468
+ }
469
+ ],
470
+ [
471
+ {
472
+ title: "Do work",
473
+ contents: [
474
+ {
475
+ type: 'paragraph',
476
+ text: 'Once you have reached your destination you should be able to start work.'
477
+ }
478
+ ]
479
+ },
480
+ {
481
+ title: "Get paid",
482
+ contents: [
483
+ {
484
+ type: 'paragraph',
485
+ text: 'Your employer should pay you for hours worked.'
486
+ }
487
+ ]
488
+ }
489
+ ]
490
+ ]
491
+ with_sub_steps:
492
+ description: Steps can also contain sub steps, which act either as a way to break up content or to indicate that some tasks are optional. Whenever a step or sub step is optional this should be made clear in the written content. Optional steps are styled differently but this should support the meaning, not convey it.
493
+ data:
494
+ highlight_group: 2
495
+ show_step: 2
496
+ groups: [
497
+ [
498
+ {
499
+ title: "A required step",
500
+ contents: [
501
+ {
502
+ type: 'paragraph',
503
+ text: 'This step ends with an optional sub step.'
504
+ },
505
+ {
506
+ type: 'substep',
507
+ optional: true
508
+ },
509
+ {
510
+ type: 'paragraph',
511
+ text: 'This paragraph is inside the sub step.'
512
+ },
513
+ {
514
+ type: 'list',
515
+ contents: [
516
+ {
517
+ href: '/test6',
518
+ text: 'This link is also inside the sub step'
519
+ }
520
+ ]
521
+ }
522
+ ]
523
+ }
524
+ ],
525
+ [
526
+ {
527
+ title: "An optional step",
528
+ optional: true,
529
+ contents: [
530
+ {
531
+ type: 'paragraph',
532
+ text: 'This optional step contains multiple sub steps.'
533
+ },
534
+ {
535
+ type: 'substep',
536
+ optional: false
537
+ },
538
+ {
539
+ type: 'paragraph',
540
+ text: 'This paragraph is inside a required sub step.'
541
+ },
542
+ {
543
+ type: 'substep',
544
+ optional: true
545
+ },
546
+ {
547
+ type: 'paragraph',
548
+ text: 'This paragraph is inside an optional sub step.'
549
+ },
550
+ {
551
+ type: 'list',
552
+ contents: [
553
+ {
554
+ href: '/test7',
555
+ text: 'This link is inside an optional sub step as well',
556
+ active: true
557
+ }
558
+ ]
559
+ },
560
+ {
561
+ type: 'substep',
562
+ optional: false
563
+ },
564
+ {
565
+ type: 'paragraph',
566
+ text: 'This paragraph is inside a required sub step.'
567
+ }
568
+ ]
569
+ }
570
+ ],
571
+ [
572
+ {
573
+ title: "Another required step",
574
+ contents: [
575
+ {
576
+ type: 'paragraph',
577
+ text: 'Um. Hello.'
578
+ }
579
+ ]
580
+ }
581
+ ]
582
+ ]
583
+ with_links_to_more_information:
584
+ description: |
585
+ Where task lists are long, content can be substituted with a link back to the main task list page. This link will open the main task list page with that step shown. The link text defaults to "Get help completing this step" but can be overridden.
586
+
587
+ Note that this option does not remove any content - it is left to developers to simply pass less content to the component in this situation.
588
+ data:
589
+ task_list_url: "/learn-to-do-something"
590
+ task_list_url_link_text: "Get more information"
591
+ show_step: 1
592
+ groups: [
593
+ [
594
+ {
595
+ title: "A link back to the main task list",
596
+ contents: [
597
+ {
598
+ type: 'list',
599
+ contents: [
600
+ {
601
+ href: '/test7',
602
+ text: 'This is a link'
603
+ },
604
+ {
605
+ href: '/test7',
606
+ text: 'This is another link'
607
+ }
608
+ ]
609
+ }
610
+ ]
611
+ }
612
+ ],
613
+ [
614
+ {
615
+ title: "Another link back to the main task list",
616
+ contents: [
617
+ {
618
+ type: 'list',
619
+ contents: [
620
+ {
621
+ href: '/test7',
622
+ text: 'This is yet another link'
623
+ },
624
+ {
625
+ href: '/test7',
626
+ text: 'This is a further link'
627
+ },
628
+ ]
629
+ }
630
+ ]
631
+ }
632
+ ]
633
+ ]
634
+ test_all_the_things:
635
+ description: This component is very complicated so here is an example containing as many of the options available as possible.
636
+ data:
637
+ task_list_url: "/learn-to-setup-standup"
638
+ highlight_group: 2
639
+ groups: [
640
+ [
641
+ {
642
+ title: 'Get the TV ready',
643
+ contents: [
644
+ {
645
+ type: 'paragraph',
646
+ text: 'Configure the television so it is ready for the standup. You will also need a laptop.'
647
+ },
648
+ {
649
+ type: 'list',
650
+ style: 'required',
651
+ contents: [
652
+ {
653
+ href: 'https://en.wikipedia.org/wiki/HDMI',
654
+ text: 'Remove the Chromebit from HDMI 1 on the TV',
655
+ active: true
656
+ }
657
+ ]
658
+ }
659
+ ]
660
+ },
661
+ {
662
+ title: 'Plug everything in',
663
+ contents: [
664
+ {
665
+ type: 'paragraph',
666
+ text: 'Connect the relevant cables between the various devices.'
667
+ },
668
+ {
669
+ type: 'list',
670
+ style: 'required',
671
+ contents: [
672
+ {
673
+ href: 'https://www.google.co.uk/',
674
+ text: 'Run the HDMI - MINI DVI cable from the TV to the facilitators laptop'
675
+ },
676
+ {
677
+ href: 'https://www.jabra.co.uk/',
678
+ text: 'Plug the Jabra into the facilitators laptop'
679
+ }
680
+ ]
681
+ }
682
+ ]
683
+ }
684
+ ],
685
+ [
686
+ {
687
+ title: 'Configure the catchbox',
688
+ contents: [
689
+ {
690
+ type: 'paragraph',
691
+ text: 'These steps are required.'
692
+ },
693
+ {
694
+ type: 'list',
695
+ style: 'required',
696
+ contents: [
697
+ {
698
+ href: '',
699
+ text: 'Ensure the catchbox transmitter is plugged in at the mains wall',
700
+ active: true
701
+ },
702
+ {
703
+ href: '',
704
+ text: 'Turn on the transmitter and wait for the switch to blink green'
705
+ },
706
+ {
707
+ href: '',
708
+ text: 'Plug the transmitter USB cable into the facilitators laptop'
709
+ },
710
+ {
711
+ href: '',
712
+ text: 'Twist and pull the black piece of foam out of the catchbox'
713
+ },
714
+ {
715
+ href: '',
716
+ text: 'Turn on the catchbox and wait for the LED to turn green'
717
+ },
718
+ {
719
+ href: '',
720
+ text: 'Wait for the transmitter light to turn solid green'
721
+ }
722
+ ]
723
+ },
724
+ {
725
+ type: 'substep',
726
+ optional: true
727
+ },
728
+ {
729
+ type: 'paragraph',
730
+ text: 'These steps are not required.'
731
+ },
732
+ {
733
+ type: 'list',
734
+ style: 'choice',
735
+ contents: [
736
+ {
737
+ href: 'https://www.google.co.uk/',
738
+ text: "Get annoyed when it doesn't work"
739
+ },
740
+ {
741
+ href: '',
742
+ text: 'Try to find someone else who knows how to do it',
743
+ context: '1 to 10 minutes'
744
+ }
745
+ ]
746
+ }
747
+ ]
748
+ }
749
+ ],
750
+ [
751
+ {
752
+ title: 'Join and configure the standup',
753
+ contents: [
754
+ {
755
+ type: 'paragraph',
756
+ text: 'Join the hangout and present to those on it.'
757
+ },
758
+ {
759
+ type: 'list',
760
+ style: 'required',
761
+ contents: [
762
+ {
763
+ href: '',
764
+ text: 'Connect to standup hangout via the calendar invite',
765
+ active: true
766
+ },
767
+ {
768
+ text: 'or'
769
+ },
770
+ {
771
+ href: '',
772
+ text: 'Connect to standup hangout via the link in the team slack',
773
+ active: true
774
+ }
775
+ ]
776
+ },
777
+ {
778
+ type: 'paragraph',
779
+ text: 'then'
780
+ },
781
+ {
782
+ type: 'list',
783
+ style: 'required',
784
+ contents: [
785
+ {
786
+ href: '',
787
+ text: 'Click the three dots in the bottom hand corner to open settings'
788
+ },
789
+ {
790
+ href: '',
791
+ text: 'Set speaker to "Jabra"'
792
+ },
793
+ {
794
+ href: '',
795
+ text: 'Set microphone to "C Media USB"'
796
+ },
797
+ {
798
+ href: '',
799
+ text: 'Click "present to meeting"'
800
+ },
801
+ ]
802
+ }
803
+ ]
804
+ }
805
+ ],
806
+ [
807
+ {
808
+ title: 'Clear up',
809
+ contents: [
810
+ {
811
+ type: 'paragraph',
812
+ text: 'Disconnect from the hangout and disconnect any cables.'
813
+ },
814
+ {
815
+ type: 'paragraph',
816
+ text: 'Most importantly, remember to switch off the catchbox to save the battery.'
817
+ }
818
+ ]
819
+ },
820
+ {
821
+ title: 'Get someone else to clear up',
822
+ logic: 'or',
823
+ optional: true,
824
+ contents: [
825
+ {
826
+ type: 'paragraph',
827
+ text: 'Schedule another meeting for right after the standup and force someone else to sort everything out.'
828
+ }
829
+ ]
830
+ }
831
+ ]
832
+ ]
833
+ small:
834
+ description: Designed to fit in the sidebar of a page. Note that the small version of the task list 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.
835
+ data:
836
+ small: true
837
+ task_list_url: "/learn-to-setup-standup"
838
+ highlight_group: 2
839
+ groups: [
840
+ [
841
+ {
842
+ title: 'Get the TV ready.',
843
+ contents: [
844
+ {
845
+ type: 'paragraph',
846
+ text: 'Configure the television so it is ready for the standup. You will also need a laptop.'
847
+ },
848
+ {
849
+ type: 'list',
850
+ style: 'required',
851
+ contents: [
852
+ {
853
+ href: 'https://en.wikipedia.org/wiki/HDMI',
854
+ text: 'Remove the Chromebit from HDMI 1 on the TV',
855
+ active: true
856
+ }
857
+ ]
858
+ }
859
+ ]
860
+ },
861
+ {
862
+ title: 'Plug everything in.',
863
+ contents: [
864
+ {
865
+ type: 'paragraph',
866
+ text: 'Connect the relevant cables between the various devices.'
867
+ },
868
+ {
869
+ type: 'list',
870
+ style: 'required',
871
+ contents: [
872
+ {
873
+ href: 'https://www.google.co.uk/',
874
+ text: 'Run the HDMI - MINI DVI cable from the TV to the facilitators laptop'
875
+ },
876
+ {
877
+ href: 'https://www.jabra.co.uk/',
878
+ text: 'Plug the Jabra into the facilitators laptop'
879
+ }
880
+ ]
881
+ }
882
+ ]
883
+ }
884
+ ],
885
+ [
886
+ {
887
+ title: 'Configure the catchbox.',
888
+ contents: [
889
+ {
890
+ type: 'paragraph',
891
+ text: 'These steps are required.'
892
+ },
893
+ {
894
+ type: 'list',
895
+ style: 'required',
896
+ contents: [
897
+ {
898
+ href: '',
899
+ text: 'Ensure the catchbox transmitter is plugged in at the mains wall',
900
+ active: true
901
+ },
902
+ {
903
+ href: '',
904
+ text: 'Turn on the transmitter and wait for the switch to blink green'
905
+ },
906
+ {
907
+ href: '',
908
+ text: 'Plug the transmitter USB cable into the facilitators laptop'
909
+ },
910
+ {
911
+ href: '',
912
+ text: 'Twist and pull the black piece of foam out of the catchbox'
913
+ },
914
+ {
915
+ href: '',
916
+ text: 'Turn on the catchbox and wait for the LED to turn green'
917
+ },
918
+ {
919
+ href: '',
920
+ text: 'Wait for the transmitter light to turn solid green'
921
+ }
922
+ ]
923
+ },
924
+ {
925
+ type: 'substep',
926
+ optional: true
927
+ },
928
+ {
929
+ type: 'paragraph',
930
+ text: 'These steps are not required.'
931
+ },
932
+ {
933
+ type: 'list',
934
+ style: 'choice',
935
+ contents: [
936
+ {
937
+ href: 'https://www.google.co.uk/',
938
+ text: "Get annoyed when it doesn't work"
939
+ },
940
+ {
941
+ href: '',
942
+ text: 'Try to find someone else who knows how to do it',
943
+ context: '1 to 10 minutes'
944
+ }
945
+ ]
946
+ }
947
+ ]
948
+ }
949
+ ],
950
+ [
951
+ {
952
+ title: 'Join and configure the standup.',
953
+ contents: [
954
+ {
955
+ type: 'paragraph',
956
+ text: 'Join the hangout and present to those on it.'
957
+ },
958
+ {
959
+ type: 'list',
960
+ style: 'required',
961
+ contents: [
962
+ {
963
+ href: '',
964
+ text: 'Connect to standup hangout via the calendar invite',
965
+ active: true
966
+ },
967
+ {
968
+ text: 'or'
969
+ },
970
+ {
971
+ href: '',
972
+ text: 'Connect to standup hangout via the link in the team slack',
973
+ active: true
974
+ }
975
+ ]
976
+ },
977
+ {
978
+ type: 'paragraph',
979
+ text: 'then'
980
+ },
981
+ {
982
+ type: 'list',
983
+ style: 'required',
984
+ contents: [
985
+ {
986
+ href: '',
987
+ text: 'Click the three dots in the bottom hand corner to open settings'
988
+ },
989
+ {
990
+ href: '',
991
+ text: 'Set speaker to "Jabra"'
992
+ },
993
+ {
994
+ href: '',
995
+ text: 'Set microphone to "C Media USB"'
996
+ },
997
+ {
998
+ href: '',
999
+ text: 'Click "present to meeting"'
1000
+ },
1001
+ ]
1002
+ }
1003
+ ]
1004
+ }
1005
+ ],
1006
+ [
1007
+ {
1008
+ title: 'Clear up.',
1009
+ contents: [
1010
+ {
1011
+ type: 'paragraph',
1012
+ text: 'Disconnect from the hangout and disconnect any cables.'
1013
+ },
1014
+ {
1015
+ type: 'paragraph',
1016
+ text: 'Most importantly, remember to switch off the catchbox to save the battery.'
1017
+ }
1018
+ ]
1019
+ },
1020
+ {
1021
+ title: 'Get someone else to clear up.',
1022
+ logic: 'or',
1023
+ optional: true,
1024
+ contents: [
1025
+ {
1026
+ type: 'paragraph',
1027
+ text: 'Schedule another meeting for right after the standup and force someone else to sort everything out.'
1028
+ }
1029
+ ]
1030
+ }
1031
+ ]
1032
+ ]