Global header and footer used across all NICE digital services
🚀 Jump straight to getting started
📑 Table of contents (click to expand)
- Global navigation
- What is it?
- Stack
- 🚀 Set up
- How to use
- React
- Installation
- Usage
- Props
- Main props
- Header props
- Header.service
- Header.skipLinkId
- Header.renderSearchOnly
- Header.onNavigating
- Header.onResize
- Header.onDropdownOpen
- Header.onDropdownClose
- Header.additionalSubMenuItems
- Header.search
- Header.search.url
- Header.search.autocomplete
- Header.search.placeholder
- Header.search.query
- Header.search.onSearching
- Header.auth
- Header.auth.environment
- Header.auth.provider
- Header.auth.links
- Header.auth.displayName
- Footer props
- CDN
- React
- Deployments
- Upgrading to v2
- Upgrading to v3
- Upgrading to v4
- Upgrading to v5
- Upgrading to v6
Global Nav consists common header and footer to be used across all NICE digital services. It is designed to be used across any NICE branded, externally facing web application. This includes all externally facing services that sit under the nice.org.uk domain. It also includes other NICE branded sites like Evidence Search that sit on non-NICE domains. It is a replacement for NICE.TopHat.
The header covers the following high-level functionality:
- main navigation
- skip links
- search and autocomplete
- COVID-19 message
- TLS warning message for old IE
- sign in and account management via NICE Accounts
- In the future will support Auth0
The following non-functional requirements apply:
- accessible: to WCAG 2.0 AA
- touch: optimized for touch with sufficient touch targets
- print: print styles
- security: tested against OWASP top 10 and pen tested
- progressive enhancement:
- mobile first
- non-JS fallback for SSR React apps
- browser support: IE11+
- React
- SCSS for styles
- CSS Modules for generated class names
- PostCSS for transforming CSS with plugins:
- autoprefixer for automatically adding vendor prefixes in CSS
- and NICE Digital shared browserslist config
- Vite for module bundling
- Babel 7 for ES6/JSX → ES5 transpilation
- accessible-autocomplete
- ESLint for linting our JavaScript
- Stylelint for linting our SCSS
- Prettier for code formatting
- Jest for JS unit tests and snapshot tests
- NICE Design System core for SASS mixins, functions and colour/spacing variables
Consider the following development principles:
- One single header and footer component (and optional main wrapper component with back to top link) across all NICE services
- Progressively enhanced to support maximum number of devices and browsers
- Fast performance
- single HTTP request for CDN minified bundle
- as small as possible bundle size
- High unit test coverage
- 'Standard' React wherever possible
- easy for any React developer to pickup
- Consistent code style and formatting
- as if a single developer worked across the codebase
- Clear extension points and hooks for integrating into applications
- To avoid some of the issues from TopHat where there was no consistency
We use SCSS modules for a few reasons:
- local scoping of SCSS avoids accidental cascades:
- within global nav
- polluting out of global nav into the global scope
- obfuscated class names discourages overriding CSS styles in your app. This is by design to keep the header consistent across all services.
Using SCSS allows us to use mixins, functions and variables from the NICE Design System.
If you really need to override styles, see the overrides documentation.
TL;DR; to run the project locally, do the following:
- install Node 14+ or latest LTS version. Or even better, use Volta to use the Node version pinned in package.json.
- run
npm cion the command line to install dependencies - run
npm run devon the command line - navigate to http://localhost:3000/ in a browser.
This compiles the application and spins up a development server. It then watches for changes to files and:
- lints changed files
- automatically rebuilds the app.
It then automatically reloads the application in the Browser (so no need for a manual reload) using Hot Module Replacement (HMR) in webpack.
There are various other commands you can run for further things like tests and linting:
npm testLints code and runs testsnpm test:unitRuns Jest unit testsnpm test:unit:watchRuns Jest unit tests and watches for changes. Run this in development.npm test:unit:coverageRuns Jest unit tests and reports coverage
If you've installed the VSCode npm extension then you can easily run scripts by:
- right-clicking the script name in package.json
- or Ctrl+Shift+P -> npm run script -> test:unit:watch.
To run a single test file, use the jest cli option to pass in a regex to match test files. For example, to run just files that match nav:
npm run-script test:unit -- navTo run a single test, or a bunch of tests that match a given name, use the jest --testNamePattern cli flag (or the -t alias). For example, to run all tests that check aria attributes:
npm run-script test:unit -- -t arianpm run lintLints both JavaScript and SCSSnpm run prettierChecks files for Prettier code stylenpm run prettier:fixFixes Prettier code style issuesnpm run lint:jsLints just JavaScript filesnpm run lint:js:fixFixes linting issues automatically in JavaScript filesnpm run lint:scssLints just SCSS filesnpm run lint:scss:fixFixes linting issues automatically in SCSS files
To distinguish between local development builds and builds on TeamCity, a custom npm script has been added, 'build:teamcity.'. The local build step does not work on TeamCity as 'vite build' needs to be passed differently for a build configuration step. For production on TeamCity, npm run build:teamcity is used first, then 'vite build' is passed in:
run build:teamcity vite buildWe recommend using VS Code as the IDE. It's free, used consistently across NICE Digital Services because of the .NET integration and is extensible with high quality, useful extensions:
The following VS Code extensions are strongly recommended, but not required:
- EditorConfig for VS Code - configures VSCode to use the correct settings (line endings etc) for various files
- stylelint - this will highlight SCSS linting errors directly in the IDE
- eslint - automatically lints your JavaScript as you type and highlights any errors
- Prettier - Code formatter - highlights code formatting issues in the IDE and formats the file on save
- npm and npm Intellisense for support for using npm
- Jest for automatically running tests and highlighting errors in the IDE
- Check you have the right version of Node installed
- Make sure have LF line endings as this is a cross-platform project. This should happen automatically because of settings in .gitattributes and .editorconfig.
- Watch out for features of React that Nerv doesn't support, for example refs.
We support 2 main methods for using the Global Nav in your projects:
- as a React component installed directly into your app
- or externally to your app, loaded via the CDN.
Install and use Global Nav as a dependency in a React application to include it as part of your application bundle.
This is a good option if you're rendering you're app's interface via React, either client side or server side, or both. For example, if you're using Create React App, Gatsby or Next.js.
Note if you're using Create React App you'll need to use v2+ because we use CSS modules
Install the package and require the Header, Footer and Main React components into your application, just as you would for any other 3rd party component:
First, install the @nice-digital/global-nav package from npm into your project:
npm i @nice-digital/global-nav --saveNote: we used to recommend installing directly from GitHub via
npm i nice-digital/global-nav --save(notice the missing @), which still works but we now recommend using npm.
Then, require the header and/or footer and/or main into your application:
Import the header, footer and main component like this:
import { Header, Footer, Main } from '@nice-digital/global-nav';Note: we've used ES6 module imports for this examples as we've assumed all React apps will be using ES6.
These header, footer and main components that can be be used like any other React component and configured via props, for example:
const search = {
autocomplete: '/autocomplete',
};
const page = () => (
<div>
<Header service="guidance" search={search} />
<Main withPadding={true} myOptionalProp={myOptionalProp} className="my-optional-class" >{/* Your page content here */} </Main>
<Footer />
</div>
);Wrapping your template with the main component will render a main tag in the html with a back to top link.
For a full list of all the available props, see the props section below:
- Type:
Boolean - Default: true
Optional spacing between page content and footer back-to-top link.
- Type:
String | false - Default:
undefined
- Type:
String | null - Default:
'' - Values:
guidance,standards,evidence,bnf,bnfc,cks,journals
The identifier of the service to highlight in the main menu. See services.json for a list of the available service identifiers.
- Type:
String | null - Default:
'content-start'
The identifier of the skip link target. An empty div with this id will be created at the end of the header, if it doesn't already exist on the page.
- Type:
boolean - Default:
false
Optionally render the header with search box only to aid with debugging by reducing noise in the rendered output.
- Type:
String | Function - Default:
null
Function parameters:
element(HTMLAnchorElement) the HTML anchor element that was clicked to trigger the navigationhref(String) the href of the link that was clicked
Currently onNavigating only applies to the sub navigation.
Pass onNavigating to prevent default of the default navigation behaviour and
provide your own implementation. Pass either a function, or the name of a
function defined on window. E.g.:
window.onNavigatingHandler = function (e) {
// Define your implementation here e.g.:
if (e.href === '/#browse') {
// Trigger some custom behaviour
} else window.location.assign(e.href); // Fallback to navigation as normal
};
var global_nav_config = {
header: {
onNavigating: 'onNavigatingHandler',
},
};- Type:
String | Function - Default:
null
Pass an onResize function to handle when the header is resized. This includes banners being closed/collapsed:
var global_nav_config = {
header: {
onResize: function () {
// Define your resize implementation here
},
},
};Or the name of a function defined on window. E.g.:
window.onResizeHandler = function () {
// Define your resize implementation here
};
var global_nav_config = {
header: {
onResize: 'onResizeHandler',
},
};- Type:
String,Function - Default:
null
Pass an onDropdownOpen property to enable callback when dropdown is open.
Pass either a function, or the name of a function defined on window. E.g.:
window.onDropdownOpenHandler = function () {
// Define your implementation here e.g.:
document.querySelector("body").classList.add("global-nav__dropdown--open");
};
var global_nav_config = {
header: {
onDropdownOpen: 'onDropdownOpenHandler',
},
};- Type:
String,Function - Default:
null
Pass an onDropdownClose property to enable callback when dropdown is closed.
Pass either a function, or the name of a function defined on window. E.g.:
window.onDropdownCloseHandler = function (e) {
// Define your implementation here e.g.:
document.querySelector("body").classList.remove("global-nav__dropdown--open")
};
var global_nav_config = {
header: {
onDropdownClose: 'onDropdownCloseHandler',
},
};- Type:
null | Array - Default:
null
Pass an additionalSubMenuItems array to add extra sub menu items for a given service.
The array should be an array of objects, each containing a service: string and another array of links: Array.
The links array should contain an array of text: string and url: string. E.g:
const adminMenus = [{
service: "indev",
links: [{text: "Admin", url: "/admin"}]
},{
service: "publications",
links: [{text: "Admin", url: "/admin"}]
}];
var global_nav_config = {
header: {
additionalSubMenuItems: adminMenus,
},
};- Type:
Boolean | Object - Default:
{}
Search is enabled by default, pass false to disable it e.g. <Header search={false} />.
Or pass a set of key/value pairs to configure search and autocomplete:
- Type:
String - Default:
/search
The url of the search results page that the search form submits a GET request to. For example submitting a search term paracetamol with a url of /search will go to /search?q=paracetamol.
- Type:
Boolean | String | Array<AutoCompleteSuggestion> | AutoCompleteOptions - Default:
false
The source for autocomplete (typeahead) suggestions. Set to false to disable autocomplete.
Pass an array of objects to use as the source. The objects in the array should have two keys of Title: string and Link: string, with an optional TitleHtml: string and TypeAheadType: string. E.g.:
const suggestions = [
{ Title: 'Achilles tendinopathy', Link: '/achilles-tendinopathy' },
{ Title: 'Acne vulgaris', Link: '/acne-vulgaris', TitleHtml: '<mark>Acne</mark> vulgaris', TypeAheadType: 'keyword' },
];
<Header search={{ autocomplete: suggestions }} />;Pass a string, not containing a slash, to use a variable with that name on window e.g. <Header search={{ autocomplete: "topics" }} />. This is useful for when the suggestions are loaded asynchronously after page load.
Or to make a remote call to a URL on demand, if the source name does contain a slash e.g. <Header search={{ autocomplete: "/autocomplete?ajax=ajax" }} />.
The response is expected to be JSON in the format Array<{ Title: string, TitleHtml?: string, Link: string }> e.g.:
[
{
"Title": "Paracetamol",
"Link": "/search?q=Paracetamol"
},
{
"Title": "Paracetamol",
"TitleHtml": "<mark>Para</mark>cetamol",
"Link": "/search?q=Paracetamol",
"TypeAheadType": "keyword"
}
]Or to customise the template for autocomplete suggestions, pass an object with suggestions and suggestionTemplate, for example:
const autocompleteOptions = {
// Suggestions can be either the name of a variable, a remote url starting with a slash or an array
suggestions: "/a-remote-url",
// Return an HTML string, for example:
suggestionTemplate: (suggestion) => {
if (!suggestion || !suggestion.Link) return "";
return `<a href="${suggestion.Link}">${
suggestion.TitleHtml || suggestion.Title
}</a>`;
}
};
<Header search={{
autocomplete: autocompleteOptions
}} />;If you're using TypeScript, then you can import types e.g.:
import { AutoCompleteSuggestions, AutoCompleteOptions } from "@nice-digital/global-nav";- Type:
String - Default:
Search NICE…
Override the placeholder (and label) of the search input box, for example change to Search BNF… for the BNF microsite.
-
- Type:
String
- Type:
- Default:
""
The search query term, usually taken from the q value of the querstring.
If you're using .NET, use HttpUtility.JavaScriptStringEncode to avoid XSS attacks and make sure Request Validation is enabled.
Note: old TopHat looked for the q querystring value itself, but with Global Nav it's the responsibility of each application to pass in the search term.
- Type:
String,Function - Default:
null
Function parameters:
query(String) the query term used in the search
The search form by default submits a GET request to /search?q=XYZ.
Disable this and provide your own implementation by passing an onSearching property.
Pass either a function, or the name of a function defined on window. E.g.:
window.onSearchingHandler = function (e) {
// Define your implementation here e.g.:
window.location.assign('/search?q=' + encodeURIComponent(e.query));
};
var global_nav_config = {
header: {
search: {
onSearching: 'onSearchingHandler',
},
},
};- Type:
Boolean | Object - Default:
{}
Authentication is enabled by default. Disable authentication by passing false:
// React:
<Header auth={false} />
// Or config:
var global_nav_config = {
header: {
auth: false,
},
};Pass a set of key/value pairs to configure authentication, for example:
// React
<Header auth={{ environment: 'live', provider: 'niceAccounts' }} />
// Or config:
var global_nav_config = {
header: {
auth: { environment: 'live', provider: 'niceAccounts' },
},
};See the header.auth properties below for how to configure authentication providers.
- Type:
String - Default:
live - Values:
live,test,beta,local
This value is the authentication environment eg beta would be beta-accounts.nice.org.uk.
- Type:
String - Default:
niceAccounts - Values:
niceAccounts,idam
The authentication provider allows the provider to be changed. If the provider is set to niceAccounts then an environment be defined. If the provider is set to idam the links and displayName must be defined.
- Type:
Array | null - Default:
null - Values:
[{ key: "Sign in", value: "/Account/Login" }],[{ key: "My profile", value: "/Account/profile" },{ key: "Sign out", value: "/Account/Logout" }]
If the authentication provider has been set to "idam", then an array of links must be provided. If the user is logged out then a "Sign in" link should be provided with an appropriate url supplied - this should be the first in the list. If the user is logged in, then a number of links are supported, with a "Sign out" link normally last in the list, also a displayName must be supplied.
- Type:
String | null - Default:
null
The displayName is the user's name and must be provided if the "idam" provider is used and the user is logged in.
- Type:
String | false - Default:
undefined
Overrides how the AWS WAF challenge script is loaded. Leave it out and Global Nav loads the script for the page's hostname, if it knows of one.
Pass a URL to load that script instead, for example to test against a stand-in locally:
<Header awsWafScriptURL="https://localhost:4000/mock-aws-waf-jsapi.js" />Pass false to stop Global Nav loading the script at all, for example because your app includes it itself:
<Header awsWafScriptURL={false} />The Header, Footer and Main components all take this prop and all behave the same way, because no one of them is on every page of every service. Whichever mounts first does the work. false from any of them switches the challenge off for the rest of the page's life, so there's no need to pass it to all three as long as the one you pass it to mounts first - the header, usually.
- Type:
String | null - Default:
'' - Values:
pathways,guidance,standards,evidence,bnf,bnfc,cks,journals
The identifier of the currently active service. See services.json for a list of the available service identifiers.
- Type:
String | false - Default:
undefined
Reference the Global Nav bundle directly from the NICE CDN to render the Global Nav. We recommend including this before the closing </body> tag but before your application's scripts:
<script src="//cdn.nice.org.uk/global-nav/global-nav.min.js"></script>This renders with the default configuration. See the configuration section below for how to pass options into the Global Nav.
Note: you can reference the non-minified version by removing .min from the filename.
Reference a specific version of the global nav by including the build number as a sub folder. This is useful for testing, in case of a breaking change, or in case of needing to roll back for a hotfix, for example:
<script src="//alpha-cdn.nice.org.uk/global-nav/4.1.806-GN-180-FixInDev/global-nav.min.js"></script>
or
<script src="//cdn.nice.org.uk/global-nav/4.1.805%2Br6D13311/global-nav.min.js"></script>Note the production build needs the + character in the build metadata encoding as %2B to avoid browsers interpreting it as a space in the URL.
The CDN version of Global Nav creates its own containers for the header and footer if they don't already exist on the page. These containers use the ids:
global-nav-headerfor the headerglobal-nav-footerfor the footer.
Include empty elements with these ids on the page and Global Nav will render into these instead of creating its own:
<body>
<div id="global-nav-header"></div>
<main>
<!-- Your page content here -->
</main>
<div id="global-nav-footer"></div>
<script src="//cdn.nice.org.uk/global-nav/global-nav.min.js"></script>
</body>Where possible, we recommend using the provided configuration hooks like onSearching, onNavigating, onRendering, onRendered etc for hooking into or overriding default Global Nav behaviours, rather than using unsupported CSS selectors.
Use the global-nav-header and global-nav-footer ids to target the Global Nav for more bespoke behaviours - these are the only officially supported selector hooks.
Please don't rely on inner implementations for hooks or overrides.
For example, if you're targeting the search form via jQuery, use the robust $("#global-nav-header form[role='search']") selector rather than $("#global-nav-search-form") as this is an inner implementation and might change.
Try not to override Global Nav styles in your app: the Global Nav exists to give consistency across NICE digital services. If you really have to, then same rules as apply as above. For example in CSS:
#global-nav-header {
position: relative;
}Global Nav configuration is loaded from a global JavaScript variable on the window object called global_nav_config. Include this variable before the cdn script include. Here's a fulle example of all the available config options:
var global_nav_config = {
service: 'guidance',
header: {
skipLinkId: 'content-start',
cookie: true,
onNavigating: function (e) {
// Use e.href
},
auth: {
environment: 'beta',
provider: 'niceAccounts',
},
search: {
autocomplete: '/autocomplete?ajax=ajax',
url: '/search',
placeholder: 'Search NICE…',
query: '"diabetes in pregnancy"',
onSearching: function (e) {
// Use e.query
},
},
},
footer: false,
};The following config options apply:
- Type:
String - Default:
null
The key of the service to highlight on the navigation elements. See src/Header/Nav/links.json for the available options.
- Type:
Boolean | Object - Default:
null
The header renders by default, set header to false to stop it from rendering e.g. global_nav_config = { header: false }.
Or, pass an object of key/value pairs of settings specific to the header.
See the header props section for available options.
In addition to the options from the React props, there are also the following callbacks available when rendering using the CDN embed:
- Type:
Function | Stringsignature:function(element) - Default:
null
Function parameters:
element(HTMLElement) the HTML element the header will be rendered in to
A callback function, called just before the header is rendered. If it is a string, then a function with that name will be looked for on window.
- Type:
Function | Stringsignature:function(element) - Default:
null
Function parameters:
element(HTMLElement) the HTML the header was rendered in to
A callback function, called just after the header has been rendered. If it is a string, then a function with that name will be looked for on window.
- Type:
Boolean | Object - Default:
null
The footer renders by default, set footer to false to stop it from rendering e.g. global_nav_config = { footer: false }.
Or, pass an object of key/value pairs of settings specific to the footer.
See the footer props section for available options.
- Type:
String | Boolean - Default:
undefined
Overrides how the AWS WAF challenge script is loaded: a URL to load that script instead of the one for the page's hostname, or false to not load it at all e.g. global_nav_config = { awsWafScriptURL: false }.
This sits at the top level of the config, next to service, rather than under header or footer. That's deliberate: it still applies when either of those is set to false.
Global Nav loads the AWS WAF JavaScript SDK on services that sit behind an AWS WAF web ACL. The SDK silently acquires an aws-waf-token cookie in the background. The web ACL checks requests for that token and challenges the ones without it, which is how we tell real browsers from bots.
It's the web ACL that keeps the bots out, not this script. The script is there so that real users already hold a token by the time they need one, and never see the challenge interstitial.
Global Nav carries this because it's the one piece of code already on every NICE service. The alternative is each service adding the script for itself.
Each web ACL issues its own script URL, and the ids in that URL are generated by AWS, so it can't be worked out from the hostname. Instead there's a lookup table in src/aws-waf/integrations.js, with one entry per web ACL listing the hostnames it protects.
When Global Nav loads, it looks up window.location.hostname in that table. If there's an entry, it adds the script to the <head>. If there isn't, it does nothing, which is what we want for localhost and for any environment with no web ACL in front of it.
The table lists ops' sandbox and our live, alpha, beta, test and dev hostnames already, but a
scriptURLstays empty until ops create that web ACL. An entry with an empty URL does nothing, so on the other hostnames the script only loads whenawsWafScriptURLprop is passed.
The script is only ever added once per page. Global Nav also does nothing if the SDK is already there, i.e. window.AwsWafIntegration exists or the page has its own script tag pointing at awswaf.com.
Use awsWafScriptURL to override the lookup, or to switch the whole thing off.
Each entry in src/aws-waf/integrations.js looks like this:
export const integrations = [
{
hosts: ['www.nice.org.uk'],
scriptURL: 'https://<id>.eu-west-1.sdk.awswaf.com/<id>/<id>/challenge.js',
cookieDomains: ['.nice.org.uk'],
},
];hostsare exact hostnames, or a leading wildcard like*.nice.org.uk, which matches any subdomain at any depth but not the bare domain. An exact hostname always wins over a wildcard, wherever either one is in the table. Hostnames that share a load balancer (or CloudFront distribution) share a web ACL, so list them all against the one entry. The entries we ship were grouped by which hostnames resolve to the same address, which is a best guess at that: confirm it against the web ACLs ops actually create, and merge or split entries to match.scriptURLcomes from Application integration in the AWS WAF console. Ops are issuing the Intelligent threat integration URL, which ends inchallenge.js; the CAPTCHA integration one ends injsapi.jsand works the same way. It isn't a secret: it ends up in the page source. Leave it empty for a web ACL that doesn't exist yet and the entry does nothing.cookieDomainsis optional, e.g.['.nice.org.uk']. It widens the token cookie from the exact hostname so that one token works across subdomains. It's only valid once the same domain is on the web ACL's token domain list, otherwise AWS rejects the tokens, so ask ops for that at the same time as the URL. The shipped entries all set it.
A new or changed entry needs a Global Nav release. Services loading the unversioned CDN bundle pick that up straight away; services using the npm package pick it up when they next upgrade and deploy.
NICE Accounts sits behind a web ACL too, and the header calls it to find out whether you're signed in. That call is a script tag, which can't send the token as a header, so it relies on the aws-waf-token cookie instead. Global Nav waits for the SDK to have a token before it makes the call, so the cookie is there to send. With no SDK on the page it doesn't wait at all, and if the SDK hasn't got a token after 5 seconds it makes the call anyway.
This only works when the cookie reaches accounts.nice.org.uk:
- The page has to be on
nice.org.uk. A browser won't send a cookie from one domain to another, so services on other domains, and sandbox onsandbox1-ds.net, call NICE Accounts without a token. - The cookie has to be set on
.nice.org.ukand not on the exact hostname. The shipped entries do that withcookieDomains. AnawsWafScriptURLoverride doesn't, so setwindow.awsWafCookieDomainList = ['.nice.org.uk']on the page before Global Nav loads. .nice.org.ukhas to be on the token domain list of both web ACLs: the one in front of the page and the one in front of NICE Accounts.
If your service sets a Content Security Policy then script-src and connect-src need to allow https://*.awswaf.com.
We create 2 deployment artifacts: one for deploying to the CDN and one test site for previewing the header and footer.
To test what the deployment packages looks like locally, run the following command:
dotnet pack NICE.GlobalNav.CDN.csproj -o publish /p:Version=1.2.3-r1a2b3c
# OR dotnet pack NICE.GlobalNav.Preview.csproj -o publish /p:Version=1.2.3-r1a2b3cWhere the version number can be any valid SemVer build number compatible with Octopus Deploy. Note: this version number will be the build number when TeamCity creates this build artifact.
Note: you'll need the DotNet Core SDK installed. We don't use NuGet.exe to build so we can run on both Windows and Linux
Version 2 is a breaking change, because we removed the cookie banner and associated cookie option.
If you were already using cookie: false in the header config, then the upgrade is easy - the cookie: false will no longer do anything so can safely be removed.
If you were using cookie: true (or not setting the cookie option and leaving the default value of true) then you will need to include the cookie banner separately from Global Nav.
Version 3 removes react hot loader, replacing it with fast refresh. Although this is mostly internal implmenentation, react-hot-loader was a production dependency, and the Header and Footer components were both exported wrapped in hot. So this could affect services using Global Nav as an npm dependency (installed from GitHub).
V4 involved updating a lot of dependencies. Mostly this was internal implementation details. However, the one external facing change was the build command changing from npm run build -- --env.version=1.2.3 to npm run build -- --env version=1.2.3. Notice the space instead of the dot. This is a result of the --env parameter in webpack 4.
Version 5 includes updates for the summer 2022 brand refresh. It's mostly an internal refactor of typography and colour updates and shouldn't include any breaking API changes.
Version 6 is mostly updates of dependencies, the biggest of which was React Testing Library (from Enzyme). It also includes support for React 18 and Design System v5.
Updated autocomplete component.
In Version 7.1, significant changes to improve the development and build processes of the project have been introduced:
Migration from Webpack to Vite, a faster build tool. Vite provides improved performance and a better development experience with features like Fast Refresh, which replaces React Hot Loader. Terser minification options enable further optimisation of the bundle size, resulting in approximately 10% reduction in bundle size during the build process.
With the migration to Vite, transitioning to TypeScript in the future will be more straightforward. Vite's TypeScript support will make the process smoother when the time comes for the project to adopt TypeScript.