diff --git a/README.md b/README.md index a7ed33ddf..55ad299a2 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,15 @@ To publish ``` $ yarn publish:npm ``` + +### Testing + +Install Playwright: +``` +yarn playwright install +``` + +Run the tests +``` +yarn test:e2e:local +``` \ No newline at end of file diff --git a/docs/utils.md b/docs/utils.md index 8d18a62cb..04738eefa 100644 --- a/docs/utils.md +++ b/docs/utils.md @@ -53,18 +53,20 @@ How to use in your styled component `@media ${({ theme }) => theme.allBreakpoints('M')} {` #### screen sizes: -``` -import { breakpointValues } from '../../../theme/shared/allBreakpoints'; -... -max-width: ${breakpointValues.M}px; -``` +`import { breakpointValues } from '../../../theme/shared/allBreakpoints';` + +`...` + +`max-width: ${breakpointValues.M}px;` + ### Usage within Component Library -``` -import { breakpointValues } from '@comicrelief/component-library/src/theme/shared/allBreakpoints'; -... -max-width: ${breakpointValues.M}px); -``` +`import { breakpointValues } from '@comicrelief/component-library/src/theme/shared/allBreakpoints';` + +`...` + +`max-width: ${breakpointValues.M}px);` + ## containers from containers.js diff --git a/playwright/components/organisms/header.spec.js b/playwright/components/organisms/header.spec.js index e54ba90e7..82ffffea9 100644 --- a/playwright/components/organisms/header.spec.js +++ b/playwright/components/organisms/header.spec.js @@ -2,80 +2,67 @@ const { test, expect } = require('@playwright/test'); test.describe('header component', () => { test('Comic Relief header', async ({ page }) => { - await page.goto('/#header'); await expect(page.locator('[data-testid="Header-example-1"]')).toBeVisible(); // donate locator - await expect(page.locator('[data-testid="Header-example-1"] header[role="banner"] a[href="/donation"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-1"] header[role="banner"] [data-testid="donate-button--desktop"] a[href="/donation"]')).toBeVisible(); // CR logo await expect(page.locator('[data-testid="Header-example-1"] [title="Go to Comic Relief homepage"]')).toBeVisible(); - // shop - await expect(page.locator('[data-testid="Header-example-1"] header[role="banner"] a[href*="/shop"]')).toBeVisible(); await page.close(); }); test('Sport Relief header', async ({ page }) => { - await page.goto('/#header'); await expect(page.locator('[data-testid="Header-example-3"]')).toBeVisible(); // donate locator - await expect(page.locator('[data-testid="Header-example-3"] header[role="banner"] a[href="/donation"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-3"] header[role="banner"] [data-testid="donate-button--desktop"] a[href="/donation"]')).toBeVisible(); // SR logo await expect(page.locator('[data-testid="Header-example-3"] header[role="banner"] a[href="/sportrelief"]')).toBeVisible(); - // shop - await expect(page.locator('[data-testid="Header-example-3"] header[role="banner"] a[href*="/shop"]')).toBeVisible(); await page.close(); }); test('Pride header', async ({ page }) => { - await page.goto('/#header'); await expect(page.locator('[data-testid="Header-example-5"]')).toBeVisible(); // donate locator - await expect(page.locator('[data-testid="Header-example-5"] header[role="banner"] a[href="/donation"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-5"] header[role="banner"] [data-testid="donate-button--desktop"] a[href="/donation"]')).toBeVisible(); // CR logo await expect(page.locator('[data-testid="Header-example-5"] [title="Go to Comic Relief homepage"]')).toBeVisible(); - // shop - await expect(page.locator('[data-testid="Header-example-5"] header[role="banner"] a[href*="/shop"]')).toBeVisible(); await page.close(); }); test('Comic Relief header with Search', async ({ page }) => { - await page.goto('/#header'); await expect(page.locator('[data-testid="Header-example-7"]')).toBeVisible(); // donate locator - await expect(page.locator('[data-testid="Header-example-7"] header[role="banner"] a[href="/donation"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-7"] header[role="banner"] [data-testid="donate-button--desktop"] a[href="/donation"]')).toBeVisible(); // CR logo await expect(page.locator('[data-testid="Header-example-7"] [title="Go to Comic Relief homepage"]')).toBeVisible(); - // shop - await expect(page.locator('[data-testid="Header-example-7"] header[role="banner"] a[href*="/shop"]')).toBeVisible(); // search - await expect(page.locator('[data-testid="Header-example-7"] header[role="banner"] a[href="/search"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-7"] header[role="banner"] [data-testid="meta-icons--desktop"] a[data-testid="header-search"]')).toBeVisible(); await page.close(); }); test('Comic Relief header with Search and Shop', async ({ page }) => { - await page.goto('/#header'); await expect(page.locator('[data-testid="Header-example-9"]')).toBeVisible(); // donate locator - await expect(page.locator('[data-testid="Header-example-9"] header[role="banner"] a[href="/donation"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-9"] header[role="banner"] [data-testid="donate-button--desktop"] a[href="/donation"]')).toBeVisible(); // CR logo await expect(page.locator('[data-testid="Header-example-9"] [title="Go to Comic Relief homepage"]')).toBeVisible(); // shop icon - await expect(page.locator('[data-testid="Header-example-9"] header[role="banner"] [title="Shop"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-9"] header[role="banner"] [data-testid="meta-icons--desktop"] [title="Shop"]')).toBeVisible(); // search - await expect(page.locator('[data-testid="Header-example-9"] header[role="banner"] a[href="/search"]')).toBeVisible(); + await expect(page.locator('[data-testid="Header-example-9"] header[role="banner"] [data-testid="meta-icons--desktop"] a[data-testid="header-search"]')).toBeVisible(); await page.close(); }); diff --git a/src/components/Atoms/Logo/Logo.js b/src/components/Atoms/Logo/Logo.js index 67395c28a..10eabc22f 100644 --- a/src/components/Atoms/Logo/Logo.js +++ b/src/components/Atoms/Logo/Logo.js @@ -70,8 +70,8 @@ Logo.propTypes = { Logo.defaultProps = { rotate: false, - sizeSm: '51px', // - to work with the header 75px height and 12px padding - sizeMd: '70px', + sizeSm: '51px', + sizeMd: '51px', campaign: 'Comic Relief' }; diff --git a/src/components/Atoms/Logo/Logo.test.js b/src/components/Atoms/Logo/Logo.test.js index fa698c860..9fa011307 100644 --- a/src/components/Atoms/Logo/Logo.test.js +++ b/src/components/Atoms/Logo/Logo.test.js @@ -25,9 +25,9 @@ it("renders correctly", () => { vertical-align: bottom; } - @media (min-width:1150px) { + @media (min-width:1175px) { .c0 { - width: 70px; + width: 51px; } } diff --git a/src/components/Atoms/SocialIcons/Icon/Icon.js b/src/components/Atoms/SocialIcons/Icon/Icon.js index b215f496f..9cc6f23e1 100755 --- a/src/components/Atoms/SocialIcons/Icon/Icon.js +++ b/src/components/Atoms/SocialIcons/Icon/Icon.js @@ -1,17 +1,73 @@ import React from 'react'; import PropTypes from 'prop-types'; -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; +import { kebabCase } from 'lodash'; import hideVisually from '../../../../theme/shared/hideVisually'; +import Text from '../../Text/Text'; + +const RevealTextWidth = 58; +const RevealTextSpeed = 0.35; const StyledLink = styled.a` text-decoration: none; cursor: pointer; display: block; - transition: opacity 0.2s; + position: relative; + + ${({ isHeader }) => isHeader && css` + overflow: hidden; + padding-right: 0px; + transition: padding-right ${RevealTextSpeed}s cubic-bezier(0.5, 1.5, 0.5, 0.75); + + &:hover, + &:focus { + img { + filter: invert(0.5) sepia(1) saturate(100) hue-rotate(20deg); + } + } + + @media ${({ theme }) => theme.allBreakpoints('NavWithAnimations')} { + &:hover, + &:focus { + // Default + padding-right: ${RevealTextWidth}px; + + // Tweak for ESU's longer text: + &[data-testid="header-esu"] { + padding-right: 95px; + } + + // Tweak for Shop 's shorter text: + &[data-testid="header-shop"] { + padding-right: 52px; + } + + // Show the Reveal text + img + span { + display: block; + } + } + `} + }; +`; + +const RevealText = styled(Text)` + width: auto; + color: ${({ theme }) => theme.color('black')}; + position: absolute; + top: 50%; + transform: translateY(-50%); + left: 70px; - &:hover, - &:focus { - opacity: 0.6; + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + width: 100%; + text-align: center; + position: absolute; + top: 8px; + left: 15px; + transform: translateX(0); + display: none; + color: ${({ theme }) => theme.color('red')}; } `; @@ -24,7 +80,7 @@ const HelperText = styled.span` `; const Icon = ({ - href, target, icon, brand, title, ...restProps + href, target, icon, brand, title, isHeader, id, ...restProps }) => ( - {title !== 'Sign up for emails' && ( + + { isHeader && ( + {title} + )} + + {id === 'esu' && ( (opens in new window) )} ); +Icon.defaultProps = { + isHeader: false +}; + Icon.propTypes = { brand: PropTypes.string.isRequired, href: PropTypes.string.isRequired, target: PropTypes.string.isRequired, icon: PropTypes.string.isRequired, - title: PropTypes.string.isRequired + title: PropTypes.string.isRequired, + isHeader: PropTypes.bool, + id: PropTypes.string.isRequired }; export default Icon; diff --git a/src/components/Atoms/SocialIcons/SocialIcons.js b/src/components/Atoms/SocialIcons/SocialIcons.js index 725e5d850..1cdc3f2a1 100755 --- a/src/components/Atoms/SocialIcons/SocialIcons.js +++ b/src/components/Atoms/SocialIcons/SocialIcons.js @@ -40,6 +40,7 @@ const SocialIcons = ({ campaign, ...restProps }) => { href={links[brand].url} title={links[brand].title} brand={brand} + id={links[brand].id} {...restProps} /> diff --git a/src/components/Atoms/SocialIcons/Utils/Links.js b/src/components/Atoms/SocialIcons/Utils/Links.js index 0844b582d..de8eb0210 100644 --- a/src/components/Atoms/SocialIcons/Utils/Links.js +++ b/src/components/Atoms/SocialIcons/Utils/Links.js @@ -6,18 +6,22 @@ export default campaign => ({ facebook: { url: `https://www.facebook.com/${campaign}`, - title: 'Check out our Facebook page' + title: 'Check out our Facebook page', + id: 'facebook' }, twitter: { url: `https://twitter.com/${campaign}`, - title: 'Check out our Twitter account' + title: 'Check out our Twitter account', + id: 'twitter' }, youtube: { url: 'https://www.youtube.com/channel/UCdF5u0ggeSETozc8fsprjcw', - title: 'Check out our YouTube channel' + title: 'Check out our YouTube channel', + id: 'youtube' }, instagram: { url: `https://www.instagram.com/${campaign}`, - title: 'Check out our Instagram account' + title: 'Check out our Instagram account', + id: 'instagram' } }); diff --git a/src/components/Atoms/SocialIcons/__snapshots__/SocialIcons.test.js.snap b/src/components/Atoms/SocialIcons/__snapshots__/SocialIcons.test.js.snap index 203e75e52..9379a53e6 100644 --- a/src/components/Atoms/SocialIcons/__snapshots__/SocialIcons.test.js.snap +++ b/src/components/Atoms/SocialIcons/__snapshots__/SocialIcons.test.js.snap @@ -6,34 +6,13 @@ exports[`renders correctly with Comic Relief links 1`] = ` text-decoration: none; cursor: pointer; display: block; - -webkit-transition: opacity 0.2s; - transition: opacity 0.2s; -} - -.c2:hover, -.c2:focus { - opacity: 0.6; + position: relative; } .c3 { width: 100%; } -.c4 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; -} - .c0 { display: -webkit-box; display: -webkit-flex; @@ -80,7 +59,7 @@ exports[`renders correctly with Comic Relief links 1`] = ` > - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • @@ -176,34 +135,13 @@ exports[`renders correctly with Red Nose Day links and self target 1`] = ` text-decoration: none; cursor: pointer; display: block; - -webkit-transition: opacity 0.2s; - transition: opacity 0.2s; -} - -.c2:hover, -.c2:focus { - opacity: 0.6; + position: relative; } .c3 { width: 100%; } -.c4 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; -} - .c0 { display: -webkit-box; display: -webkit-flex; @@ -250,7 +188,7 @@ exports[`renders correctly with Red Nose Day links and self target 1`] = ` > - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • @@ -346,34 +264,13 @@ exports[`renders correctly with Sport Relief links 1`] = ` text-decoration: none; cursor: pointer; display: block; - -webkit-transition: opacity 0.2s; - transition: opacity 0.2s; -} - -.c2:hover, -.c2:focus { - opacity: 0.6; + position: relative; } .c3 { width: 100%; } -.c4 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; -} - .c0 { display: -webkit-box; display: -webkit-flex; @@ -420,7 +317,7 @@ exports[`renders correctly with Sport Relief links 1`] = ` > - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • diff --git a/src/components/Molecules/Logos/Logos.js b/src/components/Molecules/Logos/Logos.js index 64f49d8be..940957d47 100644 --- a/src/components/Molecules/Logos/Logos.js +++ b/src/components/Molecules/Logos/Logos.js @@ -10,45 +10,58 @@ const TitleLabel = styled.span` color: transparent; `; +const LogoLink = styled.a` + img { + transition: transform 0.35s cubic-bezier(0.41, 1.64, 0.41, 0.8); + } + + &:hover, + &:focus { + img { + transform: rotate(-14deg); + } + } +`; + const Logos = ({ campaign }) => { if (campaign === 'Sport Relief Gameon') { return ( <> - + Go to Comic Relief homepage - - + + Go to Sport Relief homepage - + ); } if (campaign === 'Sport Relief') { return ( - + Go to Sport Relief homepage - + ); } if (campaign === 'Pride') { return ( - + Go to Comic Relief homepage - + ); } return ( - + Go to Comic Relief homepage - + ); }; diff --git a/src/components/Molecules/ShareButton/ShareButton.test.js b/src/components/Molecules/ShareButton/ShareButton.test.js index 690a4511b..61335b32f 100644 --- a/src/components/Molecules/ShareButton/ShareButton.test.js +++ b/src/components/Molecules/ShareButton/ShareButton.test.js @@ -1,9 +1,9 @@ -import React from 'react'; -import 'jest-styled-components'; -import renderWithTheme from '../../../hoc/shallowWithTheme'; -import ShareButton from './ShareButton'; +import React from "react"; +import "jest-styled-components"; +import renderWithTheme from "../../../hoc/shallowWithTheme"; +import ShareButton from "./ShareButton"; -it('renders correctly', () => { +it("renders correctly", () => { const tree = renderWithTheme().toJSON(); expect(tree).toMatchInlineSnapshot(` @@ -12,34 +12,13 @@ it('renders correctly', () => { text-decoration: none; cursor: pointer; display: block; - -webkit-transition: opacity 0.2s; - transition: opacity 0.2s; - } - - .c4:hover, - .c4:focus { - opacity: 0.6; + position: relative; } .c5 { width: 100%; } - .c6 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; - } - .c0 { display: -webkit-box; display: -webkit-flex; @@ -94,7 +73,7 @@ it('renders correctly', () => { > { className="c5" src="mock.asset" /> - - (opens in new window) -
  • { > { className="c5" src="mock.asset" /> - - (opens in new window) -
  • diff --git a/src/components/Organisms/Footer/Nav/Nav.js b/src/components/Organisms/Footer/Nav/Nav.js index 4e102e7a8..e33bd8587 100644 --- a/src/components/Organisms/Footer/Nav/Nav.js +++ b/src/components/Organisms/Footer/Nav/Nav.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import Text from '../../../Atoms/Text/Text'; import { breakpointValues } from '../../../../theme/shared/allBreakpoints'; -import NavHelper from '../../../../utils/navHelper'; +import { NavHelper } from '../../../../utils/navHelper'; import { InternalLinkHelper } from '../../../../utils/internalLinkHelper'; import { @@ -62,7 +62,8 @@ const FooterNav = ({ navItems, ...rest }) => { {menuGroups.map((group, index) => ( diff --git a/src/components/Organisms/Footer/__snapshots__/Footer.test.js.snap b/src/components/Organisms/Footer/__snapshots__/Footer.test.js.snap index 927ad2c01..656b7e0d0 100644 --- a/src/components/Organisms/Footer/__snapshots__/Footer.test.js.snap +++ b/src/components/Organisms/Footer/__snapshots__/Footer.test.js.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders correctly 1`] = ` -.c13 { +.c12 { font-size: 1rem; line-height: 1rem; text-transform: inherit; font-family: 'Montserrat',Helvetica,Arial,sans-serif; } -.c16 { +.c15 { color: #FFFFFF; font-size: 1rem; line-height: 1rem; @@ -18,7 +18,7 @@ exports[`renders correctly 1`] = ` font-family: 'Montserrat',Helvetica,Arial,sans-serif; } -.c21 { +.c20 { color: #FFFFFF; font-size: 1rem; line-height: 1rem; @@ -27,7 +27,7 @@ exports[`renders correctly 1`] = ` font-family: 'Montserrat',Helvetica,Arial,sans-serif; } -.c26 { +.c25 { color: #969598; font-size: 1rem; line-height: 1rem; @@ -36,7 +36,7 @@ exports[`renders correctly 1`] = ` font-family: 'Montserrat',Helvetica,Arial,sans-serif; } -.c11 { +.c10 { object-fit: cover; width: 100%; display: block; @@ -44,7 +44,7 @@ exports[`renders correctly 1`] = ` margin-right: 1rem; } -.c10 { +.c9 { display: inline-block; z-index: 3; width: 48px; @@ -54,7 +54,7 @@ exports[`renders correctly 1`] = ` vertical-align: bottom; } -.c8 { +.c7 { position: relative; -webkit-text-decoration: none; text-decoration: none; @@ -65,12 +65,12 @@ exports[`renders correctly 1`] = ` font-weight: normal; } -.c8:hover { +.c7:hover { color: #000000; border-bottom: 2px solid #000000; } -.c24 { +.c23 { border: 0; -webkit-clip: rect(0 0 0 0); clip: rect(0 0 0 0); @@ -90,34 +90,13 @@ exports[`renders correctly 1`] = ` text-decoration: none; cursor: pointer; display: block; - -webkit-transition: opacity 0.2s; - transition: opacity 0.2s; -} - -.c5:hover, -.c5:focus { - opacity: 0.6; + position: relative; } .c6 { width: 100%; } -.c7 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; -} - .c3 { display: -webkit-box; display: -webkit-flex; @@ -141,25 +120,25 @@ exports[`renders correctly 1`] = ` margin-right: 1.5rem; } -.c19 { +.c18 { border: 0; height: 46px; width: 100%; background-color: #2C0230; } -.c19:hover, -.c19:focus { +.c18:hover, +.c18:focus { border-bottom: none; } -.c12 { +.c11 { display: block; width: 100%; text-align: left; } -.c12 > h2 { +.c11 > h2 { border: 0; -webkit-clip: rect(0 0 0 0); clip: rect(0 0 0 0); @@ -174,7 +153,7 @@ exports[`renders correctly 1`] = ` width: 1px; } -.c17 { +.c16 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -191,18 +170,18 @@ exports[`renders correctly 1`] = ` flex-direction: column; } -.c17 > li a { +.c16 > li a { display: none; font-size: 15px; font-weight: 500; cursor: pointer; } -.c17 > li a:after { +.c16 > li a:after { content: none; } -.c22 { +.c21 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -219,52 +198,52 @@ exports[`renders correctly 1`] = ` flex-direction: column; } -.c22 > li a { +.c21 > li a { display: none; font-size: 15px; font-weight: 500; cursor: pointer; } -.c22 > li a:after { +.c21 > li a:after { content: none; } -.c18 { +.c17 { height: 40px; width: 100%; background-color: inherit; padding: 8px 0; } -.c23 { +.c22 { height: 40px; width: 100%; background-color: inherit; padding: 8px 0; } -.c20 { +.c19 { padding: 14px 21px; height: auto; position: relative; } -.c14 { +.c13 { background-color: inherit; list-style: none outside; padding: 0; margin: 0; } -.c15 { +.c14 { position: relative; font-weight: 700; margin: 0; margin-bottom: 1rem; } -.c15 a { +.c14 a { width: auto; padding: 0; height: auto; @@ -275,7 +254,7 @@ exports[`renders correctly 1`] = ` font-weight: 800; } -.c15 a:after { +.c14 a:after { content: '\\2303'; position: absolute; font-family: Arial; @@ -329,7 +308,7 @@ exports[`renders correctly 1`] = ` align-items: center; } -.c25 { +.c24 { display: block; width: 100%; height: 100%; @@ -337,23 +316,23 @@ exports[`renders correctly 1`] = ` margin-top: 3rem; } -.c25 p { +.c24 p { font-size: 15px; line-height: 24px; margin-bottom: 5px; } -.c9 { +.c8 { color: transparent; border: 0; } -.c9:hover { +.c8:hover { border: 0; } -@media (min-width:1150px) { - .c10 { +@media (min-width:1175px) { + .c9 { width: 72px; } } @@ -374,19 +353,19 @@ exports[`renders correctly 1`] = ` } @media (min-width:740px) { - .c17 { + .c16 { max-height: none; height: auto; } - .c17 > li a { + .c16 > li a { display: inline; line-height: 24px; } } @media (min-width:740px) { - .c22 { + .c21 { max-height: none; height: auto; -webkit-flex-direction: row; @@ -397,35 +376,35 @@ exports[`renders correctly 1`] = ` flex-wrap: wrap; } - .c22 > li a { + .c21 > li a { display: inline; line-height: 24px; } } @media (min-width:740px) { - .c18 { + .c17 { height: auto; margin-top: 12px; padding: 0; } - .c18 a { + .c17 a { background-color: inherit; height: auto; } - .c18 a:after { + .c17 a:after { content: none !important; } - .c18 a:hover, - .c18 a:focus { + .c17 a:hover, + .c17 a:focus { border-bottom: 2px solid #fff; } - .c18 a:hover span, - .c18 a:focus span { + .c17 a:hover span, + .c17 a:focus span { border-bottom: 0; padding-bottom: 2px; } @@ -436,7 +415,7 @@ exports[`renders correctly 1`] = ` } @media (min-width:740px) { - .c23 { + .c22 { height: auto; margin-top: 12px; padding: 0; @@ -445,29 +424,29 @@ exports[`renders correctly 1`] = ` flex: 0 0 100%; } - .c23 a { + .c22 a { background-color: inherit; height: auto; } - .c23 a:after { + .c22 a:after { content: none !important; } - .c23 a:hover, - .c23 a:focus { + .c22 a:hover, + .c22 a:focus { border-bottom: 2px solid #fff; } - .c23 a:hover span, - .c23 a:focus span { + .c22 a:hover span, + .c22 a:focus span { border-bottom: 0; padding-bottom: 2px; } } @media (min-width:1024px) { - .c23 { + .c22 { -webkit-flex: 0 0 100%; -ms-flex: 0 0 100%; flex: 0 0 100%; @@ -475,7 +454,7 @@ exports[`renders correctly 1`] = ` } @media (min-width:740px) { - .c14 { + .c13 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -491,7 +470,7 @@ exports[`renders correctly 1`] = ` } @media (min-width:740px) { - .c15 { + .c14 { -webkit-flex: 0 0 30%; -ms-flex: 0 0 30%; flex: 0 0 30%; @@ -500,7 +479,7 @@ exports[`renders correctly 1`] = ` } @media (min-width:1024px) { - .c15 { + .c14 { -webkit-flex: 0 0 calc(25% - 1rem); -ms-flex: 0 0 calc(25% - 1rem); flex: 0 0 calc(25% - 1rem); @@ -508,25 +487,25 @@ exports[`renders correctly 1`] = ` margin-bottom: 1rem; } - .c15 > span { + .c14 > span { padding: 0; } } @media (min-width:740px) { - .c15 a { + .c14 a { font-size: 20px; line-height: 40px; } } @media (min-width:740px) { - .c15 a { + .c14 a { cursor: default; display: inline; } - .c15 a:after { + .c14 a:after { content: none; } } @@ -544,7 +523,7 @@ exports[`renders correctly 1`] = ` } @media (min-width:1024px) { - .c25 p { + .c24 p { font-size: 16px; line-height: 27px; } @@ -573,7 +552,7 @@ exports[`renders correctly 1`] = ` > - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • - - (opens in new window) -
  • Comic Relief logo
    @@ -684,11 +643,11 @@ exports[`renders correctly 1`] = `

    diff --git a/src/components/Organisms/Header/Burger/BurgerMenu.style.js b/src/components/Organisms/Header/Burger/BurgerMenu.style.js index 1b6de22e6..81789fcaf 100644 --- a/src/components/Organisms/Header/Burger/BurgerMenu.style.js +++ b/src/components/Organisms/Header/Burger/BurgerMenu.style.js @@ -50,6 +50,7 @@ const BurgerWrapper = styled(Link)` ::after { width: 25px; height: 3px; + border-radius: 3px; display: inline-block; } diff --git a/src/components/Organisms/Header/Header.js b/src/components/Organisms/Header/Header.js index 3168a6b1f..d5c7adbca 100644 --- a/src/components/Organisms/Header/Header.js +++ b/src/components/Organisms/Header/Header.js @@ -2,36 +2,43 @@ import React from 'react'; import PropTypes from 'prop-types'; import Logos from '../../Molecules/Logos/Logos'; -import MainNav from './Nav/Nav'; +import HeaderNav from './HeaderNav/HeaderNav'; import { - Brand, HeaderWrapper, InnerWrapper, MetaIcons + Brand, HeaderWrapper, InnerWrapper, DonateButtonWrapperTop, HeaderMetaIcons, ButtonsAndIcons } from './Header.style'; const Header = ({ - navItems, metaIcons, campaign, ...rest + navItems, metaIcons, campaign, donateButton, ...rest }) => ( - + - - {metaIcons} + + + {metaIcons} + {donateButton} + + ); Header.propTypes = { - /** Check data structure example in file src/components/moleculecules/header/data/data */ + // Check data structure example in src/components/moleculecules/header/data/data navItems: PropTypes.objectOf(PropTypes.shape), - /** it can be icons, buttons */ + // NB: metaIcons no longer include the Donate button: metaIcons: PropTypes.node.isRequired, + // ... and is supplied separately to allow more render control: + donateButton: PropTypes.node, campaign: PropTypes.string }; Header.defaultProps = { navItems: {}, - campaign: 'Comic Relief' + campaign: 'Comic Relief', + donateButton: null }; export default Header; diff --git a/src/components/Organisms/Header/Header.md b/src/components/Organisms/Header/Header.md index 0406b5971..4ab4f9451 100644 --- a/src/components/Organisms/Header/Header.md +++ b/src/components/Organisms/Header/Header.md @@ -7,9 +7,9 @@ import Link from '../../Atoms/Link/Link';

    - + Donate @@ -26,9 +26,9 @@ import Link from '../../Atoms/Link/Link';
    - + Donate @@ -45,9 +45,9 @@ import Link from '../../Atoms/Link/Link';
    - + Donate @@ -87,12 +87,15 @@ const [success, setSuccess] = React.useState(false);
    - + Donate - + + } + metaIcons={ + <>
    @@ -109,7 +114,7 @@ const [success, setSuccess] = React.useState(false); />; ``` -# Comic Relief header with Search and Shop +# Comic Relief full header #1 ```js import data from './data/data'; @@ -117,6 +122,7 @@ import Link from '../../Atoms/Link/Link'; import searchIcon from './assets/icon--search--2023.svg'; import shopIcon from './assets/icon--shop--2023.svg'; import payinIcon from './assets/PayIn.svg'; +import esuIcon from './assets/Post.svg'; import Icon from '../../Atoms/SocialIcons/Icon/Icon'; import RichText from '../../Atoms/RichText/RichText'; @@ -141,14 +147,59 @@ const successCopy = ( initialState = { isSuccess: false }; const [success, setSuccess] = React.useState(false); +<>
    - + Donate + + } + metaIcons={ + <> +
    + +
    +
    + +
    + +
    + +
    +
    + + } +/> +
    + +
    +; +``` + +# Comic Relief full header #2 + +```js +import data from './data/data-extended'; +import Link from '../../Atoms/Link/Link'; +import searchIcon from './assets/icon--search--2023.svg'; +import shopIcon from './assets/icon--shop--2023.svg'; +import payinIcon from './assets/PayIn.svg'; +import esuIcon from './assets/Post.svg'; + +import Icon from '../../Atoms/SocialIcons/Icon/Icon'; +import RichText from '../../Atoms/RichText/RichText'; + +const title = 'Stay in the know!'; +const topCopy = ( + Get regular email updates and info on what we're up to!

    `} + /> +); +const privacyCopy = ( + Our
    Privacy Policy describes how we handle and protect your information.

    If you are under 18, please make sure you have your parents’ permission before providing us with any personal details.

    `} + /> +); +const successCopy = ( + Thanks! Your first email will be with you shortly

    `} + /> +); + +initialState = { isSuccess: false }; +const [success, setSuccess] = React.useState(false); + +<> +
    + + Donate + + + } + metaIcons={ + <> +
    +
    +
    + +
    +
    +
    } -/>; +/> +
    + +
    +; ``` diff --git a/src/components/Organisms/Header/Header.style.js b/src/components/Organisms/Header/Header.style.js index eb818e65d..f9005d183 100644 --- a/src/components/Organisms/Header/Header.style.js +++ b/src/components/Organisms/Header/Header.style.js @@ -4,6 +4,8 @@ import zIndex from '../../../theme/shared/zIndex'; import containers from '../../../theme/shared/containers'; import spacing from '../../../theme/shared/spacing'; +import './annoying.css'; + const HeaderWrapper = styled.header.attrs(() => ({ role: 'banner' }))` @@ -47,32 +49,57 @@ const Brand = styled.div` border: 0; } } + + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + margin-right: 0 + } `; -const MetaIcons = styled.div` - width: auto; +const DonateButtonWrapperTop = styled.div` + width: 120px; display: flex; - align-items: center; + justify-content: center; - > div { - height: 35px; - width: auto; - display: inline-block; + // Donate button + a { + width: 90%; + transition: width 0.4s cubic-bezier(0.5, 1.5, 0.5, 0.80); + + &:hover, + &:focus { + width: 100%; + box-shadow: rgba(0, 0, 0, 0.1) 0 0 20px 0; + } + } +`; + +const HeaderMetaIcons = styled.div` + // Hide these when using the mobile navigation, + // now only rendered in the HeaderNav + display: none; - > a { - height: inherit; - width: inherit; - margin-left: 0.5rem; + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + width: auto; + align-items: center; - img { - padding: 5px; + > div { + height: 35px; + width: auto; + display: inline-block; + + > a { height: inherit; width: inherit; + margin-right: 20px; + + img { + padding: 5px; + height: inherit; + width: inherit; + } } } - } - @media ${({ theme }) => theme.allBreakpoints('Nav')} { position: relative; display: flex; align-items: center; @@ -82,6 +109,12 @@ const MetaIcons = styled.div` } `; +const ButtonsAndIcons = styled.div` + margin-left: auto; + display: flex; + // +`; + export { - Brand, HeaderWrapper, InnerWrapper, MetaIcons + Brand, HeaderWrapper, InnerWrapper, DonateButtonWrapperTop, HeaderMetaIcons, ButtonsAndIcons }; diff --git a/src/components/Organisms/Header/HeaderNav/HeaderNav.js b/src/components/Organisms/Header/HeaderNav/HeaderNav.js new file mode 100644 index 000000000..93ea4285c --- /dev/null +++ b/src/components/Organisms/Header/HeaderNav/HeaderNav.js @@ -0,0 +1,353 @@ +import React, { useState, useEffect, useCallback } from 'react'; +import PropTypes from 'prop-types'; + +import Text from '../../../Atoms/Text/Text'; +import BurgerMenu from '../Burger/BurgerMenu'; +import { breakpointValues } from '../../../../theme/shared/allBreakpoints'; +import { NavHelper, MoreNavPreProcess } from '../../../../utils/navHelper'; +import { InternalLinkHelper } from '../../../../utils/internalLinkHelper'; +import allowListed from '../../../../utils/allowListed'; +import menuGroupIcon from './Menu-Group-Icon.svg'; + +import { + Nav, + NavMenu, + NavItem, + NavLink, + SubNavMenu, + SubNavItem, + SubNavLink, + ChevronWrapper, + NavMetaIcons, + // More Nav stuff: + MoreNavLink, + MoreSubNavMenu, + MoreNavItem, + MoreNestedSubNavMenu, + MoreSubNavItem, + MoreNavNestedLink, + MoreSubNavLink, + DonateButtonWrapperBottom +} from './HeaderNav.style'; + +const HeaderNav = ({ + navItems, metaIcons, donateButton, characterLimit +}) => { + const { menuGroups } = navItems; + const [isExpandable, setIsExpandable] = useState(false); + const [isSubMenuOpen, setIsSubMenuOpen] = useState({}); + const [isTabFocussed, setIsTabFocussed] = useState({}); + const [isNotDesktop, setIsNotDesktop] = useState(null); + const [processedItems, setProcessedItems] = useState(null); + let theseGroups = null; + + const toggleBurgerMenu = event => { + event.preventDefault(); + setIsExpandable(!isExpandable); + }; + + const toggleSubMenu = (e, item) => { + e.preventDefault(); + setIsSubMenuOpen({ [item]: !isSubMenuOpen[item] }); + }; + + // Handle tab key on menu nav + const keyPressed = item => () => { + window.onkeyup = e => { + // Specifies the tab key: + if (e.which === 9) { + // If the currently tabbed-to element is our item, do something + if (e.target.querySelector('span') && e.target.querySelector('span').innerText === item) { + setIsTabFocussed({ [item]: !isTabFocussed[item] }); + } else if (!e.target.querySelector('span')) { + setIsTabFocussed({}); + } + } + }; + }; + + useEffect(() => { + // Divide up our nav on initial mount: + setProcessedItems(MoreNavPreProcess(menuGroups, characterLimit)); + + // Set desktopFlag on + setIsNotDesktop(window.innerWidth < breakpointValues.Nav); + + return () => { + window.removeEventListener('onkeyup', setIsTabFocussed); + }; + }, [menuGroups, characterLimit]); + + // Custom function to let us update the nav dynamically: + const screenResizeNav = useCallback(() => { + const screenSize = typeof window !== 'undefined' ? window.innerWidth : null; + const isCurrentlyNotDesktop = window.innerWidth < breakpointValues.Nav; + + if (screenSize !== null && (isNotDesktop !== isCurrentlyNotDesktop)) { + setIsNotDesktop(isCurrentlyNotDesktop); + } + }, [isNotDesktop]); + + useEffect(() => { + // Hook into browser's own onresize event to call our custom wrapper function: + if (typeof window !== 'undefined') window.onresize = screenResizeNav; + }, [screenResizeNav]); + + // Once we've processed the items, assign according to breakpoint; sub desktop 'Nav' + // breakpoints use 'raw' unprocessed menu groups, Desktop uses the divided up versions: + if (processedItems) theseGroups = isNotDesktop ? menuGroups : processedItems.standardGroups; + + return ( + <> + + + Open + + + ); +}; + +HeaderNav.propTypes = { + navItems: PropTypes.objectOf(PropTypes.shape), + metaIcons: PropTypes.node.isRequired, + characterLimit: PropTypes.number, + // As this is rendered in both the Header AND the Nav, just passing + // the same prop through to here: + donateButton: PropTypes.node +}; + +HeaderNav.defaultProps = { + navItems: {}, + // To be overridable as a CMS prop + characterLimit: 60, + donateButton: null +}; + +export default HeaderNav; diff --git a/src/components/Organisms/Header/HeaderNav/HeaderNav.style.js b/src/components/Organisms/Header/HeaderNav/HeaderNav.style.js new file mode 100644 index 000000000..64e76475d --- /dev/null +++ b/src/components/Organisms/Header/HeaderNav/HeaderNav.style.js @@ -0,0 +1,505 @@ +/* eslint-disable no-multiple-empty-lines */ +import styled, { css } from 'styled-components'; + +import Link from '../../../Atoms/Link/Link'; +import hideVisually from '../../../../theme/shared/hideVisually'; +import zIndex from '../../../../theme/shared/zIndex'; +import Arrow from './arrow-right.png'; + +const transitionDuration = 0.2; + +const NavLinkClass = styled(Link)` + display: inline-block; + border: 0; + padding: 25px; + line-height: 1rem; + height: auto; + font-weight: 700; + width: 100%; + color: ${({ theme }) => theme.color('black')}; + transition: color ${transitionDuration}s ease; + + :hover, + :focus, + :focus-within { + border: 0; + color: ${({ theme }) => theme.color('red')}; + font-weight: inherit; + } +`; + +/** + * Navigation menu + */ +const Nav = styled.nav` + display: ${({ isExpandable }) => (isExpandable ? 'block' : 'none')}; + width: 100%; + position: absolute; + top: 75px; + left: 0; + ${zIndex('higher')}; + background-color: ${({ theme }) => theme.color('white')}; + box-shadow: 0px 20px 20px 5px rgba(0, 0, 0, 0.25); + + @media ${({ theme }) => theme.allBreakpoints('M')} { + width: 50%; + right: 0; + left: inherit; + box-shadow: -20px 15px 20px 0px rgba(0, 0, 0, 0.25); + } + + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + ${zIndex('medium')}; + position: relative; + top: 0; + display: block; + margin: 0 10px; + width: auto; + height: 100%; + box-shadow: none; + } + > h2 { + ${hideVisually}; + } +`; + +/** + * Sub Navigation Menu (second level) + */ +const SubNavMenu = styled.ul` + visibility: ${({ isSubMenuOpen }) => (isSubMenuOpen ? 'visible' : 'hidden')}; + display: ${({ isSubMenuOpen }) => (isSubMenuOpen ? 'flex' : 'none')}; + padding: 0; + position: relative; + list-style: none outside; + left: 0; + top: 0; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: ${({ theme }) => theme.color('white')}; + overflow: hidden; + border: 1px solid ${({ theme }) => theme.color('grey_medium')}; + + // DESKTOP: + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + display: flex; + visibility: ${({ isFocussed }) => (isFocussed ? 'visible' : 'hidden')}; + width: 330px; + height: auto; + padding: 0; + position: absolute; + top: 88px; + left: -5px; + border-radius: 0 0 25px 25px; + transition: opacity ${transitionDuration}s ease; + opacity: 0; + box-shadow: 0px 20px 20px 5px rgba(0, 0, 0, 0.25); + } +`; + +/** + * Sub Menu list items + */ +const SubNavItem = styled.li` + padding: 0; + height: 100%; + width: 100%; + border-top: 1px solid ${({ theme }) => theme.color('grey_medium')};; + position: relative; + transition: background-color ${transitionDuration}s ease; + + &:first-of-type { + border-top: none; + } + + span { + font-weight: 100; + } + + :hover, + :focus, + :focus-within { + background-color: ${({ theme }) => theme.color('grey_extra_light')}; + + span { + border-bottom: 0; + padding-bottom: 2px; + color: ${({ theme }) => theme.color('red')}; + } + } +`; + +/** + * Sub menu link item + */ +const SubNavLink = styled(NavLinkClass)` + padding: 20px 25px 18px 40px; + color: ${({ theme }) => theme.color('black')}; + height: auto; + position: relative; +`; + +/** + * Navigation Menu (first level) + */ +const NavMenu = styled.ul` + background-color: ${({ theme }) => theme.color('white')}; + list-style: none outside; + padding: 0; + margin: 0; + + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-start; + background-color: ${({ theme }) => theme.color('white')}; + } +`; + +/** + * Menu item link + */ +const NavLink = styled(NavLinkClass)` + display: flex; + gap: 4px; + font-family: ${({ theme }) => theme.fontFamilies(theme.font.regular)}; + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + padding: 10px 0; + height: auto; + :hover, + :focus-within, + :focus { + + ${SubNavMenu} { + display: flex; + opacity: 1; + }} + } +`; + +/** + * Menu list items + */ +const NavItem = styled.li` + ${zIndex('medium')}; + position: relative; + font-weight: 700; + border-bottom: 1px solid ${({ theme }) => theme.color('grey_medium')}; + + li { + span { + border-bottom: none; + padding-bottom: 0; + } + + :hover, + :focus, + :focus-within { + span { + border-bottom: none; + padding-bottom: 0; + } + } + } + + // Chevron icon: + span > a > div { + transition: transform 0.35s cubic-bezier(0.41, 1.64, 0.41, 0.8); + } + + :hover, + :focus, + :focus-within { + li { + span { + border-bottom: none; + padding-bottom: 0; + } + } + + // Chevron icon: + span > a { + color: ${({ theme }) => theme.color('red')}; + > div { + transform: rotate(-180deg); + img { + // Use fancy filter to colour 'img' version of SVG + filter: invert(0.5) sepia(1) saturate(100) hue-rotate(20deg); + } + } + } + } + + + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + margin: 0 4px; + padding: 25px 5px; + border-bottom: none; + + + :hover, + :focus, + :focus-within { + > ${SubNavMenu}, :focus-within > ${SubNavMenu} { + visibility: visible; + opacity: 1; + display: flex; + } + } + + :hover, + :focus, + :focus-within { + background-color: transparent; + ${zIndex('high')}; + + span { + border-bottom: 2px solid ${({ theme }) => theme.color('black')}; + padding-bottom: 2px; + } + + ${SubNavMenu} { + display: flex; + opacity: 1; + visibility: visible; + flex-direction: column; + } + } + } +`; + +const ChevronWrapper = styled.div` + width: 16px; + position: absolute; + top: 20px; + right: 22px; + + img { + width: 100%; + } + + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + position: relative; + top: -3px; + right: -1px; + width: 10px; + padding-top: 2px; + } +`; + +// This represents the 'non-desktop'/mobile nav icons: +const NavMetaIcons = styled.div` + width: auto; + display: flex; + align-items: center; + flex-direction: column; + background-color: inherit; + + > div { + height: 60px; + width: 100%; + display: flex; + border-bottom: 1px solid ${({ theme }) => theme.color('grey_medium')}; + + > a { + height: inherit; + width: 100%; + padding: 15px 20px; + position: relative; + + &: after { + position: absolute; + right: 20px; + top: 50%; + transform: translateY(-50%); + content: ""; + width: 20px; + height: 20px; + background-image: url(${Arrow}); + background-size: 100%; + background-repeat: no-repeat; + } + + img { + padding: 5px; + height: 35px; + width: 35px; + } + + span { + transition: color 0.15s ease-out; + } + + &:focus, + &:hover { + span { + color: ${({ theme }) => theme.color('red')}; + } + } + } + + &:first-child { + margin-top: 20px; + } + } + + // Hide these when using non-mobile nav, + // just leaving the Header version in place + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + display: none; + } +`; + +const DonateButtonWrapperBottom = styled.div` + display: flex; + justify-content: center; + padding: 35px 20px; + background-color: inherit; + + // Donate button + a { + width: calc(100% - 10px); + transition: width 0.35s cubic-bezier(0.5, 1.5, 0.5, 0.9); + + &:hover, + &:focus { + width: 100%; + box-shadow: rgba(0, 0, 0, 0.1) 0 0 20px 0; + } + } + + // Hide the 'Nav'-embedded version of the button when the nav + // goes FULL DESKTOP, leaving just the 'Header'-embedded example + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + display: none; + } +`; + +/* + * ********** + * MORE NAV + * ********** + */ + +const MoreSubNavMenu = styled(SubNavMenu)` + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + // top: 88px + } +`; + +const MoreNavLink = styled(NavLink)` + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + :focus, + :hover, + :focus-within { + + ${MoreSubNavMenu} { + display: flex; + } + } + } +`; + +// Use for the 'More' link only +const MoreNavItem = styled(NavItem)` + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + :hover, + :focus-within, + :focus { + > ${MoreSubNavMenu} { + visibility: visible; + opacity: 1; + display: flex; + } + } + + :hover, + :focus, + :focus-within { + ${MoreSubNavMenu} { + display: flex; + flex-direction: column; + } + } + } +`; + +// Clone Of SubNavMenu, NESTED menu +const MoreNestedSubNavMenu = styled(SubNavMenu)` + @media ${({ theme }) => theme.allBreakpoints('Nav')} { + top: 0; + left: -1px; + border-radius: 0; + border-bottom: 0; + position: relative; + transition: max-height 0.5s cubic-bezier(0.5, 1.5, 0.5, 0.80); + max-height: 0; + border: 0; + box-shadow: none; + + ${({ isSubMenuOpen }) => (isSubMenuOpen && css` + // Calculating a realistic height ceiling (8 subnav items) + // to make animation as slick as possible + max-height: calc(57px * 8); + `)}; + } +`; + +const MoreSubNavItem = styled(SubNavItem)` + // Chevron icon + > a > div { + position: absolute; + width: 15px; + top: 13px; + right: 25px; + transition: transform 0.35s cubic-bezier(0.41, 1.64, 0.41, 0.8); + } + + :hover, + :focus, + :focus-within { + > a { + color: ${({ theme }) => theme.color('red')}; + } + > a > div { + img { + filter: invert(0.5) sepia(1) saturate(100) hue-rotate(20deg); + } + } + } +`; + +const MoreNavNestedLink = styled(NavLink)` + padding: 20px 25px 18px; + + ${({ isSubMenuOpen }) => (isSubMenuOpen && css` + > div { + transform: rotate(-180deg); + } + `)}; +`; + +const MoreSubNavLink = styled(SubNavLink)` + // +`; + +export { + Nav, + NavMenu, + NavItem, + NavLink, + SubNavMenu, + SubNavItem, + SubNavLink, + ChevronWrapper, + NavMetaIcons, + DonateButtonWrapperBottom, + // 'More Nav' stuff: + MoreNavLink, + MoreSubNavMenu, + MoreNavItem, + MoreNestedSubNavMenu, + MoreSubNavItem, + MoreNavNestedLink, + MoreSubNavLink +}; diff --git a/src/components/Organisms/Header/HeaderNav/Menu-Group-Icon.svg b/src/components/Organisms/Header/HeaderNav/Menu-Group-Icon.svg new file mode 100644 index 000000000..7f187af79 --- /dev/null +++ b/src/components/Organisms/Header/HeaderNav/Menu-Group-Icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Organisms/Header/HeaderNav/arrow-right.png b/src/components/Organisms/Header/HeaderNav/arrow-right.png new file mode 100644 index 000000000..ee948bb25 Binary files /dev/null and b/src/components/Organisms/Header/HeaderNav/arrow-right.png differ diff --git a/src/components/Organisms/Header/HeaderNav/arrow.svg b/src/components/Organisms/Header/HeaderNav/arrow.svg new file mode 100644 index 000000000..027b666f4 --- /dev/null +++ b/src/components/Organisms/Header/HeaderNav/arrow.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/components/Organisms/Header/Nav/chevron-down.svg b/src/components/Organisms/Header/HeaderNav/chevron-down.svg similarity index 100% rename from src/components/Organisms/Header/Nav/chevron-down.svg rename to src/components/Organisms/Header/HeaderNav/chevron-down.svg diff --git a/src/components/Organisms/Header/Nav/Nav.js b/src/components/Organisms/Header/Nav/Nav.js deleted file mode 100644 index f724d6d4c..000000000 --- a/src/components/Organisms/Header/Nav/Nav.js +++ /dev/null @@ -1,187 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; - -import Text from '../../../Atoms/Text/Text'; -import BurgerMenu from '../Burger/BurgerMenu'; -import { breakpointValues } from '../../../../theme/shared/allBreakpoints'; -import NavHelper from '../../../../utils/navHelper'; -import { InternalLinkHelper } from '../../../../utils/internalLinkHelper'; -import allowListed from '../../../../utils/allowListed'; -import chevronDown from './chevron-down.svg'; - -import { - Nav, - NavMenu, - NavItem, - NavLink, - SubNavMenu, - SubNavItem, - SubNavLink, - SubNavLinkUnderline, - ChevronWrapper -} from './Nav.style'; - -const MainNav = ({ navItems }) => { - const { menuGroups } = navItems; - const [isExpandable, setIsExpandable] = useState(false); - const [isSubMenuOpen, setIsSubMenuOpen] = useState({}); - const [isKeyPressed, setIsKeyPressed] = useState({}); - - const [isMobile, setIsMobile] = useState(false); - - const toggleBurgerMenu = event => { - event.preventDefault(); - setIsExpandable(!isExpandable); - }; - - const toggleSubMenu = (e, item) => { - e.preventDefault(); - setIsSubMenuOpen({ [item]: !isSubMenuOpen[item] }); - }; - - // Handle tab key on menu nav - const keyPressed = item => () => { - window.onkeyup = e => { - if ( - e.target.querySelector('span') - && e.target.querySelector('span').innerText === item - ) { - setIsKeyPressed({ [item]: !isKeyPressed[item] }); - } else if (!e.target.querySelector('span')) { - setIsKeyPressed({}); - } - }; - }; - - useEffect(() => { - const width = window.innerWidth; - setIsMobile(width < breakpointValues.Nav); - window.addEventListener('onkeyup', setIsKeyPressed); - - return () => { - window.removeEventListener('onkeyup', setIsKeyPressed); - }; - }, []); - return ( - <> - - - Open - - - ); -}; - -MainNav.propTypes = { - navItems: PropTypes.objectOf(PropTypes.shape) -}; - -MainNav.defaultProps = { - navItems: {} -}; - -export default MainNav; diff --git a/src/components/Organisms/Header/Nav/Nav.style.js b/src/components/Organisms/Header/Nav/Nav.style.js deleted file mode 100644 index 94a99aed0..000000000 --- a/src/components/Organisms/Header/Nav/Nav.style.js +++ /dev/null @@ -1,245 +0,0 @@ -import styled from 'styled-components'; - -import Link from '../../../Atoms/Link/Link'; -import hideVisually from '../../../../theme/shared/hideVisually'; -import zIndex from '../../../../theme/shared/zIndex'; - -const NavLinkClass = styled(Link)` - display: inline-block; - border: 0; - padding: 17px 20px; - line-height: 1.3rem; - height: 46px; - font-weight: 700; - width: 100%; - color: ${({ theme }) => theme.color('deep_violet_dark')}; - :hover { - border: 0; - color: ${({ theme }) => theme.color('deep_violet_dark')}; - font-weight: inherit; - } -`; - -/** - * Navigation menu - */ -const Nav = styled.nav` - display: ${({ isExpandable }) => (isExpandable ? 'block' : 'none')}; - width: 100%; - position: absolute; - top: 75px; - left: 0; - ${zIndex('higher')}; - - @media ${({ theme }) => theme.allBreakpoints('M')} { - width: 50%; - right: 0; - left: inherit; - } - - @media ${({ theme }) => theme.allBreakpoints('Nav')} { - ${zIndex('medium')}; - position: relative; - top: 0; - display: block; - margin: 0 10px; - width: auto; - height: 100%; - } - > h2 { - ${hideVisually}; - } -`; - -/** - * Sub Navigation Menu (second level) - */ -const SubNavMenu = styled.ul` - display: ${({ isSubMenuOpen }) => (isSubMenuOpen ? 'flex' : 'none')}; - padding: 0; - position: relative; - list-style: none outside; - left: 0; - top: 0; - flex-direction: column; - justify-content: center; - align-items: center; - background-color: ${({ theme }) => theme.color('deep_violet_dark')}; - - @media ${({ theme }) => theme.allBreakpoints('Nav')} { - display: none; - display: ${({ isKeyPressed }) => (isKeyPressed ? 'flex' : 'none')}; - top: 90px; - position: absolute; - padding: 0 0 20px; - width: 250px; - height: auto; - } -`; - -/** - * Sub Menu list items - */ -const SubNavItem = styled.li` - padding: 0; - height: 100%; - width: 100%; - :hover { - background-color: ${({ theme }) => theme.color('deep_violet_light')}; - span { - border-bottom: 0; - padding-bottom: 2px; - color: ${({ theme }) => theme.color('white')}; - } - } -`; - -/** - * Sub menu link item - */ -const SubNavLink = styled(NavLinkClass)` - padding: 14px 14px 7px 21px; - color: ${({ theme }) => theme.color('white')}; - height: auto; - position: relative; -`; - -/** - * Sub menu link item underline - */ -const SubNavLinkUnderline = styled(SubNavLink)` - padding: 26px 21px; - ::after { - content: ''; - position: absolute; - width: 14px; - border-bottom: 2px solid ${({ theme }) => theme.color('white')}; - left: 12px; - top: auto; - bottom: 10px; - margin: 0 10px; - } - @media ${({ theme }) => theme.allBreakpoints('Nav')} { - ::before { - display: block; - position: absolute; - content: ''; - left: 34px; - width: 10px; - height: 10px; - border: 11px solid transparent; - border-bottom-color: ${({ theme }) => theme.color('deep_violet_dark')}; - top: -22px; - } - :hover::before { - border-bottom-color: ${({ theme }) => theme.color('deep_violet_light')}; - } - } -`; - -/** - * Navigation Menu (first level) - */ -const NavMenu = styled.ul` - background-color: ${({ theme }) => theme.color('grey_extra_light')}; - list-style: none outside; - padding: 0; - margin: 0; - - @media ${({ theme }) => theme.allBreakpoints('Nav')} { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: flex-start; - background-color: ${({ theme }) => theme.color('white')}; - } -`; - -/** - * Menu item link - */ -const NavLink = styled(NavLinkClass)` - display: flex; - gap: 4px; - font-family: ${({ theme }) => theme.fontFamilies(theme.font.regular)}; - @media ${({ theme }) => theme.allBreakpoints('Nav')} { - padding: 10px 0; - height: auto; - :focus + ${SubNavMenu} { - display: flex; - } - } -`; - -/** - * Menu list items - */ -const NavItem = styled.li` - ${zIndex('medium')}; - position: relative; - font-weight: 700; - :hover { - li { - span { - border-bottom: none; - padding-bottom: 0; - } - } - } - li { - span { - border-bottom: none; - padding-bottom: 0; - } - :hover { - span { - border-bottom: none; - padding-bottom: 0; - } - } - } - :hover { - background-color: ${({ theme }) => theme.color('teal_light')}; - } - @media ${({ theme }) => theme.allBreakpoints('Nav')} { - margin: 0 4px; - padding: 25px 5px; - - :hover > ${SubNavMenu}, :focus-within > ${SubNavMenu} { - visibility: visible; - opacity: 1; - display: flex; - } - - :hover { - background-color: transparent; - ${zIndex('high')}; - span { - border-bottom: 2px solid ${({ theme }) => theme.color('black')}; - padding-bottom: 2px; - } - ${SubNavMenu} { - display: flex; - flex-direction: column; - } - } - } -`; - -const ChevronWrapper = styled.div` - width: 12px; - padding-top: 2px; -`; - -export { - Nav, - NavMenu, - NavItem, - NavLink, - SubNavMenu, - SubNavItem, - SubNavLink, - SubNavLinkUnderline, - ChevronWrapper -}; diff --git a/src/components/Organisms/Header/annoying.css b/src/components/Organisms/Header/annoying.css new file mode 100644 index 000000000..95b03d576 --- /dev/null +++ b/src/components/Organisms/Header/annoying.css @@ -0,0 +1,14 @@ +/* Overiding the crummy Styleguidest styles */ +.rsg--preview-35 { + padding: 0 !important; + border: none !important; +} + +.rsg--content-3 { + padding: 0 !important; +} + +.rsg--header-11, +.rsg--tabs-12 { + display: none !important;; +} diff --git a/src/components/Organisms/Header/assets/Post.svg b/src/components/Organisms/Header/assets/Post.svg new file mode 100644 index 000000000..048a052c1 --- /dev/null +++ b/src/components/Organisms/Header/assets/Post.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Organisms/Header/data/data-extended.js b/src/components/Organisms/Header/data/data-extended.js new file mode 100644 index 000000000..71b081942 --- /dev/null +++ b/src/components/Organisms/Header/data/data-extended.js @@ -0,0 +1,280 @@ +export default { + title: 'Header', + menuGroups: [ + { + title: 'GROUP1', + id: 'group1', + links: [ + { + title: 'Sport Relief', + path: 'https://www.comicrelief.com/fundraising/pay-in-your-money', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Run 30 Miles in June', + path: 'https://www.comicrelief.com/rednoseday', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Be a Good Sport: Schools', + path: 'https://www.comicrelief.com/join', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Win a trip to New York with Major League Baseball', + path: 'https://www.comicrelief.com/squads', + internal: { + type: 'ContentfulPageLandingPage' + } + } + ] + }, + { + title: 'GROUP2', + id: 'group2', + links: [ + { + title: 'Red Nose Day', + path: 'https://www.comicrelief.com/rednoseday/schools', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'The New Red Nose', + path: 'https://www.comicrelief.com/rednoseday/schools', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Schools', + path: 'https://www.comicrelief.com/rednoseday/schools', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'The Red Nose Day Nosey Awards', + path: 'https://www.comicrelief.com/rednoseday/schools', + internal: { + type: 'ContentfulPageLandingPage' + } + } + ] + }, + { + title: 'GROUP3', + id: 'group3', + links: [ + { + title: 'Funding', + path: 'https://www.comicrelief.com/what-your-money-does', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Our Funding Practice', + path: 'https://www.comicrelief.com/our-legacy', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Funding opportunities', + path: 'https://www.comicrelief.com/our-legacy', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Our Funding strategy', + path: 'https://www.comicrelief.com/our-legacy', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Managing your funding', + path: 'https://www.comicrelief.com/our-legacy', + internal: { + type: 'ContentfulPageLandingPage' + } + } + ] + }, + { + title: 'GROUP4', + id: 'group4', + links: [ + { + title: 'What Your Money Does', + path: + 'https://www.comicrelief.com/rednoseday/schools/primary-schools', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Reports & Publications', + path: + 'https://www.comicrelief.com/rednoseday/schools/secondary-schools', + internal: { + type: 'ContentfulPageLandingPage' + } + } + ] + }, + { + title: 'GROUP5', + id: 'group5', + links: [ + { + title: 'Get Involved', + url: 'https://www.comicrelief.com/working-with-us/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Do your own fundraising', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Regular Donations', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Run for Comic Relief', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'How to pay in your fundraising money', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Partners', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + } + ] + }, + { + title: 'GROUP6', + id: 'group6', + links: [ + { + title: 'Something Here', + url: 'https://www.comicrelief.com/working-with-us/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Do your own fundraising', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Regular Donations', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Run for Comic Relief', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'How to pay in your fundraising money', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Partners', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + } + ] + }, + { + title: 'GROUP7', + id: 'group7', + links: [ + { + title: 'Something Else', + url: 'https://www.comicrelief.com/working-with-us/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Do your own fundraising', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Regular Donations', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Run for Comic Relief', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'How to pay in your fundraising money', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Partners', + url: 'https://www.comicrelief.com/404/', + internal: { + type: 'ContentfulComponentLink' + } + } + ] + } + ] +}; diff --git a/src/components/Organisms/Header/data/data.js b/src/components/Organisms/Header/data/data.js index 98d161a1d..5f3a2e91e 100644 --- a/src/components/Organisms/Header/data/data.js +++ b/src/components/Organisms/Header/data/data.js @@ -2,131 +2,108 @@ export default { title: 'Header', menuGroups: [ { - title: 'Fundraising - menu group', - id: 'f7dc5eef-f4eb-5405-8a35-08808b55cb33', + title: 'GROUP1', + id: 'group1', links: [ { - title: 'Fundraising', + title: 'Sport Relief', path: 'https://www.comicrelief.com/fundraising/pay-in-your-money', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Red Nose Day', + title: 'Run 30 Miles in June', path: 'https://www.comicrelief.com/rednoseday', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Regular donations', + title: 'Be a Good Sport: Schools', path: 'https://www.comicrelief.com/join', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Squads', + title: 'Win a trip to New York with Major League Baseball', path: 'https://www.comicrelief.com/squads', internal: { type: 'ContentfulPageLandingPage' } - }, - { - title: 'The Noseys', - path: 'https://www.comicrelief.com/rednoseday/fundraising/the-noseys', - internal: { - type: 'ContentfulPageLandingPage' - } - }, - { - title: 'Free downloads', - path: - 'https://www.comicrelief.com/rednoseday/fundraising/free-downloads', - internal: { - type: 'ContentfulPageLandingPage' - } } ] }, { - title: 'Schools & youth - menu group', - id: 'eaec51921-bbb3-5e8d-b966-c53fff34998b5', + title: 'GROUP2', + id: 'group2', links: [ { - title: 'Single menu link', + title: 'Red Nose Day', path: 'https://www.comicrelief.com/rednoseday/schools', internal: { type: 'ContentfulPageLandingPage' } - } - ] - }, - { - title: 'What your money does - menu group', - id: '9f3980f3-d02b-52e9-ac41-933a778c040a', - links: [ + }, { - title: 'What your money does', - path: 'https://www.comicrelief.com/what-your-money-does', + title: 'The New Red Nose', + path: 'https://www.comicrelief.com/rednoseday/schools', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Our legacy', - path: 'https://www.comicrelief.com/What-we-do/our-legacy', + title: 'Schools', + path: 'https://www.comicrelief.com/rednoseday/schools', internal: { type: 'ContentfulPageLandingPage' } - } - ] - }, - { - title: 'Schools & youth - menu group', - id: 'eaec5191-bbb3-5e8d-b966-c53fff34998b', - links: [ + }, { - title: 'Schools & youth', + title: 'The Red Nose Day Nosey Awards', path: 'https://www.comicrelief.com/rednoseday/schools', internal: { type: 'ContentfulPageLandingPage' } - }, + } + ] + }, + { + title: 'GROUP3', + id: 'group3', + links: [ { - title: 'Primary schools', - path: - 'https://www.comicrelief.com/rednoseday/schools/primary-schools', + title: 'Funding', + path: 'https://www.comicrelief.com/what-your-money-does', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Secondary schools', - path: - 'https://www.comicrelief.com/rednoseday/schools/secondary-schools', + title: 'Our Funding Practice', + path: 'https://www.comicrelief.com/our-legacy', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Nurseries', - path: 'https://www.comicrelief.com/rednoseday/schools/nurseries', + title: 'Funding opportunities', + path: 'https://www.comicrelief.com/our-legacy', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Youth groups', - path: 'https://www.comicrelief.com/rednoseday/youth', + title: 'Our Funding strategy', + path: 'https://www.comicrelief.com/our-legacy', internal: { type: 'ContentfulPageLandingPage' } }, { - title: 'Free downloads', - path: 'https://www.comicrelief.com/rednoseday/schools/free-downloads', + title: 'Managing your funding', + path: 'https://www.comicrelief.com/our-legacy', internal: { type: 'ContentfulPageLandingPage' } @@ -134,12 +111,21 @@ export default { ] }, { - title: 'Shop', - id: 'eaec51921-bb89b3-5e8d-b9566-c53fff34998b5', + title: 'GROUP4', + id: 'group4', links: [ { - title: 'Shop', - path: 'https://shop.comicrelief.com', + title: 'What Your Money Does', + path: + 'https://www.comicrelief.com/rednoseday/schools/primary-schools', + internal: { + type: 'ContentfulPageLandingPage' + } + }, + { + title: 'Reports & Publications', + path: + 'https://www.comicrelief.com/rednoseday/schools/secondary-schools', internal: { type: 'ContentfulPageLandingPage' } @@ -147,47 +133,47 @@ export default { ] }, { - title: 'External Links (menu group)', - id: 'eaec5191-bbb3-5e8d-b966-c53fff34998a', + title: 'GROUP5', + id: 'group5', links: [ { - title: 'Test allowListed external link', - url: 'https://www.sportrelief.com', + title: 'Get Involved', + url: 'https://www.comicrelief.com/working-with-us/', + internal: { + type: 'ContentfulComponentLink' + } + }, + { + title: 'Do your own fundraising', + url: 'https://www.comicrelief.com/404/', internal: { type: 'ContentfulComponentLink' } }, { - title: 'Test non-allowListed external link', - url: 'https://bing.com', + title: 'Regular Donations', + url: 'https://www.comicrelief.com/404/', internal: { type: 'ContentfulComponentLink' } }, { - title: 'Link comp: URL and Ref', - url: 'https://www.google.com', - reference: { - path: 'test-ref-path-1' - }, + title: 'Run for Comic Relief', + url: 'https://www.comicrelief.com/404/', internal: { type: 'ContentfulComponentLink' } }, { - title: 'Link comp: only Ref', - url: null, - reference: { - path: 'test-ref-path-2' - }, + title: 'How to pay in your fundraising money', + url: 'https://www.comicrelief.com/404/', internal: { type: 'ContentfulComponentLink' } }, { - title: 'Link comp: only URL', - url: 'test-url', - reference: null, + title: 'Partners', + url: 'https://www.comicrelief.com/404/', internal: { type: 'ContentfulComponentLink' } diff --git a/src/styleguide/data/data.js b/src/styleguide/data/data.js index 5660b6be4..532ff57ff 100644 --- a/src/styleguide/data/data.js +++ b/src/styleguide/data/data.js @@ -62,63 +62,63 @@ const carouselItemsComplete = { node1Amount: '1,000', node1Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node2Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node2Amount: '750,000', node2Image: { file: { - url: 'https://images.ctfassets.net/zsfivwzfgl3t/5uKnps3prnG6GpTM1EPZdC/8d7264465846de31e3bbb5b6b2c36c8f/014-helping_hand.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node3Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node3Amount: '3,000', node3Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node4Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node4Amount: '4,000', node4Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node5Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node5Amount: '5,000', node5Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node6Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node6Amount: '6,000', node6Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node7Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node7Amount: '7,000', node7Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node8Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node8Amount: '8,000', node8Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node9Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node9Amount: '9,000', node9Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } } }; @@ -136,34 +136,34 @@ const carouselItemsIncomplete = { node1Amount: '1,000', node1Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node2Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node2Amount: '750,000', node2Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node3Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node3Amount: '3,000', node3Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node4Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node4Amount: '4,000', node4Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node5Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node5Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node6Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', @@ -176,7 +176,7 @@ const carouselItemsIncomplete = { node8Amount: null, node8Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node9_Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', @@ -197,28 +197,28 @@ const carouselItemsMinimal = { node1Amount: '1,000', node1Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node2Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node2Amount: '750,000', node2Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node3Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node3Amount: '3,000', node3Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } }, node4Copy: 'children and young people in the UK and around the world, including with safe homes, good nutrition and access to quality healthcare and education.', node4Amount: '4,000', node4Image: { file: { - url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png' + url: '//images.ctfassets.net/zsfivwzfgl3t/6ZsS5CpukQwXRcMSUlbOM1/be31c7ff09891d14232e7c3dbe9fa8a2/028-love_1.png' } } }; diff --git a/src/theme/shared/allBreakpoints.js b/src/theme/shared/allBreakpoints.js index cdafa505d..326d8e9c0 100644 --- a/src/theme/shared/allBreakpoints.js +++ b/src/theme/shared/allBreakpoints.js @@ -6,7 +6,8 @@ export const breakpointValues = { S: 0, M: 740, L: 1024, - Nav: 1150, + Nav: 1175, + NavWithAnimations: 1280, XL: 1440 }; diff --git a/src/utils/navHelper.js b/src/utils/navHelper.js index 33a33cd18..8cdb85dd5 100644 --- a/src/utils/navHelper.js +++ b/src/utils/navHelper.js @@ -12,4 +12,27 @@ const NavHelper = navItem => { return thisUrl; }; -export default NavHelper; +const MoreNavPreProcess = (menuGroups, characterLimit) => { + let characterCount = 0; + const overLimit = false; + const standardGroups = []; + const moreNavGroups = []; + + menuGroups.map(group => { + // As this first item is used as our top level parent 'button' link, + // look to this to grab the amount of copied rendered: + const thisFirstChild = group.links[0]; + + // Keep track of how many characters our nav has in total: + characterCount += thisFirstChild.title.length; + + // Assign groups to the relevant array if we're over the limit + return characterCount > characterLimit !== overLimit + ? moreNavGroups.push(group) + : standardGroups.push(group); + }); + + return { standardGroups, moreNavGroups }; +}; + +export { NavHelper, MoreNavPreProcess };