diff --git a/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink-multi-lang/index.njk b/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink-multi-lang/index.njk new file mode 100644 index 0000000000..29631bf18a --- /dev/null +++ b/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink-multi-lang/index.njk @@ -0,0 +1,429 @@ +--- +title: Child maintenance - multiple language +name: Child maintenance (multiple language) +scenario: | + Worst case scenario that includes all possible header-related components. + This combination of components is less common but possible. + Things to test are if any of the header-related components hinder each other + or confuse users. +--- + +{% extends "layouts/full-page-example.njk" %} + +{% from "govuk/components/cookie-banner/macro.njk" import govukCookieBanner %} +{% from "govuk/components/breadcrumbs/macro.njk" import govukBreadcrumbs %} +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "govuk/components/details/macro.njk" import govukDetails %} +{% from "govuk/components/exit-this-page/macro.njk" import govukExitThisPage %} +{% from "govuk/components/inset-text/macro.njk" import govukInsetText %} +{% from "govuk/components/language-switcher/macro.njk" import govukLanguageSwitcher %} +{% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} +{% from "govuk/components/phase-banner/macro.njk" import govukPhaseBanner %} +{% from "govuk/components/footer/macro.njk" import govukFooter %} + +{% set pageTitle = example.title %} +{% block pageTitle %}{{ pageTitle }} - GOV.UK{% endblock %} + +{% set languageSwitcherHTML %} + {{ govukLanguageSwitcher({ + classes: "govuk-language-switcher--no-top-margin", + items: [ + { + text: "English", + href: "#", + lang: "en", + current: true + }, + { + text: "Cymraeg", + href: "#", + lang: "cy" + }, + { + text: "Français", + href: "#", + lang: "fr" + }, + { + text: "हिंदी", + href: "#", + lang: "hi" + }, + { + text: "日本語", + href: "#", + lang: "ja" + }, + { + text: "اردو", + href: "#", + lang: "ur" + }, + { + text: "中文", + href: "#", + lang: "zh" + } + ] + }) }} +{% endset %} + +{% from "govuk/components/header/macro.njk" import govukHeader %} + +{% block bodyStart %} + {{ super() }} + {{ govukCookieBanner({ + ariaLabel: "Cookies on [name of service]", + messages: [ + { + headingText: "Cookies on [name of service]", + html: html, + actions: [ + { + text: "Accept analytics cookies", + type: "button" + }, + { + text: "Reject analytics cookies", + type: "button" + }, + { + text: "View cookies", + href: "#" + } + ] + } + ] + }) }} +{% endblock %} + +{% block govukHeader %} + {{ govukHeader({ + navigationClasses: "govuk-header__navigation--end", + productName: "Product Name" + }) }} +{% endblock %} + +{% block govukServiceNavigation %} + {{ govukServiceNavigation({ + classes: "app-service-navigation", + serviceName: "Find company information", + serviceUrl: "#0", + navigation: [ + { + href: '#1', + text: 'Search the register' + }, + { + href: '#2', + text: 'Your details' + }, + { + href: '#3', + text: 'Your filings' + }, + { + href: '#4', + text: 'Companies you follow', + current: true + } + ], + slots: { + end: languageSwitcherHTML, + endRightAligned: true + } + }) }} +{% endblock %} + +{% block govukSkipLink %} + {{ super() }} + {{ govukSkipLink({ + href: "https://bbc.co.uk/weather/", + text: "Exit this page", + classes: "govuk-js-exit-this-page-skiplink", + attributes: { + rel: "nofollow noreferrer" + } + }) }} +{% endblock %} + +{% block headerEnd %} + {{ govukPhaseBanner({ + tag: { + text: "Beta" + }, + html: 'This is a new service – your feedback will help us to improve it.' + }) }} +{% endblock %} + +{% block containerStart %} + {{ govukBreadcrumbs({ + classes: "", + collapseOnMobile: true, + items: [ + { + html: "Home", + href: "/" + }, + { + html: "Births, deaths, marriages and care", + href: "/" + }, + { + html: "Having a child, parenting and adoption", + href: "/" + } + ] + }) }} +{% endblock %} + +{% block content %} + {{ govukExitThisPage() }} + +
+
+

Get help arranging child maintenance

+ +

This service will give you information about the different options available to make a child maintenance arrangement. These are:

+ + + +

+ Contact Child Maintenance Choices if you live in Northern Ireland +

+ +

Using the Child Maintenance Service

+

If you already have an active case

+

If you have a case with the same parent you should report a change of circumstances instead of making a new arrangement. You can use this service if you want to set up a new arrangement with a different parent.

+ +

Fees

+

If you decide to use the Child Maintenance Service the application fee is £20 and cannot be refunded. You’ll need a debit or credit card to pay this. It does not guarantee an arrangement.

+

You will not have to pay the application fee if you:

+ +

+ Get help if you have experienced domestic abuse +

+ +

If you’re worried about contacting the other parent

+

If you decide to use the Child Maintenance Service, we will try to contact the other parent about setting up child maintenance – you do not need to.

+

We will share the following details with the other parent:

+ + +

If you are the parent who will be paying child maintenance, we will also share the following details with the other parent:

+ + + {{ govukInsetText({ + text: "We will not share any other information with the other parent as a part of your application." + }) }} + + {% set doIHaveAnActiveCase %} + You will need to contact child maintenance (opens in new tab). + {% endset %} + + {% set payingToReceiving %} +

You will need to close your existing Child Maintenance case and open a new one.

+

If you were the original applicant, you can close your case in MCMC (opens in new tab), or you can contact child maintenance (opens in new tab).

+

If you were not the original applicant, you will need to contact child maintenance (opens in new tab).

+ {% endset %} + + {% set receivingToPaying %} +

You will need to close your existing Child Maintenance case and open a new one.

+

If you were the original applicant, you can close your case in MCMC (opens in new tab), or you can contact child maintenance (opens in new tab).

+

If you were not the original applicant, you will need to contact child maintenance (opens in new tab).

+ {% endset %} + + {{ govukDetails({ + summaryText: "I do not know if I have an active case", + html: doIHaveAnActiveCase + }) }} + + {{ govukDetails({ + summaryText: "I need to change from paying to receiving child maintenance", + html: payingToReceiving + }) }} + + {{ govukDetails({ + summaryText: "I need to change from receiving to paying child maintenance", + html: receivingToPaying + }) }} + + {{ govukButton({ + text: "Start now", + href: "#", + isStartButton: true + }) }} +
+
+

There could be other content here.

+

In ea ex nulla veniam commodo Lorem labore dolor et ea in deserunt qui. Enim adipisicing dolore est amet magna. Cupidatat adipisicing labore consectetur exercitation Lorem dolor ipsum et deserunt est. Sit laborum dolore sit id eiusmod.

+
+
+ +{% endblock %} + + +{% block govukFooter %} +{{ govukFooter({ + navigation: [ + { + title: "Coronavirus (COVID-19)", + width: "two-thirds", + items: [ + { + href: "/coronavirus", + text: "Coronavirus (COVID-19): guidance and support" + } + ] + }, + { + title: "Brexit", + width: "one-third", + items: [ + { + href: "/brexit", + text: "Check what you need to do" + } + ] + }, + { + title: "Services and information", + width: "two-thirds", + columns: 2, + items: [ + { + href: "/browse/benefits", + text: "Benefits" + }, + { + href: "/browse/births-deaths-marriages", + text: "Births, deaths, marriages and care" + }, + { + href: "/browse/business", + text: "Business and self-employed" + }, + { + href: "/browse/childcare-parenting", + text: "Childcare and parenting" + }, + { + href: "/browse/citizenship", + text: "Citizenship and living in the UK" + }, + { + href: "/browse/justice", + text: "Crime, justice and the law" + }, + { + href: "/browse/disabilities", + text: "Disabled people" + }, + { + href: "/browse/driving", + text: "Driving and transport" + }, + { + href: "/browse/education", + text: "Education and learning" + }, + { + href: "/browse/employing-people", + text: "Employing people" + }, + { + href: "/browse/environment-countryside", + text: "Environment and countryside" + }, + { + href: "/browse/housing-local-services", + text: "Housing and local services" + }, + { + href: "/browse/tax", + text: "Money and tax" + }, + { + href: "/browse/abroad", + text: "Passports, travel and living abroad" + }, + { + href: "/browse/visas-immigration", + text: "Visas and immigration" + }, + { + href: "/browse/working", + text: "Working, jobs and pensions" + } + ] + }, + { + title: "Departments and policy", + width: "one-third", + items: [ + { + href: "/government/how-government-works", + text: "How government works" + }, + { + href: "/government/organisations", + text: "Departments" + }, + { + href: "/world", + text: "Worldwide" + }, + { + href: "/government/policies", + text: "Policies" + }, + { + href: "/government/publications", + text: "Publications" + }, + { + href: "/government/announcements", + text: "Announcements" + } + ] + } + ], + meta: { + items: [ + { + href: "/help", + text: "Help" + }, + { + href: "/help/cookies", + text: "Cookies" + }, + { + href: "/contact", + text: "Contact" + }, + { + href: "/help/terms-conditions", + text: "Terms and conditions" + }, + { + href: "/cymraeg", + text: "Rhestr o Wasanaethau Cymraeg" + } + ], + html: 'Built by the Government Digital Service' + } +}) }} +{% endblock %} diff --git a/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink-multi-lang2/index.njk b/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink-multi-lang2/index.njk new file mode 100644 index 0000000000..c6b1646f18 --- /dev/null +++ b/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink-multi-lang2/index.njk @@ -0,0 +1,420 @@ +--- +title: Child maintenance - multiple language with short nav menu +name: Child maintenance (multiple language with short nav menu) +scenario: | + Worst case scenario that includes all possible header-related components. + This combination of components is less common but possible. + Things to test are if any of the header-related components hinder each other + or confuse users. +--- + +{% extends "layouts/full-page-example.njk" %} + +{% from "govuk/components/cookie-banner/macro.njk" import govukCookieBanner %} +{% from "govuk/components/breadcrumbs/macro.njk" import govukBreadcrumbs %} +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "govuk/components/details/macro.njk" import govukDetails %} +{% from "govuk/components/exit-this-page/macro.njk" import govukExitThisPage %} +{% from "govuk/components/inset-text/macro.njk" import govukInsetText %} +{% from "govuk/components/language-switcher/macro.njk" import govukLanguageSwitcher %} +{% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} +{% from "govuk/components/phase-banner/macro.njk" import govukPhaseBanner %} +{% from "govuk/components/footer/macro.njk" import govukFooter %} + +{% set pageTitle = example.title %} +{% block pageTitle %}{{ pageTitle }} - GOV.UK{% endblock %} + +{% set languageSwitcherHTML %} + {{ govukLanguageSwitcher({ + classes: "govuk-language-switcher--no-top-margin", + items: [ + { + text: "English", + href: "#", + lang: "en", + current: true + }, + { + text: "Cymraeg", + href: "#", + lang: "cy" + }, + { + text: "Français", + href: "#", + lang: "fr" + }, + { + text: "हिंदी", + href: "#", + lang: "hi" + }, + { + text: "日本語", + href: "#", + lang: "ja" + }, + { + text: "اردو", + href: "#", + lang: "ur" + }, + { + text: "中文", + href: "#", + lang: "zh" + } + ] + }) }} +{% endset %} + +{% from "govuk/components/header/macro.njk" import govukHeader %} + +{% block bodyStart %} + {{ super() }} + {{ govukCookieBanner({ + ariaLabel: "Cookies on [name of service]", + messages: [ + { + headingText: "Cookies on [name of service]", + html: html, + actions: [ + { + text: "Accept analytics cookies", + type: "button" + }, + { + text: "Reject analytics cookies", + type: "button" + }, + { + text: "View cookies", + href: "#" + } + ] + } + ] + }) }} +{% endblock %} + +{% block govukHeader %} + {{ govukHeader({ + navigationClasses: "govuk-header__navigation--end", + productName: "Product Name" + }) }} +{% endblock %} + +{% block govukServiceNavigation %} + {{ govukServiceNavigation({ + classes: "app-service-navigation", + serviceName: "Find company information", + serviceUrl: "#0", + navigation: [ + { + href: '#1', + text: 'Search' + }, + { + href: '#2', + text: 'Your details' + } + ], + slots: { + end: languageSwitcherHTML, + endRightAligned: true + } + }) }} +{% endblock %} + +{% block govukSkipLink %} + {{ super() }} + {{ govukSkipLink({ + href: "https://bbc.co.uk/weather/", + text: "Exit this page", + classes: "govuk-js-exit-this-page-skiplink", + attributes: { + rel: "nofollow noreferrer" + } + }) }} +{% endblock %} + +{% block headerEnd %} + {{ govukPhaseBanner({ + tag: { + text: "Beta" + }, + html: 'This is a new service – your feedback will help us to improve it.' + }) }} +{% endblock %} + +{% block containerStart %} + {{ govukBreadcrumbs({ + classes: "", + collapseOnMobile: true, + items: [ + { + html: "Home", + href: "/" + }, + { + html: "Births, deaths, marriages and care", + href: "/" + }, + { + html: "Having a child, parenting and adoption", + href: "/" + } + ] + }) }} +{% endblock %} + +{% block content %} + {{ govukExitThisPage() }} + +
+
+

Get help arranging child maintenance

+ +

This service will give you information about the different options available to make a child maintenance arrangement. These are:

+ + + +

+ Contact Child Maintenance Choices if you live in Northern Ireland +

+ +

Using the Child Maintenance Service

+

If you already have an active case

+

If you have a case with the same parent you should report a change of circumstances instead of making a new arrangement. You can use this service if you want to set up a new arrangement with a different parent.

+ +

Fees

+

If you decide to use the Child Maintenance Service the application fee is £20 and cannot be refunded. You’ll need a debit or credit card to pay this. It does not guarantee an arrangement.

+

You will not have to pay the application fee if you:

+ +

+ Get help if you have experienced domestic abuse +

+ +

If you’re worried about contacting the other parent

+

If you decide to use the Child Maintenance Service, we will try to contact the other parent about setting up child maintenance – you do not need to.

+

We will share the following details with the other parent:

+ + +

If you are the parent who will be paying child maintenance, we will also share the following details with the other parent:

+ + + {{ govukInsetText({ + text: "We will not share any other information with the other parent as a part of your application." + }) }} + + {% set doIHaveAnActiveCase %} + You will need to contact child maintenance (opens in new tab). + {% endset %} + + {% set payingToReceiving %} +

You will need to close your existing Child Maintenance case and open a new one.

+

If you were the original applicant, you can close your case in MCMC (opens in new tab), or you can contact child maintenance (opens in new tab).

+

If you were not the original applicant, you will need to contact child maintenance (opens in new tab).

+ {% endset %} + + {% set receivingToPaying %} +

You will need to close your existing Child Maintenance case and open a new one.

+

If you were the original applicant, you can close your case in MCMC (opens in new tab), or you can contact child maintenance (opens in new tab).

+

If you were not the original applicant, you will need to contact child maintenance (opens in new tab).

+ {% endset %} + + {{ govukDetails({ + summaryText: "I do not know if I have an active case", + html: doIHaveAnActiveCase + }) }} + + {{ govukDetails({ + summaryText: "I need to change from paying to receiving child maintenance", + html: payingToReceiving + }) }} + + {{ govukDetails({ + summaryText: "I need to change from receiving to paying child maintenance", + html: receivingToPaying + }) }} + + {{ govukButton({ + text: "Start now", + href: "#", + isStartButton: true + }) }} +
+
+

There could be other content here.

+

In ea ex nulla veniam commodo Lorem labore dolor et ea in deserunt qui. Enim adipisicing dolore est amet magna. Cupidatat adipisicing labore consectetur exercitation Lorem dolor ipsum et deserunt est. Sit laborum dolore sit id eiusmod.

+
+
+ +{% endblock %} + + +{% block govukFooter %} +{{ govukFooter({ + navigation: [ + { + title: "Coronavirus (COVID-19)", + width: "two-thirds", + items: [ + { + href: "/coronavirus", + text: "Coronavirus (COVID-19): guidance and support" + } + ] + }, + { + title: "Brexit", + width: "one-third", + items: [ + { + href: "/brexit", + text: "Check what you need to do" + } + ] + }, + { + title: "Services and information", + width: "two-thirds", + columns: 2, + items: [ + { + href: "/browse/benefits", + text: "Benefits" + }, + { + href: "/browse/births-deaths-marriages", + text: "Births, deaths, marriages and care" + }, + { + href: "/browse/business", + text: "Business and self-employed" + }, + { + href: "/browse/childcare-parenting", + text: "Childcare and parenting" + }, + { + href: "/browse/citizenship", + text: "Citizenship and living in the UK" + }, + { + href: "/browse/justice", + text: "Crime, justice and the law" + }, + { + href: "/browse/disabilities", + text: "Disabled people" + }, + { + href: "/browse/driving", + text: "Driving and transport" + }, + { + href: "/browse/education", + text: "Education and learning" + }, + { + href: "/browse/employing-people", + text: "Employing people" + }, + { + href: "/browse/environment-countryside", + text: "Environment and countryside" + }, + { + href: "/browse/housing-local-services", + text: "Housing and local services" + }, + { + href: "/browse/tax", + text: "Money and tax" + }, + { + href: "/browse/abroad", + text: "Passports, travel and living abroad" + }, + { + href: "/browse/visas-immigration", + text: "Visas and immigration" + }, + { + href: "/browse/working", + text: "Working, jobs and pensions" + } + ] + }, + { + title: "Departments and policy", + width: "one-third", + items: [ + { + href: "/government/how-government-works", + text: "How government works" + }, + { + href: "/government/organisations", + text: "Departments" + }, + { + href: "/world", + text: "Worldwide" + }, + { + href: "/government/policies", + text: "Policies" + }, + { + href: "/government/publications", + text: "Publications" + }, + { + href: "/government/announcements", + text: "Announcements" + } + ] + } + ], + meta: { + items: [ + { + href: "/help", + text: "Help" + }, + { + href: "/help/cookies", + text: "Cookies" + }, + { + href: "/contact", + text: "Contact" + }, + { + href: "/help/terms-conditions", + text: "Terms and conditions" + }, + { + href: "/cymraeg", + text: "Rhestr o Wasanaethau Cymraeg" + } + ], + html: 'Built by the Government Digital Service' + } +}) }} +{% endblock %} diff --git a/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink/index.njk b/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink/index.njk index 6304d00327..7d9dc5c83a 100644 --- a/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink/index.njk +++ b/packages/govuk-frontend-review/src/views/full-page-examples/header-kitchen-sink/index.njk @@ -16,6 +16,7 @@ scenario: | {% from "govuk/components/details/macro.njk" import govukDetails %} {% from "govuk/components/exit-this-page/macro.njk" import govukExitThisPage %} {% from "govuk/components/inset-text/macro.njk" import govukInsetText %} +{% from "govuk/components/language-switcher/macro.njk" import govukLanguageSwitcher %} {% from "govuk/components/service-navigation/macro.njk" import govukServiceNavigation %} {% from "govuk/components/phase-banner/macro.njk" import govukPhaseBanner %} {% from "govuk/components/footer/macro.njk" import govukFooter %} @@ -23,6 +24,23 @@ scenario: | {% set pageTitle = example.title %} {% block pageTitle %}{{ pageTitle }} - GOV.UK{% endblock %} +{% set languageSwitcherHTML %} + {{ govukLanguageSwitcher({ + classes: "govuk-language-switcher--no-top-margin", + items: [ + { + text: "English", + href: "#", + current: true + }, + { + text: "Cymraeg", + href: "#" + } + ] + }) }} +{% endset %} + {% from "govuk/components/header/macro.njk" import govukHeader %} {% block bodyStart %} @@ -82,7 +100,11 @@ scenario: | text: 'Companies you follow', current: true } - ] + ], + slots: { + end: languageSwitcherHTML, + endRightAligned: true + } }) }} {% endblock %} diff --git a/packages/govuk-frontend/src/govuk/all.mjs b/packages/govuk-frontend/src/govuk/all.mjs index f0fd0ba0f0..6ea3c02219 100644 --- a/packages/govuk-frontend/src/govuk/all.mjs +++ b/packages/govuk-frontend/src/govuk/all.mjs @@ -6,6 +6,7 @@ export { Checkboxes } from './components/checkboxes/checkboxes.mjs' export { ErrorSummary } from './components/error-summary/error-summary.mjs' export { ExitThisPage } from './components/exit-this-page/exit-this-page.mjs' export { FileUpload } from './components/file-upload/file-upload.mjs' +export { LanguageSwitcher } from './components/language-switcher/language-switcher.mjs' export { NotificationBanner } from './components/notification-banner/notification-banner.mjs' export { PasswordInput } from './components/password-input/password-input.mjs' export { Radios } from './components/radios/radios.mjs' diff --git a/packages/govuk-frontend/src/govuk/components/language-switcher/_mixin.scss b/packages/govuk-frontend/src/govuk/components/language-switcher/_mixin.scss index 77a86cf7fb..44f204d6c1 100644 --- a/packages/govuk-frontend/src/govuk/components/language-switcher/_mixin.scss +++ b/packages/govuk-frontend/src/govuk/components/language-switcher/_mixin.scss @@ -10,28 +10,87 @@ color: base.govuk-functional-colour(text); } - .govuk-language-switcher__list { + // Modifier to remove the top margin on small viewports. Intended for use when + // the switcher is in the service navigation. Kept as a modifier so the style is + // not dependent on another component. + .govuk-language-switcher--no-top-margin { + @media #{base.govuk-until-breakpoint(tablet)} { + margin-top: 0; + } + } + + // Menu toggle button, shown on mobile when JavaScript is available. These + // styles deliberately mirror the service navigation menu toggle. + .govuk-language-switcher__toggle { + @include base.govuk-font($size: 19, $weight: bold); display: inline-flex; - flex-wrap: wrap; - row-gap: base.govuk-spacing(1); + align-items: center; + margin: base.govuk-spacing(2) 0; + padding: 0; + border: 0; + color: base.govuk-functional-colour(link); + background: none; + word-break: break-all; + cursor: pointer; + + &:focus { + @include base.govuk-focused-text; + } + + &::after { + @include base.govuk-shape-arrow($direction: down, $base: 10px, $display: inline-block); + content: ""; + margin-left: base.govuk-spacing(1); + } + + &[aria-expanded="true"]::after { + @include base.govuk-shape-arrow($direction: up, $base: 10px, $display: inline-block); + } + + &[hidden] { + display: none; + } + } + + // Icon shown before the toggle button text + .govuk-language-switcher__toggle-icon { + flex-shrink: 0; + margin-right: base.govuk-spacing(1); + } + + .govuk-language-switcher__list { margin: 0; padding: 0; list-style-type: none; + + @media #{base.govuk-from-breakpoint(tablet)} { + display: inline-flex; + flex-wrap: wrap; + row-gap: base.govuk-spacing(1); + } } .govuk-language-switcher__list-item { - display: flex; - align-items: center; + // On mobile, stack the language items vertically, matching the service + // navigation menu + @media #{base.govuk-until-breakpoint(tablet)} { + margin: base.govuk-spacing(2) 0; + } + + @media #{base.govuk-from-breakpoint(tablet)} { + display: flex; + align-items: center; - &:not(:last-child) { - &::after { - content: ""; - display: block; - height: 1em; - margin-right: base.govuk-spacing(2); - margin-left: base.govuk-spacing(2); - border-right: 1px solid; - border-right-color: base.govuk-functional-colour(secondary-text); + &:not(:last-child) { + &::after { + content: ""; + display: block; + height: 1em; + margin-right: base.govuk-spacing(2); + margin-left: base.govuk-spacing(2); + border-right: 1px solid; + border-right-color: base.govuk-functional-colour(secondary-text); + } } } } diff --git a/packages/govuk-frontend/src/govuk/components/language-switcher/language-switcher.mjs b/packages/govuk-frontend/src/govuk/components/language-switcher/language-switcher.mjs new file mode 100644 index 0000000000..236e77d1fb --- /dev/null +++ b/packages/govuk-frontend/src/govuk/components/language-switcher/language-switcher.mjs @@ -0,0 +1,196 @@ +import { getBreakpoint } from '../../common/index.mjs' +import { Component } from '../../component.mjs' +import { ElementError } from '../../errors/index.mjs' + +/** + * Language switcher component + * + * On mobile, collapses the list of languages into a menu behind a toggle + * button, mirroring the behaviour of the service navigation menu. + * + * @preserve + */ +export class LanguageSwitcher extends Component { + /** @private */ + $menuButton + + /** @private */ + $menu + + /** + * Remember the open/closed state of the menu so we can maintain it when the + * screen is resized. + * + * @private + */ + menuIsOpen = false + + /** + * A global const for storing a matchMedia instance which we'll use to detect + * when a screen size change happens. We rely on it being null if the feature + * isn't available to initially apply hidden attributes + * + * @private + * @type {MediaQueryList | null} + */ + mql = null + + /** + * @param {Element | null} $root - HTML element to use for the language switcher + */ + constructor($root) { + super($root) + + const $menuButton = this.$root.querySelector( + '.govuk-js-language-switcher-toggle' + ) + + // The toggle button may be omitted when writing plain HTML, in which case + // the list of languages is always shown + if (!$menuButton) { + return this + } + + const menuId = $menuButton.getAttribute('aria-controls') + if (!menuId) { + throw new ElementError({ + component: LanguageSwitcher, + identifier: + 'Menu button (` + {% endif %} +