govuk_publishing_components 43.2.0 → 43.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/govuk_publishing_components/icon-autocomplete-search-suggestion.svg +4 -0
- data/app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js +123 -0
- data/app/assets/javascripts/govuk_publishing_components/lib/cookie-functions.js +0 -2
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +5 -4
- data/app/assets/stylesheets/govuk_publishing_components/components/_phase-banner.scss +0 -2
- data/app/assets/stylesheets/govuk_publishing_components/components/_search-with-autocomplete.scss +200 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_table.scss +1 -0
- data/app/views/govuk_publishing_components/components/_layout_header.html.erb +16 -40
- data/app/views/govuk_publishing_components/components/_password_input.html.erb +4 -3
- data/app/views/govuk_publishing_components/components/_search.html.erb +16 -14
- data/app/views/govuk_publishing_components/components/_search_with_autocomplete.html.erb +27 -0
- data/app/views/govuk_publishing_components/components/docs/layout_header.yml +0 -41
- data/app/views/govuk_publishing_components/components/docs/password_input.yml +4 -0
- data/app/views/govuk_publishing_components/components/docs/phase_banner.yml +4 -0
- data/app/views/govuk_publishing_components/components/docs/search_with_autocomplete.yml +61 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 907217210fe22535516273b8a2bddec801e1ccf6d0105013c90d96ebcc8912c7
|
4
|
+
data.tar.gz: 1db72b2071a73d7706b2beef1edc5ed1fc628c42433731234bcff19c68db6160
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52021a5d93c13d4478369b20a69f7813d28ecfdb5669e4489aa5d6322a88e1b621858f31a49ff02ae32c46e5bd27cd3b89cd07b4d85d80d4de6997061e081db5
|
7
|
+
data.tar.gz: ff20583781681f2c7dac855929fd7302b156e0dbc7e1f1f6bbdf6770cd75d48b4f486bf3ab83d448089b160b2dfa14f4404c8efd13730ebcd65f94ecdfcde347
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg width="20" height="40" viewBox="0 -10 20 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M8.902 14.4681C12.3859 14.4681 15.2102 11.6438 15.2102 8.15981C15.2102 4.67586 12.3859 1.85156 8.902 1.85156C5.41805 1.85156 2.59375 4.67586 2.59375 8.15981C2.59375 11.6438 5.41805 14.4681 8.902 14.4681Z" stroke="#505a5f" stroke-width="2"/>
|
3
|
+
<path d="M13.2344 12.8584L19.5904 19.2144" stroke="#505a5f" stroke-width="2"/>
|
4
|
+
</svg>
|
data/app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
/* global accessibleAutocomplete, fetch */
|
2
|
+
//= require accessible-autocomplete/dist/accessible-autocomplete.min.js
|
3
|
+
|
4
|
+
window.GOVUK = window.GOVUK || {}
|
5
|
+
window.GOVUK.Modules = window.GOVUK.Modules || {};
|
6
|
+
|
7
|
+
(function (Modules) {
|
8
|
+
class GemSearchWithAutocomplete {
|
9
|
+
constructor ($module) {
|
10
|
+
this.$module = $module
|
11
|
+
|
12
|
+
this.$originalInput = this.$module.querySelector('input')
|
13
|
+
this.$inputWrapper = this.$module.querySelector('.js-search-input-wrapper')
|
14
|
+
this.$form = this.$module.closest('form')
|
15
|
+
|
16
|
+
this.sourceUrl = this.$module.getAttribute('data-source-url')
|
17
|
+
this.sourceKey = this.$module.getAttribute('data-source-key')
|
18
|
+
}
|
19
|
+
|
20
|
+
init () {
|
21
|
+
const configOptions = {
|
22
|
+
element: this.$inputWrapper,
|
23
|
+
id: this.$originalInput.id,
|
24
|
+
name: this.$originalInput.name,
|
25
|
+
inputClasses: this.$originalInput.classList,
|
26
|
+
defaultValue: this.$originalInput.value,
|
27
|
+
cssNamespace: 'gem-c-search-with-autocomplete',
|
28
|
+
confirmOnBlur: false,
|
29
|
+
showNoOptionsFound: false,
|
30
|
+
source: this.getResults.bind(this),
|
31
|
+
onConfirm: this.submitContainingForm.bind(this),
|
32
|
+
templates: {
|
33
|
+
suggestion: this.constructSuggestionHTMLString.bind(this)
|
34
|
+
},
|
35
|
+
tStatusNoResults: () => 'No search suggestions found',
|
36
|
+
tStatusQueryTooShort: (minQueryLength) => `Type in ${minQueryLength} or more characters for search suggestions`,
|
37
|
+
tStatusResults: (length, contentSelectedOption) => {
|
38
|
+
const words = {
|
39
|
+
result: (length === 1) ? 'search suggestion' : 'search suggestions',
|
40
|
+
is: (length === 1) ? 'is' : 'are'
|
41
|
+
}
|
42
|
+
|
43
|
+
return `${length} ${words.result} ${words.is} available. ${contentSelectedOption}`
|
44
|
+
},
|
45
|
+
tAssistiveHint: () => 'When search suggestions are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.'
|
46
|
+
}
|
47
|
+
accessibleAutocomplete(configOptions)
|
48
|
+
|
49
|
+
// The accessible-autocomplete component is meant to generate a new input element rather than enhancing an existing one, so we need to do some cleanup here.
|
50
|
+
this.$autocompleteInput = this.$inputWrapper.querySelector(
|
51
|
+
'.gem-c-search-with-autocomplete__input'
|
52
|
+
)
|
53
|
+
// Ensure the new input element generated by accessible-autocomplete has the correct type
|
54
|
+
this.$autocompleteInput.setAttribute('type', 'search')
|
55
|
+
// Remove the original input from the DOM
|
56
|
+
this.$originalInput.parentNode.removeChild(this.$originalInput)
|
57
|
+
}
|
58
|
+
|
59
|
+
// Callback used by accessible-autocomplete to generate the HTML for each suggestion based on
|
60
|
+
// the values returned from the source
|
61
|
+
constructSuggestionHTMLString (result) {
|
62
|
+
const sanitizedResult = this.sanitizeResult(result)
|
63
|
+
const inputValue = this.$inputWrapper.querySelector('input').value.toLowerCase()
|
64
|
+
|
65
|
+
const index = sanitizedResult.toLowerCase().indexOf(inputValue)
|
66
|
+
|
67
|
+
let html = sanitizedResult
|
68
|
+
if (index !== -1) {
|
69
|
+
const before = sanitizedResult.slice(0, index)
|
70
|
+
const match = sanitizedResult.slice(index, index + inputValue.length)
|
71
|
+
const after = sanitizedResult.slice(index + inputValue.length)
|
72
|
+
|
73
|
+
html = `${before}<mark class="gem-c-search-with-autocomplete__suggestion-highlight">${match}</mark>${after}`
|
74
|
+
}
|
75
|
+
|
76
|
+
return `
|
77
|
+
<div class="gem-c-search-with-autocomplete__option-wrapper">
|
78
|
+
<span class="gem-c-search-with-autocomplete__suggestion-icon"></span>
|
79
|
+
<span class="gem-c-search-with-autocomplete__suggestion-text">${html}</span>
|
80
|
+
</div>
|
81
|
+
`
|
82
|
+
}
|
83
|
+
|
84
|
+
// Callback used by accessible-autocomplete to fetch results from the source
|
85
|
+
getResults (query, populateResults) {
|
86
|
+
const url = new URL(this.sourceUrl)
|
87
|
+
url.searchParams.set('q', query)
|
88
|
+
fetch(url, { headers: { Accept: 'application/json' } })
|
89
|
+
.then(response => response.json())
|
90
|
+
.then((data) => { populateResults(data[this.sourceKey]) })
|
91
|
+
.catch(() => { populateResults([]) })
|
92
|
+
}
|
93
|
+
|
94
|
+
// Callback used by accessible-autocomplete to submit the containing form when a suggestion is
|
95
|
+
// confirmed by the user (e.g. by pressing Enter or clicking on it)
|
96
|
+
submitContainingForm (value) {
|
97
|
+
if (this.$form) {
|
98
|
+
// The accessible-autocomplete component calls this callback _before_ it updates its
|
99
|
+
// internal state, so the value of the input field is not yet updated when this callback is
|
100
|
+
// called. We need to force the value to be updated before submitting the form, but the rest
|
101
|
+
// of the state can catch up later.
|
102
|
+
this.$autocompleteInput.value = value
|
103
|
+
|
104
|
+
if (this.$form.requestSubmit) {
|
105
|
+
this.$form.requestSubmit()
|
106
|
+
} else {
|
107
|
+
// Fallback for certain Grade C browsers that don't support `requestSubmit`
|
108
|
+
this.$form.submit()
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
// Sanitises a result coming back from the source to prevent XSS issues if the result happens to
|
114
|
+
// contain HTML.
|
115
|
+
sanitizeResult (value) {
|
116
|
+
const scratch = document.createElement('div')
|
117
|
+
scratch.textContent = value
|
118
|
+
return scratch.innerHTML
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
Modules.GemSearchWithAutocomplete = GemSearchWithAutocomplete
|
123
|
+
})(window.GOVUK.Modules)
|
@@ -23,8 +23,6 @@
|
|
23
23
|
multivariatetest_cohort_coronavirus_extremely_vulnerable_rate_limit: 'essential',
|
24
24
|
dgu_beta_banner_dismissed: 'settings',
|
25
25
|
global_bar_seen: 'settings',
|
26
|
-
govuk_browser_upgrade_dismisssed: 'settings',
|
27
|
-
govuk_not_first_visit: 'settings',
|
28
26
|
user_nation: 'settings',
|
29
27
|
'JS-Detection': 'usage',
|
30
28
|
TLSversion: 'usage',
|
@@ -608,10 +608,6 @@ $after-button-padding-left: govuk-spacing(4);
|
|
608
608
|
// Styles for search toggle button.
|
609
609
|
.gem-c-layout-super-navigation-header__search-toggle-button {
|
610
610
|
background: none;
|
611
|
-
|
612
|
-
&.gem-c-layout-super-navigation-header__search-toggle-button--blue-background {
|
613
|
-
background: $govuk-brand-colour;
|
614
|
-
}
|
615
611
|
border: 0;
|
616
612
|
color: govuk-colour("white");
|
617
613
|
cursor: pointer;
|
@@ -619,6 +615,11 @@ $after-button-padding-left: govuk-spacing(4);
|
|
619
615
|
padding: govuk-spacing(3);
|
620
616
|
position: relative;
|
621
617
|
width: $search-width-or-height;
|
618
|
+
|
619
|
+
&.gem-c-layout-super-navigation-header__search-toggle-button--blue-background {
|
620
|
+
background: $govuk-brand-colour;
|
621
|
+
}
|
622
|
+
|
622
623
|
@include govuk-font($size: 19, $weight: "bold", $line-height: 20px);
|
623
624
|
|
624
625
|
@include focus-and-focus-visible {
|
data/app/assets/stylesheets/govuk_publishing_components/components/_search-with-autocomplete.scss
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
@import "govuk_publishing_components/individual_component_support";
|
2
|
+
|
3
|
+
// These styles are adapted from the original Accessible Autocomplete component stylesheet, mostly
|
4
|
+
// to remove superfluous styles that are already provided by the GOV.UK Design System, and to adapt
|
5
|
+
// the styling to match the new GOV.UK search box designs (e.g. to remove the zebra striping on
|
6
|
+
// rows, adjust whitespace, and manage the tweaked markup we use in the suggestion template).
|
7
|
+
//
|
8
|
+
// Note that most selectors targetted within this file are those constructed by the Accessible
|
9
|
+
// Autocomplete component, so they may not 100% match our own component conventions.
|
10
|
+
//
|
11
|
+
// see https://github.com/alphagov/accessible-autocomplete/blob/main/src/autocomplete.css
|
12
|
+
|
13
|
+
// Helps to make the autocomplete menu as wide as the entire search box _including_ the submit
|
14
|
+
// button, not just the width of the input field.
|
15
|
+
@mixin enhance-autocomplete-menu-width($button-size) {
|
16
|
+
margin-right: -$button-size;
|
17
|
+
}
|
18
|
+
|
19
|
+
$input-size: 40px;
|
20
|
+
$large-input-size: 50px;
|
21
|
+
|
22
|
+
.gem-c-search-with-autocomplete__wrapper {
|
23
|
+
position: relative;
|
24
|
+
}
|
25
|
+
|
26
|
+
.gem-c-search-with-autocomplete__menu {
|
27
|
+
margin: 0;
|
28
|
+
padding: 0;
|
29
|
+
overflow-x: hidden;
|
30
|
+
background-color: govuk-colour("white");
|
31
|
+
border: 1px solid $govuk-border-colour;
|
32
|
+
border-top: 0;
|
33
|
+
|
34
|
+
@include enhance-autocomplete-menu-width($input-size);
|
35
|
+
}
|
36
|
+
|
37
|
+
.gem-c-search-with-autocomplete__menu--visible {
|
38
|
+
display: block;
|
39
|
+
}
|
40
|
+
|
41
|
+
.gem-c-search-with-autocomplete__menu--hidden {
|
42
|
+
display: none;
|
43
|
+
}
|
44
|
+
|
45
|
+
.gem-c-search-with-autocomplete__menu--inline {
|
46
|
+
position: relative;
|
47
|
+
}
|
48
|
+
|
49
|
+
.gem-c-search-with-autocomplete__option {
|
50
|
+
display: block;
|
51
|
+
cursor: pointer;
|
52
|
+
|
53
|
+
@include govuk-font(19);
|
54
|
+
|
55
|
+
// Ensure only the option itself receives pointer events
|
56
|
+
& > * {
|
57
|
+
pointer-events: none;
|
58
|
+
}
|
59
|
+
|
60
|
+
// Accessible Autocomplete's iOS screenreader inset has broken CSS which hasn't been fixed
|
61
|
+
// upstream, and means that its text is not just visible to screenreader users, but displayed
|
62
|
+
// for everyone. This span is added dynamically only on iOS and not given a class, so we need to
|
63
|
+
// target it in a roundabout way and make it invisible to non-screenreader users.
|
64
|
+
& > span {
|
65
|
+
clip: rect(0 0 0 0);
|
66
|
+
clip-path: inset(50%);
|
67
|
+
height: 1px;
|
68
|
+
overflow: hidden;
|
69
|
+
position: absolute;
|
70
|
+
white-space: nowrap;
|
71
|
+
width: 1px;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
// Common styling for _all_ focus states, including keyboard focus, mouse hover, and keyboard focus
|
76
|
+
// but mouse on another option.
|
77
|
+
.gem-c-search-with-autocomplete__option--focused,
|
78
|
+
.gem-c-search-with-autocomplete__option:hover,
|
79
|
+
.gem-c-search-with-autocomplete__option:focus-visible {
|
80
|
+
background-color: govuk-colour("light-grey");
|
81
|
+
outline: none;
|
82
|
+
|
83
|
+
@include govuk-link-decoration;
|
84
|
+
@include govuk-link-hover-decoration;
|
85
|
+
|
86
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
87
|
+
background-color: $govuk-text-colour;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
// Styling specifically _only_ for keyboard focus
|
92
|
+
.gem-c-search-with-autocomplete__option:focus-visible {
|
93
|
+
.gem-c-search-with-autocomplete__suggestion-text {
|
94
|
+
background-color: $govuk-focus-colour;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
.gem-c-search-with-autocomplete__option-wrapper {
|
99
|
+
display: flex;
|
100
|
+
align-items: center;
|
101
|
+
margin: 0 govuk-spacing(3);
|
102
|
+
padding: govuk-spacing(1) 0;
|
103
|
+
border-bottom: 1px solid govuk-colour("mid-grey");
|
104
|
+
}
|
105
|
+
|
106
|
+
.gem-c-search-with-autocomplete__option:last-child .gem-c-search-with-autocomplete__option-wrapper {
|
107
|
+
border-bottom: 0;
|
108
|
+
}
|
109
|
+
|
110
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
111
|
+
width: calc($input-size / 2);
|
112
|
+
height: $input-size;
|
113
|
+
margin-right: govuk-spacing(2);
|
114
|
+
flex: none;
|
115
|
+
mask-image: url("govuk_publishing_components/icon-autocomplete-search-suggestion.svg");
|
116
|
+
-webkit-mask-image: url("govuk_publishing_components/icon-autocomplete-search-suggestion.svg");
|
117
|
+
background-color: $govuk-secondary-text-colour;
|
118
|
+
}
|
119
|
+
|
120
|
+
.gem-c-search-with-autocomplete__suggestion-text {
|
121
|
+
font-weight: bold;
|
122
|
+
}
|
123
|
+
|
124
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
125
|
+
font-weight: normal;
|
126
|
+
background: none;
|
127
|
+
}
|
128
|
+
|
129
|
+
// Tweak the look and feel for the autocomplete in large mode
|
130
|
+
.gem-c-search-with-autocomplete.gem-c-search-with-autocomplete--large {
|
131
|
+
.gem-c-search-with-autocomplete__menu {
|
132
|
+
@include enhance-autocomplete-menu-width($large-input-size);
|
133
|
+
}
|
134
|
+
|
135
|
+
.gem-c-search-with-autocomplete__option {
|
136
|
+
min-height: $large-input-size;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
// Fix top border styling on "borderless" search input when rendered on a GOV.UK blue background
|
141
|
+
.gem-c-search-with-autocomplete.gem-c-search-with-autocomplete--on-govuk-blue {
|
142
|
+
.gem-c-search-with-autocomplete__menu {
|
143
|
+
border-top: 1px solid $govuk-border-colour;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
// High contrast mode adjustments
|
148
|
+
@media (forced-colors: active) {
|
149
|
+
.gem-c-search-with-autocomplete__menu {
|
150
|
+
border-color: FieldText;
|
151
|
+
}
|
152
|
+
|
153
|
+
.gem-c-search-with-autocomplete__option {
|
154
|
+
forced-color-adjust: none; // opt out of all default forced-colors adjustments
|
155
|
+
background-color: Field;
|
156
|
+
color: FieldText;
|
157
|
+
}
|
158
|
+
|
159
|
+
.gem-c-search-with-autocomplete__option--focused,
|
160
|
+
.gem-c-search-with-autocomplete__option:hover,
|
161
|
+
.gem-c-search-with-autocomplete__option:focus-visible {
|
162
|
+
background-color: Highlight;
|
163
|
+
color: HighlightText;
|
164
|
+
border-color: FieldText;
|
165
|
+
|
166
|
+
.gem-c-search-with-autocomplete__suggestion-text {
|
167
|
+
background: none;
|
168
|
+
}
|
169
|
+
|
170
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
171
|
+
color: HighlightText;
|
172
|
+
}
|
173
|
+
|
174
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
175
|
+
background-color: HighlightText;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
// Allow mouse hover styling to take precedence over keyboard focus styling
|
180
|
+
.gem-c-search-with-autocomplete__option:focus-visible:not(:hover) {
|
181
|
+
background-color: SelectedItem;
|
182
|
+
color: SelectedItemText;
|
183
|
+
|
184
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
185
|
+
color: SelectedItemText;
|
186
|
+
}
|
187
|
+
|
188
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
189
|
+
background-color: SelectedItemText;
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
.gem-c-search-with-autocomplete__suggestion-highlight {
|
194
|
+
color: FieldText;
|
195
|
+
}
|
196
|
+
|
197
|
+
.gem-c-search-with-autocomplete__suggestion-icon {
|
198
|
+
background-color: FieldText;
|
199
|
+
}
|
200
|
+
}
|
@@ -8,58 +8,34 @@
|
|
8
8
|
product_name ||= nil
|
9
9
|
remove_bottom_border ||= false
|
10
10
|
search ||= false
|
11
|
-
search_left ||= false
|
12
11
|
width_class = full_width ? "govuk-header__container--full-width" : "govuk-width-container"
|
13
12
|
logo_link ||= "/"
|
14
13
|
|
15
14
|
header_classes = %w[gem-c-layout-header govuk-header]
|
16
15
|
header_classes << "gem-c-layout-header--#{environment}" if environment
|
17
16
|
header_classes << "gem-c-layout-header--no-bottom-border" if remove_bottom_border
|
18
|
-
header_classes << "gem-c-layout-header--search-left" if search_left
|
19
17
|
%>
|
20
18
|
|
21
19
|
<header class="<%= header_classes.join(' ') %>" role="banner" data-module="govuk-header">
|
22
20
|
<div class="govuk-header__container <%= width_class %>">
|
23
|
-
|
24
|
-
<div class="govuk-grid-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
} %>
|
31
|
-
</div>
|
21
|
+
<div class="govuk-grid-row">
|
22
|
+
<div class="gem-c-layout-header__logo govuk-grid-column-one-half">
|
23
|
+
<%= render "govuk_publishing_components/components/layout_header/header_logo", {
|
24
|
+
environment: environment,
|
25
|
+
logo_link: logo_link,
|
26
|
+
product_name: product_name,
|
27
|
+
} %>
|
32
28
|
</div>
|
33
|
-
|
34
|
-
<div class="govuk-
|
35
|
-
<%= render "govuk_publishing_components/components/layout_header/
|
29
|
+
<% if navigation_items.any? %>
|
30
|
+
<div class="govuk-header__content gem-c-header__content govuk-grid-column-full govuk-!-display-none-print">
|
31
|
+
<%= render "govuk_publishing_components/components/layout_header/navigation_items", navigation_items: navigation_items, navigation_aria_label: navigation_aria_label %>
|
36
32
|
</div>
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
<% end %>
|
42
|
-
</div>
|
43
|
-
<% else %>
|
44
|
-
<div class="govuk-grid-row">
|
45
|
-
<div class="gem-c-layout-header__logo govuk-grid-column-one-half">
|
46
|
-
<%= render "govuk_publishing_components/components/layout_header/header_logo", {
|
47
|
-
environment: environment,
|
48
|
-
logo_link: logo_link,
|
49
|
-
product_name: product_name,
|
50
|
-
} %>
|
33
|
+
<% end %>
|
34
|
+
<% if search %>
|
35
|
+
<div class="govuk-grid-column-one-half gem-c-layout-header__search govuk-!-display-none-print">
|
36
|
+
<%= render "govuk_publishing_components/components/layout_header/search" %>
|
51
37
|
</div>
|
52
|
-
|
53
|
-
|
54
|
-
<%= render "govuk_publishing_components/components/layout_header/navigation_items", navigation_items: navigation_items, navigation_aria_label: navigation_aria_label %>
|
55
|
-
</div>
|
56
|
-
<% end %>
|
57
|
-
<% if search %>
|
58
|
-
<div class="govuk-grid-column-one-half gem-c-layout-header__search govuk-!-display-none-print">
|
59
|
-
<%= render "govuk_publishing_components/components/layout_header/search" %>
|
60
|
-
</div>
|
61
|
-
<% end %>
|
62
|
-
</div>
|
63
|
-
<% end %>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
64
40
|
</div>
|
65
41
|
</header>
|
@@ -13,6 +13,8 @@
|
|
13
13
|
password_shown_announcement ||= t("components.password_input.password_shown_announcement")
|
14
14
|
password_hidden_announcement ||= t("components.password_input.password_hidden_announcement")
|
15
15
|
|
16
|
+
name ||= "password"
|
17
|
+
|
16
18
|
shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
|
17
19
|
component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
|
18
20
|
component_helper.add_data_attribute({
|
@@ -34,7 +36,6 @@
|
|
34
36
|
|
35
37
|
label_for = uid + '-password-input'
|
36
38
|
|
37
|
-
input_name = 'password'
|
38
39
|
input_id = uid + '-password-input'
|
39
40
|
|
40
41
|
aria_controls = uid + '-password-input'
|
@@ -42,9 +43,9 @@
|
|
42
43
|
input_classes = %w(govuk-input govuk-password-input__input govuk-js-password-input-input)
|
43
44
|
|
44
45
|
if error_text
|
46
|
+
name << '-input-with-error-message'
|
45
47
|
label_for << '-with-error-message'
|
46
48
|
input_id << '-with-error-message'
|
47
|
-
input_name << '-input-with-error-message'
|
48
49
|
input_classes << 'govuk-input--error'
|
49
50
|
aria_controls << '-with-error-message'
|
50
51
|
paragraph_id = uid + '-password-input-with-error-message-error'
|
@@ -64,7 +65,7 @@
|
|
64
65
|
|
65
66
|
<div class="govuk-input__wrapper govuk-password-input__wrapper">
|
66
67
|
<%= tag.input(
|
67
|
-
name
|
68
|
+
name:,
|
68
69
|
type: "password",
|
69
70
|
class: input_classes,
|
70
71
|
id: input_id,
|
@@ -61,20 +61,22 @@
|
|
61
61
|
<%= tag_label %>
|
62
62
|
<% end %>
|
63
63
|
<div class="gem-c-search__item-wrapper">
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
64
|
+
<div class="js-search-input-wrapper">
|
65
|
+
<%= tag.input(
|
66
|
+
aria: {
|
67
|
+
controls: aria_controls,
|
68
|
+
},
|
69
|
+
enterkeyhint: "search",
|
70
|
+
class: "gem-c-search__item gem-c-search__input js-class-toggle",
|
71
|
+
id: id,
|
72
|
+
name: name,
|
73
|
+
title: t("components.search_box.input_title"),
|
74
|
+
type: "search",
|
75
|
+
value: value,
|
76
|
+
autocorrect: correction_value,
|
77
|
+
autocapitalize: correction_value,
|
78
|
+
) %>
|
79
|
+
</div>
|
78
80
|
<div class="gem-c-search__item gem-c-search__submit-wrapper">
|
79
81
|
<%= tag.button class: "gem-c-search__submit", type: "submit", data: data_attributes, enterkeyhint: "search" do %>
|
80
82
|
<%= button_text %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%
|
2
|
+
add_gem_component_stylesheet("search-with-autocomplete")
|
3
|
+
|
4
|
+
source_url = local_assigns[:source_url]
|
5
|
+
source_key = local_assigns[:source_key]
|
6
|
+
|
7
|
+
if source_url.nil? || source_key.nil?
|
8
|
+
raise ArgumentError, "The search_with_autocomplete component requires source_url and source_key"
|
9
|
+
end
|
10
|
+
|
11
|
+
search_component_options = local_assigns.except(:autocomplete, :source_url, :source_key).merge(
|
12
|
+
# The `search` component has an inline label by default, but this conflicts with the accessible-
|
13
|
+
# autocomplete component's markup and styling. Every potential use of this component is in
|
14
|
+
# situations where we want the label not to be inline anyway, so we override the default here.
|
15
|
+
inline_label: false
|
16
|
+
)
|
17
|
+
|
18
|
+
classes = %w[gem-c-search-with-autocomplete]
|
19
|
+
classes << "gem-c-search-with-autocomplete--large" if local_assigns[:size] == "large"
|
20
|
+
classes << "gem-c-search-with-autocomplete--on-govuk-blue" if local_assigns[:on_govuk_blue]
|
21
|
+
%>
|
22
|
+
<%= tag.div(
|
23
|
+
class: classes.join(" "),
|
24
|
+
data: { module: "gem-search-with-autocomplete", source_url:, source_key: }
|
25
|
+
) do %>
|
26
|
+
<%= render "govuk_publishing_components/components/search", search_component_options %>
|
27
|
+
<% end %>
|
@@ -41,47 +41,6 @@ examples:
|
|
41
41
|
- text: Hidden on desktop
|
42
42
|
href: "item-3"
|
43
43
|
show_only_in_collapsed_menu: true
|
44
|
-
with_left_search_and_navigation:
|
45
|
-
description: This supports pages where the search appears on the left with multiple navigation links on the right, such as the [How government works](https://www.gov.uk/government/how-government-works) page
|
46
|
-
data:
|
47
|
-
search_left: true
|
48
|
-
navigation_items:
|
49
|
-
- text: Departments
|
50
|
-
href: "item-1"
|
51
|
-
- text: Worldwide
|
52
|
-
href: "item-2"
|
53
|
-
- text: How government works
|
54
|
-
href: "item-3"
|
55
|
-
- text: Get involved
|
56
|
-
href: "item-4"
|
57
|
-
- text: Consultations
|
58
|
-
href: "item-4"
|
59
|
-
- text: Statistics
|
60
|
-
href: "item-5"
|
61
|
-
- text: News and communications
|
62
|
-
href: "item-6"
|
63
|
-
active: true
|
64
|
-
with_custom_navigation_aria_label:
|
65
|
-
description: The navigation has `aria-label="Top level"` by default. This option is here for when the `aria-label` needs to be more descriptive than that.
|
66
|
-
data:
|
67
|
-
search_left: true
|
68
|
-
navigation_aria_label: "Departments and policy"
|
69
|
-
navigation_items:
|
70
|
-
- text: Departments
|
71
|
-
href: "item-1"
|
72
|
-
- text: Worldwide
|
73
|
-
href: "item-2"
|
74
|
-
- text: How government works
|
75
|
-
href: "item-3"
|
76
|
-
- text: Get involved
|
77
|
-
href: "item-4"
|
78
|
-
- text: Consultations
|
79
|
-
href: "item-4"
|
80
|
-
- text: Statistics
|
81
|
-
href: "item-5"
|
82
|
-
- text: News and communications
|
83
|
-
href: "item-6"
|
84
|
-
active: true
|
85
44
|
with_navigation_link_data_attributes:
|
86
45
|
description: Supports adding data attributes i.e for tracking
|
87
46
|
data:
|
@@ -28,6 +28,10 @@ uses_component_wrapper_helper: true
|
|
28
28
|
examples:
|
29
29
|
default:
|
30
30
|
data:
|
31
|
+
with_name:
|
32
|
+
description: If no name is provided, it defaults to "password".
|
33
|
+
data:
|
34
|
+
name: user[password]
|
31
35
|
with_error:
|
32
36
|
description: If there is a validation error, passing error text will style the password input component with error styles, and semantically state that there was a validation error.
|
33
37
|
data:
|
@@ -27,11 +27,15 @@ examples:
|
|
27
27
|
data:
|
28
28
|
phase: beta
|
29
29
|
inverse: true
|
30
|
+
context:
|
31
|
+
dark_background: true
|
30
32
|
inverse_for_blue_background_with_app_name:
|
31
33
|
data:
|
32
34
|
app_name: Skittles Maker
|
33
35
|
phase: beta
|
34
36
|
inverse: true
|
37
|
+
context:
|
38
|
+
dark_background: true
|
35
39
|
without_ga4_tracking:
|
36
40
|
description: |
|
37
41
|
Disables GA4 tracking on the banner. Tracking is enabled by default. This includes link tracking on the component itself, and allows pageviews to record the presence of the banner on page load.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
name: Search with autocomplete (experimental)
|
2
|
+
description: |
|
3
|
+
A version of the search component enhanced with the ability to fetch and display search
|
4
|
+
suggestions from a remote source as a user types.
|
5
|
+
body: |
|
6
|
+
This component uses [Accessible Autocomplete](https://github.com/alphagov/accessible-autocomplete)
|
7
|
+
to enhance the [`search` component's](/component-guide/search) input element.
|
8
|
+
If the user does not have JavaScript enabled, the search component will function as normal.
|
9
|
+
|
10
|
+
The Accessible Autocomplete component generates its own input field (rather than working on the
|
11
|
+
existing one). We then remove the old input field from the DOM, and enhance the component to:
|
12
|
+
|
13
|
+
* give it the correct attributes and classes from the original input field
|
14
|
+
* fetch suggestions from a remote URL as the user types
|
15
|
+
* highlight parts of suggestions where they match the user's input
|
16
|
+
* submit the form the component is contained in when a suggestion is selected
|
17
|
+
|
18
|
+
The component will fetch results from the provided `source_url`, which should always return a JSON
|
19
|
+
response with a single object at the root, which has a property `source_key` containing an array
|
20
|
+
of strings. The component will then display these strings as suggestions to the user.
|
21
|
+
|
22
|
+
Note that the inline label on the `search` component conflicts with the markup and styling
|
23
|
+
generated internally by Accessible Autocomplete. Our current designs do not foresee us using
|
24
|
+
autocomplete on a search box with an inline label, and this component will always force the
|
25
|
+
`inline_label` option on its nested `search` component to be `false`.
|
26
|
+
|
27
|
+
Note that this component has undergone a DAC audit in September 2024, but should be considered
|
28
|
+
experimental until it has been AB tested on GOV.UK.
|
29
|
+
accessibility_criteria: |
|
30
|
+
This component should meet the accessibility acceptance criteria outlined in the [nested search
|
31
|
+
component](/component-guide/search#accessibility-acceptance-criteria), as well as those of the
|
32
|
+
external [Accessible Autocomplete
|
33
|
+
Component](https://github.com/alphagov/accessible-autocomplete/blob/master/accessibility-criteria.md)
|
34
|
+
project.
|
35
|
+
examples:
|
36
|
+
default:
|
37
|
+
data:
|
38
|
+
source_url: 'https://www.gov.uk/api/search.json?suggest=autocomplete'
|
39
|
+
source_key: suggested_autocomplete
|
40
|
+
set_input_value:
|
41
|
+
data:
|
42
|
+
source_url: 'https://www.gov.uk/api/search.json?suggest=autocomplete'
|
43
|
+
source_key: suggested_autocomplete
|
44
|
+
value: "driving licence"
|
45
|
+
homepage:
|
46
|
+
description: For use on the homepage.
|
47
|
+
data:
|
48
|
+
source_url: 'https://www.gov.uk/api/search.json?suggest=autocomplete'
|
49
|
+
source_key: suggested_autocomplete
|
50
|
+
label_text: "Search"
|
51
|
+
on_govuk_blue: true
|
52
|
+
label_size: "s"
|
53
|
+
homepage: true
|
54
|
+
size: "large"
|
55
|
+
context:
|
56
|
+
dark_background: true
|
57
|
+
complex_custom_label:
|
58
|
+
data:
|
59
|
+
source_url: 'https://www.gov.uk/api/search.json?suggest=autocomplete'
|
60
|
+
source_key: suggested_autocomplete
|
61
|
+
label_text: <h2 class="govuk-heading-m govuk-!-margin-bottom-1">Search GOV.UK</h2>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_publishing_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 43.
|
4
|
+
version: 43.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_app_config
|
@@ -388,6 +388,7 @@ files:
|
|
388
388
|
- app/assets/images/govuk_publishing_components/govuk-schema-placeholder-16x9.png
|
389
389
|
- app/assets/images/govuk_publishing_components/govuk-schema-placeholder-1x1.png
|
390
390
|
- app/assets/images/govuk_publishing_components/govuk-schema-placeholder-4x3.png
|
391
|
+
- app/assets/images/govuk_publishing_components/icon-autocomplete-search-suggestion.svg
|
391
392
|
- app/assets/images/govuk_publishing_components/icon-close.svg
|
392
393
|
- app/assets/images/govuk_publishing_components/icon-file-download.svg
|
393
394
|
- app/assets/images/govuk_publishing_components/icon-important.svg
|
@@ -453,6 +454,7 @@ files:
|
|
453
454
|
- app/assets/javascripts/govuk_publishing_components/components/print-link.js
|
454
455
|
- app/assets/javascripts/govuk_publishing_components/components/radio.js
|
455
456
|
- app/assets/javascripts/govuk_publishing_components/components/reorderable-list.js
|
457
|
+
- app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js
|
456
458
|
- app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js
|
457
459
|
- app/assets/javascripts/govuk_publishing_components/components/skip-link.js
|
458
460
|
- app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js
|
@@ -541,6 +543,7 @@ files:
|
|
541
543
|
- app/assets/stylesheets/govuk_publishing_components/components/_radio.scss
|
542
544
|
- app/assets/stylesheets/govuk_publishing_components/components/_related-navigation.scss
|
543
545
|
- app/assets/stylesheets/govuk_publishing_components/components/_reorderable-list.scss
|
546
|
+
- app/assets/stylesheets/govuk_publishing_components/components/_search-with-autocomplete.scss
|
544
547
|
- app/assets/stylesheets/govuk_publishing_components/components/_search.scss
|
545
548
|
- app/assets/stylesheets/govuk_publishing_components/components/_secondary-navigation.scss
|
546
549
|
- app/assets/stylesheets/govuk_publishing_components/components/_select.scss
|
@@ -686,6 +689,7 @@ files:
|
|
686
689
|
- app/views/govuk_publishing_components/components/_related_navigation.html.erb
|
687
690
|
- app/views/govuk_publishing_components/components/_reorderable_list.html.erb
|
688
691
|
- app/views/govuk_publishing_components/components/_search.html.erb
|
692
|
+
- app/views/govuk_publishing_components/components/_search_with_autocomplete.html.erb
|
689
693
|
- app/views/govuk_publishing_components/components/_secondary_navigation.html.erb
|
690
694
|
- app/views/govuk_publishing_components/components/_select.html.erb
|
691
695
|
- app/views/govuk_publishing_components/components/_share_links.html.erb
|
@@ -779,6 +783,7 @@ files:
|
|
779
783
|
- app/views/govuk_publishing_components/components/docs/related_navigation.yml
|
780
784
|
- app/views/govuk_publishing_components/components/docs/reorderable_list.yml
|
781
785
|
- app/views/govuk_publishing_components/components/docs/search.yml
|
786
|
+
- app/views/govuk_publishing_components/components/docs/search_with_autocomplete.yml
|
782
787
|
- app/views/govuk_publishing_components/components/docs/secondary_navigation.yml
|
783
788
|
- app/views/govuk_publishing_components/components/docs/select.yml
|
784
789
|
- app/views/govuk_publishing_components/components/docs/share_links.yml
|