Skip to content

Commit

Permalink
Add service navigation component
Browse files Browse the repository at this point in the history
  • Loading branch information
querkmachine committed Aug 29, 2024
1 parent 3362ddf commit 37877d0
Show file tree
Hide file tree
Showing 19 changed files with 1,475 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ describe('GOV.UK Prototype Kit config', () => {
importFrom: 'govuk/components/select/macro.njk',
macroName: 'govukSelect'
},
{
importFrom: 'govuk/components/service-navigation/macro.njk',
macroName: 'govukServiceNavigation'
},
{
importFrom: 'govuk/components/skip-link/macro.njk',
macroName: 'govukSkipLink'
Expand Down
1 change: 1 addition & 0 deletions packages/govuk-frontend/src/govuk/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { Header } from './components/header/header.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'
export { ServiceNavigation } from './components/service-navigation/service-navigation.mjs'
export { SkipLink } from './components/skip-link/skip-link.mjs'
export { Tabs } from './components/tabs/tabs.mjs'
export { initAll, createAll } from './init.mjs'
Expand Down
1 change: 1 addition & 0 deletions packages/govuk-frontend/src/govuk/all.puppeteer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe('GOV.UK Frontend', () => {
'NotificationBanner',
'PasswordInput',
'Radios',
'ServiceNavigation',
'SkipLink',
'Tabs'
])
Expand Down
1 change: 1 addition & 0 deletions packages/govuk-frontend/src/govuk/components/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@import "phase-banner/index";
@import "radios/index";
@import "select/index";
@import "service-navigation/index";
@import "skip-link/index";
@import "summary-list/index";
@import "table/index";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
border-bottom: $govuk-header-border-width solid $govuk-header-border-color;
}

.govuk-header--full-width-border {
border-bottom-color: $govuk-header-border-color;

.govuk-header__container {
border-bottom-color: transparent;
}
}

.govuk-header__logotype {
display: inline-block;
position: relative;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ examples:
- href: '#3'
text: Navigation item 3

- name: with full width border
description: Makes the header's bottom border full width without affecting the header's content.
options:
classes: govuk-header--full-width-border
productName: Product Name

- name: navigation item with html
options:
serviceName: Service Name
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Service Navigation

## Installation

See the [main README quick start guide](https://github.com/alphagov/govuk-frontend#quick-start) for how to install this component.

## Guidance and Examples

Find out when to use the service header component in your service in the [GOV.UK Design System](https://design-system.service.gov.uk/components/service-navigation).

## Component options

Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

See [options table](https://design-system.service.gov.uk/components/service-navigation/#options-service-navigation-example) for details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
@include govuk-exports("govuk/component/service-navigation") {
$govuk-service-navigation-active-link-border-width: govuk-spacing(1);
$govuk-service-navigation-background: $govuk-canvas-background-colour;
$govuk-service-navigation-border-colour: $govuk-border-colour;

// We make the link colour a little darker than normal here so that it has
// better perceptual contrast with the navigation background.
$govuk-service-navigation-link-colour: govuk-shade($govuk-link-colour, 10%);

.govuk-service-navigation {
border-bottom: 1px solid $govuk-service-navigation-border-colour;
background-color: $govuk-service-navigation-background;
}

.govuk-service-navigation__container {
display: flex;
flex-direction: column;
align-items: start;

@include govuk-media-query($from: tablet) {
flex-direction: row;
flex-wrap: wrap;
}
}

// These styles are shared between nav items and the service name, they
// ensure that both of them remain vertically aligned with one another
.govuk-service-navigation__item,
.govuk-service-navigation__service-name {
position: relative;
margin: govuk-spacing(2) 0;
border: 0 solid $govuk-service-navigation-link-colour;

@include govuk-media-query($from: tablet) {
margin-top: 0;
margin-bottom: 0;
padding: govuk-spacing(4) 0;

&:not(:last-child) {
@include govuk-responsive-margin(6, $direction: right);
}
}
}

.govuk-service-navigation__item--active {
@include govuk-media-query($until: tablet) {
// Negative offset the left margin so we can place a current page indicator
// to the left without misaligning the list item text.
margin-left: ((govuk-spacing(2) + $govuk-service-navigation-active-link-border-width) * -1);
padding-left: govuk-spacing(2);
border-left-width: $govuk-service-navigation-active-link-border-width;
}

@include govuk-media-query($from: tablet) {
padding-bottom: govuk-spacing(4) - $govuk-service-navigation-active-link-border-width;
border-bottom-width: $govuk-service-navigation-active-link-border-width;
}
}

.govuk-service-navigation__link {
@include govuk-link-common;
@include govuk-link-style-no-underline;
@include govuk-link-style-no-visited-state;

&:not(:hover):not(:focus) {
// We set the colour here as we don't want to override the hover or
// focus colours
color: $govuk-service-navigation-link-colour;
}
}

//
// Service name specific code
//

.govuk-service-navigation__service-name {
@include govuk-font($size: 19, $weight: bold);
}

// Annoyingly this requires a compound selector in order to overcome the
// specificity of the other link colour override we're doing
.govuk-service-navigation__service-name .govuk-service-navigation__link {
@include govuk-link-style-text;
}

//
// Navigation list specific code
//

.govuk-service-navigation__toggle {
@include govuk-font($size: 19, $weight: bold);
display: inline-flex;
margin: 0 0 govuk-spacing(2);
padding: 0;
border: 0;
color: $govuk-service-navigation-link-colour;
background: none;
word-break: break-all;
cursor: pointer;
align-items: center;

&:focus {
@include govuk-focused-text;
}

&::after {
@include govuk-shape-arrow($direction: down, $base: 10px, $display: inline-block);
content: "";
margin-left: govuk-spacing(1);
}

&[aria-expanded="true"]::after {
@include govuk-shape-arrow($direction: up, $base: 10px, $display: inline-block);
}

// Ensure the button stays hidden if the hidden attribute is present
&[hidden] {
display: none;
}
}

.govuk-service-navigation__list {
@include govuk-font($size: 19);
margin: 0;
margin-bottom: govuk-spacing(3);
padding: 0;
list-style: none;

// Make the navigation list a flexbox. Doing so resolves a couple of
// accessibility problems caused by the list items being inline-blocks:
// - Removes the extra whitespace from between each list item that screen
// readers would pointlessly announce.
// - Fixes an NVDA issue in Firefox and Chrome <= 124 where it would read
// all of the links as a run-on sentence.
@include govuk-media-query($from: tablet) {
display: flex;
flex-wrap: wrap;
margin-bottom: 0;

// However... IE11 totally trips over flexbox and doesn't wrap anything,
// making all of the items into a single, horizontally scrolling row,
// which is no good. This CSS hack removes the flexbox definition for
// IE 10 & 11, reverting it to the flawed, but OK, non-flexbox version.
//
// CSS hack taken from https://stackoverflow.com/questions/11173106/apply-style-only-on-ie#answer-36448860
// which also includes an explanation of why this works
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
display: block;
}
}
}

// This is a <strong> element that is used as a fallback mechanism for
// visually indicating the current page in scenarios where CSS isn't
// available. We don't actually want it to be bold normally, so set it to
// inherit the parent font-weight.
.govuk-service-navigation__active-fallback {
font-weight: inherit;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "../../base";
@import "./index";
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { axe, render } from '@govuk-frontend/helpers/puppeteer'
import { getExamples } from '@govuk-frontend/lib/components'

describe('/components/service-navigation', () => {
let axeRules

beforeAll(() => {
axeRules = {
/**
* Ignore 'Element has insufficient color contrast' for WCAG Level AAA
*/
'color-contrast-enhanced': { enabled: false }
}
})

describe('component examples', () => {
it('passes accessibility tests', async () => {
const examples = await getExamples('service-navigation')

// Remove the 'with no options set' example from being tested, as the
// component doesn't output anything in that scenario.
delete examples['with no options set']

for (const exampleName in examples) {
await render(page, 'service-navigation', examples[exampleName])
await expect(axe(page, axeRules)).resolves.toHaveNoViolations()
}
}, 120000)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% macro govukServiceNavigation(params) %}
{%- include "./template.njk" -%}
{% endmacro %}
Loading

0 comments on commit 37877d0

Please sign in to comment.