Skip to content

Commit

Permalink
Add secondary navigation component
Browse files Browse the repository at this point in the history
  • Loading branch information
frankieroberto authored and paulrobertlloyd committed Dec 19, 2023
1 parent fb84df2 commit 2e14145
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 0 deletions.
30 changes: 30 additions & 0 deletions docs/examples/secondary-navigation-with-header.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
eleventyExcludeFromCollections: true
layout: example.njk
title: Secondary navigation example with header
---
<span class="govuk-caption-l">Case #161351</span>
<h1 class="govuk-heading-l" id="case-name">James Smith</h1>

{% from "x-govuk/components/secondary-navigation/macro.njk" import xGovukSecondaryNavigation %}
{{ xGovukSecondaryNavigation({
labelledBy: "case-name",
items: [{
text: "Overview",
href: "#"
}, {
text: "Contact details",
href: "#",
current: true
}, {
text: "Claims",
href: "#"
}, {
text: "Audit log",
href: "#"
}]
}) }}

<main class="govuk-main-wrapper" id="main-content" role="main">
<h2 class="govuk-heading-m">Contact details</h2>
</main>
23 changes: 23 additions & 0 deletions docs/examples/secondary-navigation.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
eleventyExcludeFromCollections: true
layout: example.njk
title: Secondary navigation example
---
{% from "x-govuk/components/secondary-navigation/macro.njk" import xGovukSecondaryNavigation %}
{{ xGovukSecondaryNavigation({
visuallyHiddenTitle: "Secondary menu",
items: [{
text: "Overview",
href: "#",
current: true
}, {
text: "Staff list",
href: "#"
}, {
text: "Projects",
href: "#"
}, {
text: "Settings",
href: "#"
}]
}) }}
76 changes: 76 additions & 0 deletions docs/secondary-navigation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
layout: sub-navigation
order: 5
title: Secondary navigation
description: Allow users to navigate between pages scoped to a section.
---

{% from "example/macro.njk" import appExample %}

{{ appExample({
example: "secondary-navigation"
}) }}

## When to use this component

Use the secondary navigation when you already have a [primary navigation](primary-navigation) and need to let users navigate between pages that are scoped to a particular section or concept.

For example, if your service is a case management system, you might use the secondary navigation if there are multiple pages associated with a single case.

## When not to use this component

Do not use this component for the primary sections of your service, or if a [sub-navigation](sub-navigation) would be more appropriate.

You could also consider using the [tabs component](https://design-system.service.gov.uk/components/tabs/) if the amount of content in each sub-section is small.

## How it works

{{ appExample({
example: "secondary-navigation-with-header"
}) }}

Unlike [tabs](https://design-system.service.gov.uk/components/tabs/), secondary navigation does not use JavaScript. Each item within the navigation is a link to a separate full page.

One of the items should always be highlighted as the current page. This item remains a link, but uses black text and has a line beneath it.

The secondary navigation should appear before the `<main>` element of the page. This means that it is skipped when [skip link](https://design-system.service.gov.uk/components/skip-link/) is used.

The scope of the secondary navigation can be given by an associated heading. When doing this, you should set `labelledBy` to be the `id` of the heading, so that it is associated with the heading for screen reader users.

The title of the current page can be repeated below the sub navigation, inside the `<main>` element, using a heading tag.

You can use HTML or, if you are using Nunjucks or the GOV.UK Prototype Kit, you can use the Nunjucks macro.

### Nunjucks macro options

| Name | Type | Description |
| :---------------------- | :----- | :----------------------------------------------------------------------------------------------------------------------------- |
| **items** | array | **Required**. An array of navigation links within the secondary navigation. See [items](#options-for-items). |
| **labelledBy** | string | A reference to the id of an existing heading on a page which acts as the label for the navigation. |
| **visuallyHiddenTitle** | text | A visually-hidden label to describe the navigation. Defaults to ‘Secondary Menu’. Not included if `labelledBy` is set instead. |
| **classes** | string | Classes to add to the primary navigation container. |
| **attributes** | object | HTML attributes (for example data attributes) to add to the primary navigation container. |

#### Options for items

| Name | Type | Description |
| :---------- | :------ | :----------------------------------------------------------------- |
| **text** | string | **Required**. Text of the navigation link. |
| **href** | array | **Required**. The value of the navigation link’s `href` attribute. |
| **current** | boolean | Indicate that the item is the current page. |
| **classes** | string | Classes to add to the navigation item. |

## Research on this component

This component is based on ones originally developed as part of the Ministry of Justice and HMCTS design systems.

Versions of this component are currently used on these services:

- [Manage training for early career teachers](https://manage-training-for-early-career-teachers.education.gov.uk)
- [Register trainee teachers](https://www.register-trainee-teachers.service.gov.uk)
- [Teaching Vacancies](https://teaching-vacancies.service.gov.uk)

More research is needed on:

- how best to display the items on narrow mobile screens
- making the component as accessibile as possible
1 change: 1 addition & 0 deletions eleventy.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ module.exports = function (eleventyConfig) {
'docs/autocomplete.md',
'docs/masthead.md',
'docs/primary-navigation.md',
'docs/secondary-navigation.md',
'docs/sub-navigation.md',
'docs/related-navigation.md',
'docs/data-attributes.md'
Expand Down
1 change: 1 addition & 0 deletions x-govuk/components/_all.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
@import "masthead/masthead";
@import "primary-navigation/primary-navigation";
@import "related-navigation/related-navigation";
@import "secondary-navigation/secondary-navigation";
@import "sub-navigation/sub-navigation";
69 changes: 69 additions & 0 deletions x-govuk/components/secondary-navigation/_secondary-navigation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
.x-govuk-secondary-navigation {
@include govuk-font(19);
}

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

// Extend the touch area of the link to the list
&::after {
bottom: 0;
content: "";
left: 0;
position: absolute;
right: 0;
top: 0;
}
}

.x-govuk-secondary-navigation__list {
@include govuk-clearfix;

// The list uses box-shadow rather than a border to set a 1px
// grey line at the bottom, so that border from the current
// item appears on top of the grey line.
box-shadow: inset 0 -1px 0 $govuk-border-colour;
list-style: none;
margin: 0;
padding: 0;
width: 100%;
}

.x-govuk-secondary-navigation__list-item {
box-sizing: border-box;
display: block;
float: left;
margin-right: govuk-spacing(4);
padding-bottom: govuk-spacing(2);
padding-top: govuk-spacing(2);
position: relative;

// More generous padding beneath items on wider screens
@include govuk-media-query($from: tablet) {
padding-bottom: govuk-spacing(3);
}
}

// The last item of the list doesn’t need any spacing to its right.
// Removing this prevents the item from wrapping to the next line
// unnecessarily.
.x-govuk-secondary-navigation__list-item:last-child {
margin-right: 0;
}

.x-govuk-secondary-navigation__list-item--current {
border-bottom: $govuk-border-width solid $govuk-brand-colour;
padding-bottom: govuk-spacing(1);

// More generous padding beneath items on wider screens
@include govuk-media-query($from: tablet) {
padding-bottom: govuk-spacing(2);
}
}

.x-govuk-secondary-navigation__list-item--current .x-govuk-secondary-navigation__link:link,
.x-govuk-secondary-navigation__list-item--current .x-govuk-secondary-navigation__link:visited {
color: $govuk-text-colour;
}
3 changes: 3 additions & 0 deletions x-govuk/components/secondary-navigation/macro.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% macro xGovukSecondaryNavigation(params) %}
{%- include "./template.njk" -%}
{% endmacro %}
11 changes: 11 additions & 0 deletions x-govuk/components/secondary-navigation/template.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<nav class="x-govuk-secondary-navigation {%- if params.classes %} {{ params.classes }}{% endif -%}" {% if params.labelledBy %}aria-labelledby="{{ params.labelledBy }}"{% else %}aria-label="{{ params.visuallyHiddenTitle or "Secondary menu" }}"{% endif %} {%- for attribute, value in params.attributes %} {{ attribute }}="{{ value }}"{% endfor %}>
<ul class="x-govuk-secondary-navigation__list">
{% for item in params.items %}
<li class="x-govuk-secondary-navigation__list-item {{ "x-govuk-secondary-navigation__list-item--current" if item.current }}{% if item.classes %} {{ item.classes }}{% endif -%}">
<a class="x-govuk-secondary-navigation__link" href="{{ item.href }}" {{ "aria-current=page" if item.current }}>
{{ item.text }}
</a>
</li>
{% endfor %}
</ul>
</nav>

0 comments on commit 2e14145

Please sign in to comment.