From 388a5716952d28c0c19600d952e4af147c4d86a2 Mon Sep 17 00:00:00 2001 From: Zak Faithfull Date: Thu, 1 Aug 2024 21:18:25 +0100 Subject: [PATCH 1/2] add dropdown nav --- assets/js/all.js | 52 ++++++- assets/scss/components/_header-bar.scss | 166 +++++++++++++++++----- server/views/components/nav/macro.njk | 26 ++++ server/views/partials/header.njk | 42 +++--- server/views/partials/homepage-layout.njk | 2 +- server/views/partials/layout.njk | 2 +- 6 files changed, 234 insertions(+), 56 deletions(-) create mode 100644 server/views/components/nav/macro.njk diff --git a/assets/js/all.js b/assets/js/all.js index ff6d7505..ac1991f1 100644 --- a/assets/js/all.js +++ b/assets/js/all.js @@ -1,4 +1,54 @@ document.addEventListener('DOMContentLoaded', () => { + initHeader() + initCardToggle() +}) + +const tabOpenClass = 'launchpad-home-header__toggle-open' + +function initHeader() { + const userToggle = document.querySelector('.launchpad-home-header__user-menu-toggle') + const userMenu = document.getElementById('launchpad-home-header-user-menu') + + if (userToggle && userMenu) { + userToggle.removeAttribute('hidden') + + closeTabs([[userToggle, userMenu]]) + + userToggle.addEventListener('click', () => { + toggleMenu(userToggle, userMenu) + }) + } +} + +function closeTabs(tabTuples) { + tabTuples.forEach(([toggle, menu]) => { + if (menu) { + menu.setAttribute('hidden', 'hidden') + if (toggle) { + toggle.classList.remove(tabOpenClass) + toggle.parentElement.classList.remove('item-open') + toggle.setAttribute('aria-expanded', 'false') + } + } + }) +} + +function toggleMenu(toggle, menu) { + if (menu) { + const isOpen = !menu.hasAttribute('hidden') + + if (isOpen) { + closeTabs([[toggle, menu]]) + } else { + menu.removeAttribute('hidden') + toggle.classList.add(tabOpenClass) + toggle.parentElement.classList.add('item-open') + toggle.setAttribute('aria-expanded', 'true') + } + } +} + +function initCardToggle() { const cards = document.querySelectorAll('.card--clickable.toggle-sensitive') cards.forEach(card => { @@ -16,4 +66,4 @@ document.addEventListener('DOMContentLoaded', () => { } }) }) -}) +} diff --git a/assets/scss/components/_header-bar.scss b/assets/scss/components/_header-bar.scss index 392cc152..5e3cbe8c 100644 --- a/assets/scss/components/_header-bar.scss +++ b/assets/scss/components/_header-bar.scss @@ -1,6 +1,4 @@ -.hmpps-header { - @include govuk-responsive-padding(3, 'top'); - @include govuk-responsive-padding(3, 'bottom'); +.launchpad-home-header { background-color: govuk-colour('black'); &__container { @@ -72,35 +70,153 @@ } } + &__submenu-link { + @include govuk-link-common; + @include govuk-link-style-no-visited-state; + } + &__navigation { + height: 70px; display: flex; - flex-direction: row; - align-items: flex-end; list-style: none; margin: 0; padding: 0; align-items: center; &__item { - @include govuk-font(19); - margin-bottom: govuk-spacing(1); - text-align: right; - border-right: 1px solid govuk-colour('white'); - @include govuk-responsive-margin(4, 'right'); - @include govuk-responsive-padding(4, 'right'); - - a { - display: inline-block; + height: 100%; + position: relative; + + > button, + > a { + display: flex; + align-items: center; + justify-content: center; + padding: 0; + border: none; + cursor: pointer; + color: govuk-colour('white'); + background: govuk-colour('black'); + @include govuk-font(16); + height: 100%; + + &:hover { + color: govuk-colour('mid-grey') !important; + + &:after { + background: govuk-colour('mid-grey'); + content: ''; + height: 3px; + position: absolute; + bottom: 0; + left: 15px; + right: 15px; + } + } + + &.launchpad-home-header__menu-toggle { + padding: 10px 0; + + > span { + height: 100%; + padding: 0 15px; + display: flex; + align-items: center; + + &:before { + transform: translateY(-35%) rotate(45deg) scale(1); + border-bottom: 2px solid govuk-colour('white'); + border-right: 2px solid govuk-colour('white'); + content: ''; + display: inline-block; + height: 8px; + margin: 3px 15px 0 3px; + vertical-align: middle; + width: 8px; + } + } + + svg { + margin: 0 15px 0 0; + } + + &:hover > span:before { + border-bottom: 2px solid govuk-colour('mid-grey'); + border-right: 2px solid govuk-colour('mid-grey'); + } + } + + &.launchpad-home-header__toggle-open { + background: govuk-colour('light-grey'); + color: govuk-colour('blue'); + + > span:before { + transform: translateY(0) rotate(225deg) scale(1); + border-bottom: 2px solid govuk-colour('blue'); + border-right: 2px solid govuk-colour('blue'); + } + + &:after { + background: govuk-colour('blue'); + content: ''; + height: 3px; + position: absolute; + bottom: 0; + left: 15px; + right: 15px; + } + + &:hover { + color: govuk-colour('dark-grey') !important; + } + } + + &:focus-visible { + outline: 3px solid transparent; + color: govuk-colour('black'); + background-color: govuk-colour('yellow'); + text-decoration: none; + box-shadow: none; + + &:after { + background: govuk-colour('black'); + content: ''; + height: 3px; + position: absolute; + bottom: 0; + left: 15px; + right: 15px; + } + + > span:before { + border-bottom: 2px solid govuk-colour('black'); + border-right: 2px solid govuk-colour('black'); + } + } } - &:last-child { - margin-right: 0; - border-right: 0; - padding-right: 0; + &.item-open + div > button, + &.item-open + div > a { + > span { + border-left: 1px solid transparent; + } } } } + &__user-menu { + position: relative; + z-index: 10000000; + padding: 15px; + background: govuk-colour('light-grey'); + + a { + font-weight: 700; + display: block; + margin-bottom: 15px; + } + } + @media print { display: none; } @@ -131,17 +247,3 @@ display: none; } } - -#user-name { - background-image: url('/assets/images/icon-profile.svg'); - background-repeat: no-repeat; - background-size: 22px; - @include govuk-media-query($from: tablet) { - background-size: 27px 25px; - } - - span { - margin-left: 2em; - color: govuk-colour('white'); - } -} diff --git a/server/views/components/nav/macro.njk b/server/views/components/nav/macro.njk new file mode 100644 index 00000000..01c011bd --- /dev/null +++ b/server/views/components/nav/macro.njk @@ -0,0 +1,26 @@ +{% macro govukNav(user, userSvg) %} + {% if user %} + + {% endif %} +{% endmacro %} + diff --git a/server/views/partials/header.njk b/server/views/partials/header.njk index 331c0326..3594a047 100644 --- a/server/views/partials/header.njk +++ b/server/views/partials/header.njk @@ -1,31 +1,31 @@ - diff --git a/server/views/partials/homepage-layout.njk b/server/views/partials/homepage-layout.njk index c2e738ea..ebc224c7 100644 --- a/server/views/partials/homepage-layout.njk +++ b/server/views/partials/homepage-layout.njk @@ -21,6 +21,6 @@ {# Run JavaScript at end of the , to avoid blocking the initial render. #} - + {% endblock %} diff --git a/server/views/partials/layout.njk b/server/views/partials/layout.njk index 69259673..f484f804 100644 --- a/server/views/partials/layout.njk +++ b/server/views/partials/layout.njk @@ -19,6 +19,6 @@ {% block bodyEnd %} - + {% endblock %} From d8f47176b3c7ed5236460ce941284d3590b66b3d Mon Sep 17 00:00:00 2001 From: Zak Faithfull Date: Wed, 14 Aug 2024 15:30:40 +0100 Subject: [PATCH 2/2] update js --- assets/js/all.js | 64 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/assets/js/all.js b/assets/js/all.js index 334100e9..f9b0ee4f 100644 --- a/assets/js/all.js +++ b/assets/js/all.js @@ -1,13 +1,12 @@ document.addEventListener('DOMContentLoaded', () => { - initializeCardClickHandlers() - initializeDeleteButtonHandler() + initCardClickHandlers() + initDeleteButtonHandler() + initHeader() }) -function initializeCardClickHandlers() { +function initCardClickHandlers() { const cards = document.querySelectorAll('.card--clickable.toggle-sensitive') - cards.forEach(card => { - card.addEventListener('click', handleCardClick) - }) + cards.forEach(card => card.addEventListener('click', handleCardClick)) } function handleCardClick(event) { @@ -25,20 +24,59 @@ function handleCardClick(event) { } } -function initializeDeleteButtonHandler() { +function initDeleteButtonHandler() { const yesButton = document.getElementById('remove-access__button-yes') const noButton = document.getElementById('remove-access__button-no') const actionInput = document.getElementById('action-input') if (yesButton) { - yesButton.addEventListener('click', () => { - actionInput.value = 'remove' - }) + yesButton.addEventListener('click', () => (actionInput.value = 'remove')) } if (noButton) { - noButton.addEventListener('click', () => { - actionInput.value = 'cancel' - }) + noButton.addEventListener('click', () => (actionInput.value = 'cancel')) + } +} + +function initHeader() { + const userToggle = document.querySelector('.launchpad-home-header__user-menu-toggle') + const userMenu = document.getElementById('launchpad-home-header-user-menu') + + if (userToggle && userMenu) { + userToggle.removeAttribute('hidden') + + initCloseTabs([[userToggle, userMenu]]) + + userToggle.addEventListener('click', () => toggleMenu(userToggle, userMenu)) } } + +function initCloseTabs(tabTuples) { + tabTuples.forEach(([toggle, menu]) => { + if (menu) { + menu.setAttribute('hidden', 'hidden') + if (toggle) { + toggle.classList.remove(tabOpenClass) + toggle.parentElement.classList.remove('item-open') + toggle.setAttribute('aria-expanded', 'false') + } + } + }) +} + +function toggleMenu(toggle, menu) { + if (menu) { + const isOpen = !menu.hasAttribute('hidden') + + if (isOpen) { + initCloseTabs([[toggle, menu]]) + } else { + menu.removeAttribute('hidden') + toggle.classList.add(tabOpenClass) + toggle.parentElement.classList.add('item-open') + toggle.setAttribute('aria-expanded', 'true') + } + } +} + +const tabOpenClass = 'launchpad-home-header__toggle-open'