From c1da742aed998782ec0c9c5f5fe58abf47a3ec1a Mon Sep 17 00:00:00 2001 From: AdamChrimes Date: Tue, 16 Mar 2021 10:28:27 +0000 Subject: [PATCH] install latest version of the frontend library --- CHANGELOG.md | 1 + .../autocomplete/autoCompleteConfig.js | 62 ++++++ app/scripts/main.js | 2 +- app/styles/app/_app.scss | 1 + app/styles/app/_autocomplete.scss | 185 ++++++++++++++++++ app/views/includes/_header-prototype.njk | 6 +- app/views/includes/layout.njk | 2 +- app/views/includes/template.njk | 2 +- package-lock.json | 18 +- package.json | 3 +- 10 files changed, 263 insertions(+), 19 deletions(-) create mode 100644 app/scripts/autocomplete/autoCompleteConfig.js create mode 100644 app/styles/app/_autocomplete.scss diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ec52cd6..0d3c2050a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ :wrench **Fixes** - use maincontent as the ID for the main element across the NHS digital service manual and examples for consistency and to match the Skip link anchor (https://github.com/nhsuk/nhsuk-frontend/issues/716) +- use the latest version of NHS.UK frontend (v5.0.0) - update dependencies to the latest versions ## 3.13.0 - 11 March 2021 diff --git a/app/scripts/autocomplete/autoCompleteConfig.js b/app/scripts/autocomplete/autoCompleteConfig.js new file mode 100644 index 000000000..f0a453537 --- /dev/null +++ b/app/scripts/autocomplete/autoCompleteConfig.js @@ -0,0 +1,62 @@ +import AccessibleAutoComplete from 'accessible-autocomplete'; + +/** + @typedef autocompleteConfig + @type {Object} + Optional param for NHS.UK functionality + @property {string=} formId ID of form element containing autocomplete. + Required params for accessible-autocomplete + @property {string} inputId ID of the input field. + @property {string} containerId ID of element in which the autocomplete will be rendered in. + @property {function} source Function called on input change +*/ + +/** + * Create an autocomplete. + * @param {autocompleteConfig} config +*/ +export default (config) => { + const { formId, inputId, containerId } = config; + + const form = document.getElementById(formId); + const input = document.getElementById(inputId); + const container = document.getElementById(containerId); + + /** + * Adds event to catch enter presses when the main input is focused and submits the form + */ + const addFormEvents = () => { + // Attach event to form as the original input element is cloned by autoComplete plugin + form.addEventListener('keyup', ({ key }) => { + // Submit search using current input value if input is focused and enter is pressed + if (key === 'Enter' && document.activeElement.id === inputId) form.submit(); + }); + }; + + const initAutoComplete = () => { + const defaultConfig = { + confirmOnBlur: false, + element: container, + id: inputId, + minLength: 2, + name: input.name, + placeholder: input.placeholder, + }; + + // Remove original search input as it will be replaced by accessibleAutocomplete + input.parentNode.removeChild(input); + + // Initialise accessibleAutocomplete + AccessibleAutoComplete({ + ...defaultConfig, + ...config, + }); + }; + + // Add autocomplete functionality if required config options exist + if (input && container && config.source) { + initAutoComplete(); + // If form element exists then add events to add standard form functionality + if (form) addFormEvents(); + } +}; diff --git a/app/scripts/main.js b/app/scripts/main.js index 8b3b592e5..8fa2437c1 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,8 +1,8 @@ /* eslint-disable no-new */ // NHS.UK frontend components -import AutoComplete from 'nhsuk-frontend/packages/components/header/autoCompleteConfig'; import MenuToggle from 'nhsuk-frontend/packages/components/header/menuToggle'; import SearchToggle from 'nhsuk-frontend/packages/components/header/searchToggle'; +import AutoComplete from './autocomplete/autoCompleteConfig'; import SkipLink from '../../node_modules/nhsuk-frontend/packages/components/skip-link/skip-link'; import Details from '../../node_modules/nhsuk-frontend/packages/components/details/details'; import Checkboxes from '../../node_modules/nhsuk-frontend/packages/components/checkboxes/checkboxes'; diff --git a/app/styles/app/_app.scss b/app/styles/app/_app.scss index f160d930e..047064a5c 100755 --- a/app/styles/app/_app.scss +++ b/app/styles/app/_app.scss @@ -1,4 +1,5 @@ @import 'app-reading-width'; +@import 'autocomplete'; @import 'beta-banner'; @import 'code-block'; @import 'code-highlight'; diff --git a/app/styles/app/_autocomplete.scss b/app/styles/app/_autocomplete.scss new file mode 100644 index 000000000..120356f11 --- /dev/null +++ b/app/styles/app/_autocomplete.scss @@ -0,0 +1,185 @@ +/* ========================================================================== + COMPONENTS / #HEADER / #AUTOCOMPLETE + ========================================================================== */ + +/** + * 1. IE 10 prefix for flexbox + * 2. Proprietary extension so form field looks the same in Safari + * 3. Custom height and width of form items + * 4. Custom height and width of svg icons + * 5. Custom spacing to position the search icon + * 6. Drop shadow on search suggestions dopdown box, custom spread and blur + * 7. Z-index to bring the dropdown to the front + * 8. No current spacing at 12px so using this value + * 9. Z-index to being search box to the front for focus state style + * 10. Custom padding to stop text jumping on focus +*/ + +.autocomplete-container { + display: inline-block; + z-index: 1; /* [9] */ + + @include mq($until: tablet) { + display: inline; + width: 100%; + } +} + +@include mq($until: tablet) { + /* duplicate of .nhsuk-search__input in _header.scss, for non javascript version */ + .autocomplete__input { + -ms-flex-positive: 2; /* [1] */ + -webkit-appearance: listbox; // sass-lint:disable-line prefixes /* [2] */ + border-bottom: 1px solid $color_nhsuk-grey-3; + border-bottom-left-radius: $nhsuk-border-radius; + border-bottom-right-radius: 0; + border-left: 1px solid $color_nhsuk-grey-3; + border-right: 0; + border-top: 1px solid $color_nhsuk-grey-3; + border-top-left-radius: $nhsuk-border-radius; + border-top-right-radius: 0; + flex-grow: 2; + font-size: inherit; + height: 52px; /* [3] */ + margin: 0; + outline: none; + padding: 0 nhsuk-spacing(3); + width: 100%; /* [3] */ + + &:focus { + border: $nhsuk-focus-width solid $nhsuk-focus-text-color; + box-shadow: 0 0 0 $nhsuk-focus-width $nhsuk-focus-color; + outline: $nhsuk-focus-width solid transparent; + outline-offset: $nhsuk-focus-width; + padding: 0 13px; /* [10] */ + } + } +} + +@include mq($from: tablet) { + /* duplicate of .nhsuk-search__input in _header.scss, for non javascript version */ + .autocomplete__input { + -webkit-appearance: listbox; // sass-lint:disable-line prefixes /* [2] */ + border: 1px solid $color_nhsuk-white; + border-bottom-left-radius: $nhsuk-border-radius; + border-bottom-right-radius: 0; + border-right: 0; + border-top-left-radius: $nhsuk-border-radius; + border-top-right-radius: 0; + font-size: $nhsuk-base-font-size; + height: 40px; /* [3] */ + padding: 0 12px; /* [9] */ + width: 200px; /* [3] */ + + &:focus { + border: 2px solid $nhsuk-focus-text-color; + box-shadow: 0 0 0 $nhsuk-focus-width $nhsuk-focus-color; + outline: $nhsuk-focus-width solid transparent; + outline-offset: $nhsuk-focus-width; + padding: 0 11px; /* [10] */ + } + + &::placeholder { + color: $color_nhsuk-grey-2; + font-size: $nhsuk-base-font-size; + } + } +} + +@include mq($from: desktop) { + .autocomplete__input { + width: 235px; + } +} + +.autocomplete__menu { + // sass-lint:disable-block no-vendor-prefixes, no-color-literals + -moz-box-shadow: 0 3px 5px rgba($nhsuk-box-shadow-color, $alpha-transparency-50); /* [6] */ + -webkit-box-shadow: 0 3px 5px rgba($nhsuk-box-shadow-color, $alpha-transparency-50); /* [6] */ + background-color: $color_nhsuk-white; + border-bottom: 1px solid $color_nhsuk-grey-4; + border-bottom-left-radius: $nhsuk-border-radius; + border-bottom-right-radius: $nhsuk-border-radius; + border-left: 1px solid $color_nhsuk-grey-4; + border-right: 1px solid $color_nhsuk-grey-4; + box-shadow: 0 0 ($nhsuk-box-shadow-spread - 1) 0 rgba($nhsuk-box-shadow-color, $alpha-transparency-50); /* [6] */ + list-style: none; + margin-top: 2px; + overflow-x: hidden; + overflow-y: auto; + padding: nhsuk-spacing(3); + position: absolute; + top: 100%; + width: 100%; + z-index: 1; /* [7] */ + + @include mq($until: tablet) { + border: 0; + box-shadow: none; + margin: 0; + padding-left: 0; + padding-right: 0; + position: relative; + } +} + +.autocomplete__menu--visible { + display: block; +} + +.autocomplete__menu--hidden { + display: none; +} + +.autocomplete__option { + border-bottom: 1px solid $color_nhsuk-grey-5; + color: $color_nhsuk-blue; + cursor: pointer; + font-size: $nhsuk-base-font-size; + padding-bottom: 12px; /* [8] */ + text-align: left; + text-decoration: underline; + + .nhsuk-icon__search { + fill: $color_nhsuk-grey-3; + float: left; + height: 22px; /* [4] */ + margin: 2px 4px 0 0; /* [5] */ + width: 22px; /* [4] */ + } + + &:hover, + &:active { + text-decoration: none; + } + + &:focus { + outline: 1px solid transparent; + text-decoration: none; + + a { + @include nhsuk-focused-text(); + } + } + + @include mq($from: tablet) { + &:last-child { + border-bottom: 0; + } + } +} + +.autocomplete__option--no-results { + border-bottom: 0; + color: $color_nhsuk-black; + font-size: $nhsuk-base-font-size; + line-height: $nhsuk-base-line-height; + margin: 0; + padding: 0; + text-align: left; + text-decoration: none; + + @include mq($until: tablet) { + padding: nhsuk-spacing(3) 0; + } +} diff --git a/app/views/includes/_header-prototype.njk b/app/views/includes/_header-prototype.njk index a66957489..d72fed921 100644 --- a/app/views/includes/_header-prototype.njk +++ b/app/views/includes/_header-prototype.njk @@ -12,10 +12,9 @@