From a74403b607e97971e068a00e67dc2f4c8d85c02f Mon Sep 17 00:00:00 2001 From: Charlotte Downs Date: Mon, 28 Oct 2024 15:07:47 +0000 Subject: [PATCH 1/9] add example service nav component --- config/navigation.js | 24 ++++++++++++----- src/javascripts/application.mjs | 9 ++++++- src/stylesheets/main.scss | 4 ++- views/partials/_navigation.njk | 48 +++------------------------------ 4 files changed, 33 insertions(+), 52 deletions(-) diff --git a/config/navigation.js b/config/navigation.js index 2ee18bcf98..6540d40c30 100644 --- a/config/navigation.js +++ b/config/navigation.js @@ -6,27 +6,39 @@ const config = [ { label: 'Get started', - url: 'get-started' + url: 'get-started', + text: 'Get started', + href: '/get-started' }, { label: 'Styles', - url: 'styles' + url: 'styles', + text: 'Styles', + href: 'styles' }, { label: 'Components', - url: 'components' + url: 'components', + text: 'Components', + href: 'components' }, { label: 'Patterns', - url: 'patterns' + url: 'patterns', + text: 'Patterns', + href: 'patterns' }, { label: 'Community', - url: 'community' + url: 'community', + text: 'Community', + href: 'community' }, { label: 'Accessibility', - url: 'accessibility' + url: 'accessibility', + text: 'Accessibility', + href: 'accessibility' } ] diff --git a/src/javascripts/application.mjs b/src/javascripts/application.mjs index 0039759f75..878882e013 100644 --- a/src/javascripts/application.mjs +++ b/src/javascripts/application.mjs @@ -1,6 +1,12 @@ /* eslint-disable no-new */ -import { createAll, Button, NotificationBanner, SkipLink } from 'govuk-frontend' +import { + createAll, + Button, + NotificationBanner, + ServiceNavigation, + SkipLink +} from 'govuk-frontend' import { loadAnalytics } from './components/analytics.mjs' import BackToTop from './components/back-to-top.mjs' @@ -23,6 +29,7 @@ import AppTabs from './components/tabs.mjs' // Initialise GOV.UK Frontend createAll(Button) createAll(NotificationBanner) +createAll(ServiceNavigation) createAll(SkipLink) // Cookies and analytics diff --git a/src/stylesheets/main.scss b/src/stylesheets/main.scss index 9099717b9c..b52fe5f6b9 100644 --- a/src/stylesheets/main.scss +++ b/src/stylesheets/main.scss @@ -26,6 +26,7 @@ $govuk-new-typography-scale: true; @import "govuk/components/panel"; @import "govuk/components/phase-banner"; @import "govuk/components/radios"; +@import "govuk/components/service-navigation"; @import "govuk/components/skip-link"; @import "govuk/components/summary-list"; @import "govuk/components/table"; @@ -69,7 +70,8 @@ $app-code-color: #d13118; @import "components/table"; // We don't change the global width container width so that examples are the current width. -.app-width-container { +.app-width-container, +.govuk-service-navigation .govuk-width-container { @include govuk-width-container(1100px); } diff --git a/views/partials/_navigation.njk b/views/partials/_navigation.njk index 92c6aff795..cd7282bddb 100644 --- a/views/partials/_navigation.njk +++ b/views/partials/_navigation.njk @@ -1,45 +1,5 @@ - +{{ govukServiceNavigation({ + navigation: navigation +}) }} \ No newline at end of file From be78ae2c75bbaf0d582e09b7ac18357d34c88381 Mon Sep 17 00:00:00 2001 From: Patrick Cartlidge Date: Thu, 5 Dec 2024 15:19:49 +0000 Subject: [PATCH 2/9] get current section working --- config/navigation.js | 10 +++++----- views/partials/_navigation.njk | 12 +++++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/config/navigation.js b/config/navigation.js index 6540d40c30..ead1e365b2 100644 --- a/config/navigation.js +++ b/config/navigation.js @@ -14,31 +14,31 @@ const config = [ label: 'Styles', url: 'styles', text: 'Styles', - href: 'styles' + href: '/styles' }, { label: 'Components', url: 'components', text: 'Components', - href: 'components' + href: '/components' }, { label: 'Patterns', url: 'patterns', text: 'Patterns', - href: 'patterns' + href: '/patterns' }, { label: 'Community', url: 'community', text: 'Community', - href: 'community' + href: '/community' }, { label: 'Accessibility', url: 'accessibility', text: 'Accessibility', - href: 'accessibility' + href: '/accessibility' } ] diff --git a/views/partials/_navigation.njk b/views/partials/_navigation.njk index cd7282bddb..3af02ba5d5 100644 --- a/views/partials/_navigation.njk +++ b/views/partials/_navigation.njk @@ -1,5 +1,15 @@ {% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} +{% set navigationItems = [] %} + +{% for item in navigation %} + {% set navigationItems = navigationItems.concat({ + href: item.href, + text: item.text, + current: permalink and permalink.startsWith(item.url) + }) %} +{% endfor %} + {{ govukServiceNavigation({ - navigation: navigation + navigation: navigationItems }) }} \ No newline at end of file From 8e7365a24c363407e74baa7adf98bad61ffc47ec Mon Sep 17 00:00:00 2001 From: Patrick Cartlidge Date: Fri, 6 Dec 2024 12:06:28 +0000 Subject: [PATCH 3/9] link html --- views/partials/_navigation.njk | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/views/partials/_navigation.njk b/views/partials/_navigation.njk index 3af02ba5d5..829fe17c93 100644 --- a/views/partials/_navigation.njk +++ b/views/partials/_navigation.njk @@ -6,8 +6,18 @@ {% set navigationItems = navigationItems.concat({ href: item.href, text: item.text, - current: permalink and permalink.startsWith(item.url) + active: permalink and permalink.startsWith(item.url), + current: permalink === item.url }) %} + {% if permalink and permalink.startsWith(item.url) %} + {% for subItem in item.items %} + {% set navigationItems = navigationItems.concat({ + text: subItem.label, + current: permalink === subItem.url, + html: '' + subItem.label + '' + }) %} + {% endfor %} + {% endif %} {% endfor %} {{ govukServiceNavigation({ From 142d49eced0b1910e7c101b8a9b5de0d352ad2a1 Mon Sep 17 00:00:00 2001 From: Patrick Cartlidge Date: Mon, 9 Dec 2024 16:41:41 +0000 Subject: [PATCH 4/9] diff approach --- src/stylesheets/main.scss | 8 ++++++++ views/partials/_navigation.njk | 14 ++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/stylesheets/main.scss b/src/stylesheets/main.scss index b52fe5f6b9..af7ef73945 100644 --- a/src/stylesheets/main.scss +++ b/src/stylesheets/main.scss @@ -69,6 +69,14 @@ $app-code-color: #d13118; @import "components/tabs"; @import "components/table"; +.app-nav-subitems-mobile { + @include govuk-media-query($from: tablet) { + display: none; + } + + background-color: govuk-colour("mid-grey"); +} + // We don't change the global width container width so that examples are the current width. .app-width-container, .govuk-service-navigation .govuk-width-container { diff --git a/views/partials/_navigation.njk b/views/partials/_navigation.njk index 829fe17c93..a8a52f7071 100644 --- a/views/partials/_navigation.njk +++ b/views/partials/_navigation.njk @@ -1,6 +1,7 @@ {% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} {% set navigationItems = [] %} +{% set subNavigationItems = ["
    "] %} {% for item in navigation %} {% set navigationItems = navigationItems.concat({ @@ -11,15 +12,16 @@ }) %} {% if permalink and permalink.startsWith(item.url) %} {% for subItem in item.items %} - {% set navigationItems = navigationItems.concat({ - text: subItem.label, - current: permalink === subItem.url, - html: '' + subItem.label + '' - }) %} + {% set subNavigationItems = subNavigationItems.concat('
  • ' + subItem.label + '
  • ') %} {% endfor %} + {% set subNavigationItems = subNavigationItems.concat('
') %} + {% set subNavigationItems = subNavigationItems | join %} {% endif %} {% endfor %} {{ govukServiceNavigation({ - navigation: navigationItems + navigation: navigationItems, + slots: { + navigationEnd: subNavigationItems + } }) }} \ No newline at end of file From 97c632f2e15ad4ef48b39202c8aa7817486c7e69 Mon Sep 17 00:00:00 2001 From: Patrick Cartlidge Date: Mon, 16 Dec 2024 14:46:05 +0000 Subject: [PATCH 5/9] partials for accoridon within nav --- views/partials/_navigation.njk | 38 +++++++++++++----------- views/partials/_sub-navigation-items.njk | 13 ++++++++ 2 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 views/partials/_sub-navigation-items.njk diff --git a/views/partials/_navigation.njk b/views/partials/_navigation.njk index a8a52f7071..c1e8b6d92f 100644 --- a/views/partials/_navigation.njk +++ b/views/partials/_navigation.njk @@ -1,27 +1,31 @@ {% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} +{% from "_sub-navigation-items.njk" import subNavigationItems %} {% set navigationItems = [] %} -{% set subNavigationItems = ["
    "] %} {% for item in navigation %} - {% set navigationItems = navigationItems.concat({ - href: item.href, - text: item.text, - active: permalink and permalink.startsWith(item.url), - current: permalink === item.url - }) %} - {% if permalink and permalink.startsWith(item.url) %} - {% for subItem in item.items %} - {% set subNavigationItems = subNavigationItems.concat('
  • ' + subItem.label + '
  • ') %} - {% endfor %} - {% set subNavigationItems = subNavigationItems.concat('
') %} - {% set subNavigationItems = subNavigationItems | join %} + {% set navItem = {} %} + + {% if item.items %} + {% set subNavItemHtml = subNavigationItems({ items: item.items }) %} + {% set navItem = { + href: item.href, + html: item.text + '', + active: permalink and permalink.startsWith(item.url), + current: permalink === item.url + } %} + {% else %} + {% set navItem = { + href: item.href, + html: item.text, + active: permalink and permalink.startsWith(item.url), + current: permalink === item.url + } %} {% endif %} + + {% set navigationItems = navigationItems.concat(navItem) %} {% endfor %} {{ govukServiceNavigation({ - navigation: navigationItems, - slots: { - navigationEnd: subNavigationItems - } + navigation: navigationItems }) }} \ No newline at end of file diff --git a/views/partials/_sub-navigation-items.njk b/views/partials/_sub-navigation-items.njk new file mode 100644 index 0000000000..22061a7d0d --- /dev/null +++ b/views/partials/_sub-navigation-items.njk @@ -0,0 +1,13 @@ +{% macro subNavigationItems(params) %} + {% if params.items %} + + {% endif %} +{% endmacro %} \ No newline at end of file From d18d80ca0314c005db69f8416feca64207029245 Mon Sep 17 00:00:00 2001 From: Patrick Cartlidge Date: Mon, 16 Dec 2024 14:46:22 +0000 Subject: [PATCH 6/9] js functionality of accoridon within nav --- src/javascripts/application.mjs | 6 +- .../components/mobile-navigation.mjs | 102 ++++++++++++++++++ .../components/_mobile-navigation.scss | 44 ++++++++ src/stylesheets/components/_navigation.scss | 10 ++ src/stylesheets/main.scss | 1 + views/partials/_mobile-navigation.njk | 13 +++ views/partials/_navigation.njk | 14 +-- views/partials/_sub-navigation-items.njk | 2 +- 8 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 src/javascripts/components/mobile-navigation.mjs create mode 100644 src/stylesheets/components/_mobile-navigation.scss create mode 100644 views/partials/_mobile-navigation.njk diff --git a/src/javascripts/application.mjs b/src/javascripts/application.mjs index 878882e013..758d2e5e49 100644 --- a/src/javascripts/application.mjs +++ b/src/javascripts/application.mjs @@ -20,7 +20,7 @@ import CookiesPage from './components/cookies-page.mjs' import Copy from './components/copy.mjs' import EmbedCard from './components/embed-card.mjs' import ExampleFrame from './components/example-frame.mjs' -import Navigation from './components/navigation.mjs' +import MobileNavigation from './components/mobile-navigation.mjs' import OptionsTable from './components/options-table.mjs' import ScrollContainer from './components/scroll-container.mjs' import Search from './components/search.mjs' @@ -54,8 +54,8 @@ createAll(AppTabs) createAll(Copy) new OptionsTable() -// Initialise mobile navigation -createAll(Navigation) +// Initialise mobile navigation (again) +createAll(MobileNavigation) // Initialise scrollable container handling createAll(ScrollContainer) diff --git a/src/javascripts/components/mobile-navigation.mjs b/src/javascripts/components/mobile-navigation.mjs new file mode 100644 index 0000000000..5552524399 --- /dev/null +++ b/src/javascripts/components/mobile-navigation.mjs @@ -0,0 +1,102 @@ +import { Component } from 'govuk-frontend' + +/** + * Mobile Navigation enhancement for Service Navigation component + */ +class MobileNavigation extends Component { + static moduleName = 'app-mobile-navigation' + + /** + * @param {Element} $root - HTML element + */ + constructor($root) { + super($root) + + this.templates = this.$root.querySelectorAll( + '.app-mobile-navigation__template' + ) + this.links = this.$root.querySelectorAll('a') + + Array.from(this.templates).forEach((template) => { + const templateClone = template.content.cloneNode(true) + let link + + if (template.parentNode.tagName === 'A') { + link = template.parentNode + link.removeChild(template) + } else { + link = template.parentNode.parentNode + template.parentNode.removeChild(template) + } + + const button = document.createElement('button') + button.classList.add('govuk-service-navigation__link') + button.classList.add('app-mobile-navigation__toggle-button') + button.setAttribute( + 'aria-expanded', + String( + link.parentNode.classList.contains( + 'govuk-service-navigation__item--active' + ) + ) + ) + button.textContent = link.textContent + + link.insertAdjacentElement('afterend', templateClone.firstElementChild) + link.insertAdjacentElement('afterend', button) + }) + + // A global const for storing a matchMedia instance which we'll use to detect when a screen size change happens + // Set the matchMedia to the govuk-frontend tablet breakpoint + + const x = getComputedStyle(document.documentElement).getPropertyValue( + '--govuk-frontend-breakpoint-tablet' + ) + + this.mql = window.matchMedia(`(min-width: ${x})`) + + // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need + // to be able to fall back to the deprecated MediaQueryList.addListener + if ('addEventListener' in this.mql) { + this.mql.addEventListener('change', () => this.setHiddenStates()) + } else { + // @ts-expect-error Property 'addListener' does not exist + this.mql.addListener(() => this.setHiddenStates()) + } + + this.setHiddenStates() + this.setEventListener() + } + + /** + * Set up event delegation for button clicks + */ + setEventListener() { + this.$root.addEventListener( + 'click', + (e) => { + if (e.target.tagName === 'BUTTON') { + if (e.target.getAttribute('aria-expanded') === 'true') { + e.target.setAttribute('aria-expanded', 'false') + } else { + e.target.setAttribute('aria-expanded', 'true') + } + } + }, + { bubbles: true } + ) + } + + /** + * Hide links if viewport is below tablet + */ + setHiddenStates() { + if (!this.mql.matches) { + this.links.forEach((a) => a.setAttribute('hidden', '')) + } else { + this.links.forEach((a) => a.removeAttribute('hidden')) + } + } +} + +export default MobileNavigation diff --git a/src/stylesheets/components/_mobile-navigation.scss b/src/stylesheets/components/_mobile-navigation.scss new file mode 100644 index 0000000000..9d31c122ae --- /dev/null +++ b/src/stylesheets/components/_mobile-navigation.scss @@ -0,0 +1,44 @@ +.app-mobile-navigation__toggle-button { + @include govuk-media-query($from: tablet) { + display: none; + } + position: relative; + padding: 0; + border: 0; + + background: none; + font-size: inherit; +} + +.app-mobile-navigation__toggle-button::after { + content: ""; + box-sizing: border-box; + display: block; + position: absolute; + right: govuk-px-to-rem(-14px); + bottom: govuk-px-to-rem(10px); + width: govuk-px-to-rem(6px); + height: govuk-px-to-rem(6px); + border-top: govuk-px-to-rem(2px) solid; + border-right: govuk-px-to-rem(2px) solid; +} + +.app-mobile-navigation__toggle-button[aria-expanded="false"]::after { + transform: rotate(135deg); +} + +.app-mobile-navigation__toggle-button[aria-expanded="false"] ~ .app-navigation__list { + display: none; +} + +.app-mobile-navigation__toggle-button[aria-expanded="true"]::after { + transform: rotate(-45deg); +} + +.app-mobile-navigation__toggle-button[aria-expanded="true"] ~ .app-navigation__list { + @include govuk-media-query($until: tablet) { + display: block; + } + + display: none; +} diff --git a/src/stylesheets/components/_navigation.scss b/src/stylesheets/components/_navigation.scss index 01dca33300..17865e471e 100644 --- a/src/stylesheets/components/_navigation.scss +++ b/src/stylesheets/components/_navigation.scss @@ -1,5 +1,15 @@ $navigation-height: 50px; +.app-navigation__list-toggle { + @include govuk-media-query($from: tablet) { + display: none; + } +} + +.js-app-navigation__list--hidden { + display: none; +} + .app-navigation { border-bottom: 1px solid $govuk-border-colour; background-color: $app-light-grey; diff --git a/src/stylesheets/main.scss b/src/stylesheets/main.scss index af7ef73945..3aedd88a27 100644 --- a/src/stylesheets/main.scss +++ b/src/stylesheets/main.scss @@ -59,6 +59,7 @@ $app-code-color: #d13118; @import "components/highlight"; @import "components/image-card"; @import "components/masthead"; +@import "components/mobile-navigation"; @import "components/navigation"; @import "components/options"; @import "components/page-navigation"; diff --git a/views/partials/_mobile-navigation.njk b/views/partials/_mobile-navigation.njk new file mode 100644 index 0000000000..a042358d7f --- /dev/null +++ b/views/partials/_mobile-navigation.njk @@ -0,0 +1,13 @@ +{% macro mobileNavigation(params) %} + {% if params.items %} + + {% endif %} +{% endmacro %} \ No newline at end of file diff --git a/views/partials/_navigation.njk b/views/partials/_navigation.njk index c1e8b6d92f..77c0b0c9df 100644 --- a/views/partials/_navigation.njk +++ b/views/partials/_navigation.njk @@ -1,5 +1,5 @@ {% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} -{% from "_sub-navigation-items.njk" import subNavigationItems %} +{% from "_mobile-navigation.njk" import mobileNavigation %} {% set navigationItems = [] %} @@ -7,10 +7,10 @@ {% set navItem = {} %} {% if item.items %} - {% set subNavItemHtml = subNavigationItems({ items: item.items }) %} + {% set subNavItemHtml = mobileNavigation({ items: item.items }) %} {% set navItem = { href: item.href, - html: item.text + '', + html: item.text + '', active: permalink and permalink.startsWith(item.url), current: permalink === item.url } %} @@ -26,6 +26,8 @@ {% set navigationItems = navigationItems.concat(navItem) %} {% endfor %} -{{ govukServiceNavigation({ - navigation: navigationItems -}) }} \ No newline at end of file +
+ {{ govukServiceNavigation({ + navigation: navigationItems + }) }} +
diff --git a/views/partials/_sub-navigation-items.njk b/views/partials/_sub-navigation-items.njk index 22061a7d0d..031343a361 100644 --- a/views/partials/_sub-navigation-items.njk +++ b/views/partials/_sub-navigation-items.njk @@ -1,6 +1,6 @@ {% macro subNavigationItems(params) %} {% if params.items %} -