@times-components/ts-components 1.100.1 → 1.100.2-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/components/article-flag/ArticleFlag.d.ts +1 -4
  2. package/dist/components/article-flag/ArticleFlag.js +1 -1
  3. package/dist/components/article-flag/__tests__/ArticleFlag.test.js +2 -2
  4. package/dist/components/article-flag/getActiveFlags.d.ts +1 -1
  5. package/dist/components/article-flag/styles.d.ts +1 -1
  6. package/dist/components/article-flag/types.d.ts +4 -0
  7. package/dist/components/article-flag/types.js +2 -0
  8. package/dist/components/banner/__tests__/banner.test.d.ts +1 -0
  9. package/dist/components/banner/__tests__/banner.test.js +11 -0
  10. package/dist/components/banner/assets/CloseIconBlack.d.ts +3 -0
  11. package/dist/components/banner/assets/CloseIconBlack.js +5 -0
  12. package/dist/components/banner/assets/EmailIcon.d.ts +3 -0
  13. package/dist/components/banner/assets/EmailIcon.js +5 -0
  14. package/dist/components/banner/banner.d.ts +8 -0
  15. package/dist/components/banner/banner.js +17 -0
  16. package/dist/components/banner/styles.d.ts +8 -0
  17. package/dist/components/banner/styles.js +73 -0
  18. package/dist/components/breadcrumb/__tests__/index.test.d.ts +1 -0
  19. package/dist/components/breadcrumb/__tests__/index.test.js +40 -0
  20. package/dist/components/breadcrumb/assets/BreadcrumbIcon.d.ts +2 -0
  21. package/dist/components/breadcrumb/assets/BreadcrumbIcon.js +5 -0
  22. package/dist/components/breadcrumb/breadcrumb.d.ts +9 -0
  23. package/dist/components/breadcrumb/breadcrumb.js +28 -0
  24. package/dist/components/breadcrumb/fixtures/breadcrumbs.json +27 -0
  25. package/dist/components/breadcrumb/styles.d.ts +13 -0
  26. package/dist/components/breadcrumb/styles.js +39 -0
  27. package/dist/components/delayed-component/__tests__/delayed-component.test.d.ts +1 -0
  28. package/dist/components/delayed-component/__tests__/delayed-component.test.js +23 -0
  29. package/dist/components/delayed-component/delayed-component.d.ts +6 -0
  30. package/dist/components/delayed-component/delayed-component.js +11 -0
  31. package/dist/components/in-article-info-card/Card.d.ts +1 -1
  32. package/dist/components/in-article-info-card/InfoCard.d.ts +0 -8
  33. package/dist/components/in-article-info-card/InfoCard.js +1 -1
  34. package/dist/components/in-article-info-card/types.d.ts +8 -0
  35. package/dist/components/in-article-info-card/types.js +2 -0
  36. package/dist/components/job-title/__tests__/index.test.d.ts +1 -0
  37. package/dist/components/job-title/__tests__/index.test.js +45 -0
  38. package/dist/components/job-title/assets/TooltipIcon.d.ts +2 -0
  39. package/dist/components/job-title/assets/TooltipIcon.js +11 -0
  40. package/dist/components/job-title/assets/close-icon.d.ts +2 -0
  41. package/dist/components/job-title/assets/close-icon.js +5 -0
  42. package/dist/components/job-title/job-title.d.ts +11 -0
  43. package/dist/components/job-title/job-title.js +31 -0
  44. package/dist/components/job-title/styles.d.ts +11 -0
  45. package/dist/components/job-title/styles.js +150 -0
  46. package/dist/components/save-star/ContentProvider.d.ts +0 -6
  47. package/dist/components/save-star/ContentProvider.js +1 -1
  48. package/dist/components/save-star/SaveStar.js +1 -1
  49. package/dist/components/save-star/SaveStarUI.d.ts +1 -4
  50. package/dist/components/save-star/SaveStarUI.js +1 -1
  51. package/dist/components/save-star/types.d.ts +8 -0
  52. package/dist/components/save-star/types.js +2 -0
  53. package/dist/components/update-button/__tests__/update-button-with-delay.test.d.ts +1 -0
  54. package/dist/components/update-button/__tests__/update-button-with-delay.test.js +24 -0
  55. package/dist/components/update-button/__tests__/update-button.test.d.ts +1 -0
  56. package/dist/components/update-button/__tests__/update-button.test.js +27 -0
  57. package/dist/components/update-button/assets/FilledArrowIcon.d.ts +3 -0
  58. package/dist/components/update-button/assets/FilledArrowIcon.js +5 -0
  59. package/dist/components/update-button/styles.d.ts +1 -0
  60. package/dist/components/update-button/styles.js +39 -0
  61. package/dist/components/update-button/update-button-with-delay.d.ts +11 -0
  62. package/dist/components/update-button/update-button-with-delay.js +27 -0
  63. package/dist/components/update-button/update-button.d.ts +6 -0
  64. package/dist/components/update-button/update-button.js +9 -0
  65. package/dist/fixtures/article-harness/__tests__/articleHarness.test.d.ts +1 -0
  66. package/dist/fixtures/article-harness/__tests__/articleHarness.test.js +11 -0
  67. package/dist/index.d.ts +7 -2
  68. package/dist/index.js +8 -3
  69. package/package.json +17 -16
  70. package/rnw.js +1 -1
  71. package/src/components/article-flag/ArticleFlag.tsx +1 -5
  72. package/src/components/article-flag/__tests__/ArticleFlag.test.tsx +1 -1
  73. package/src/components/article-flag/getActiveFlags.ts +1 -1
  74. package/src/components/article-flag/styles.ts +1 -1
  75. package/src/components/article-flag/types.ts +4 -0
  76. package/src/components/banner/__tests__/__snapshots__/banner.test.tsx.snap +66 -0
  77. package/src/components/banner/__tests__/banner.test.tsx +13 -0
  78. package/src/components/banner/assets/CloseIconBlack.tsx +24 -0
  79. package/src/components/banner/assets/EmailIcon.tsx +24 -0
  80. package/src/components/banner/banner.stories.mdx +30 -0
  81. package/src/components/banner/banner.tsx +40 -0
  82. package/src/components/banner/styles.ts +80 -0
  83. package/src/components/breadcrumb/__tests__/__snapshots__/index.test.tsx.snap +64 -0
  84. package/src/components/breadcrumb/__tests__/index.test.tsx +51 -0
  85. package/src/components/breadcrumb/assets/BreadcrumbIcon.tsx +16 -0
  86. package/src/components/breadcrumb/breadcrumb.stories.mdx +47 -0
  87. package/src/components/breadcrumb/breadcrumb.tsx +84 -0
  88. package/src/components/breadcrumb/fixtures/breadcrumbs.json +27 -0
  89. package/src/components/breadcrumb/styles.ts +43 -0
  90. package/src/components/delayed-component/__tests__/delayed-component.test.tsx +30 -0
  91. package/src/components/delayed-component/delayed-component.stories.mdx +38 -0
  92. package/src/components/delayed-component/delayed-component.tsx +16 -0
  93. package/src/components/in-article-info-card/Card.tsx +1 -1
  94. package/src/components/in-article-info-card/InfoCard.tsx +1 -8
  95. package/src/components/in-article-info-card/types.ts +8 -0
  96. package/src/components/job-title/__tests__/__snapshots__/index.test.tsx.snap +271 -0
  97. package/src/components/job-title/__tests__/index.test.tsx +71 -0
  98. package/src/components/job-title/assets/TooltipIcon.tsx +37 -0
  99. package/src/components/job-title/assets/close-icon.tsx +18 -0
  100. package/src/components/job-title/job-title.stories.mdx +38 -0
  101. package/src/components/job-title/job-title.tsx +85 -0
  102. package/src/components/job-title/styles.ts +154 -0
  103. package/src/components/save-star/ContentProvider.tsx +1 -7
  104. package/src/components/save-star/SaveStar.tsx +2 -1
  105. package/src/components/save-star/SaveStarUI.tsx +1 -5
  106. package/src/components/save-star/types.ts +9 -0
  107. package/src/components/update-button/__tests__/__snapshots__/update-button-with-delay.test.tsx.snap +23 -0
  108. package/src/components/update-button/__tests__/__snapshots__/update-button.test.tsx.snap +23 -0
  109. package/src/components/update-button/__tests__/update-button-with-delay.test.tsx +67 -0
  110. package/src/components/update-button/__tests__/update-button.test.tsx +31 -0
  111. package/src/components/update-button/assets/FilledArrowIcon.tsx +17 -0
  112. package/src/components/update-button/styles.ts +40 -0
  113. package/src/components/update-button/update-button-with-delay.stories.mdx +40 -0
  114. package/src/components/update-button/update-button-with-delay.tsx +53 -0
  115. package/src/components/update-button/update-button.stories.mdx +32 -0
  116. package/src/components/update-button/update-button.tsx +17 -0
  117. package/src/fixtures/article-harness/__tests__/__snapshots__/articleHarness.test.tsx.snap +34 -0
  118. package/src/fixtures/article-harness/__tests__/articleHarness.test.tsx +11 -0
  119. package/src/index.ts +15 -7
  120. package/tsconfig.json +11 -2
@@ -10,6 +10,7 @@ import {
10
10
  FlagsContainer
11
11
  } from './styles';
12
12
  import getActiveFlags from './getActiveFlags';
13
+ import { FlagType } from './types';
13
14
 
14
15
  const ArticleFlag: React.FC<{ color?: string; title: string }> = ({
15
16
  color = colours.functional.primary,
@@ -66,11 +67,6 @@ const flagsMapping = (override = '') => {
66
67
  ]);
67
68
  };
68
69
 
69
- export type FlagType = Array<{
70
- expiryTime: string | null;
71
- type: string;
72
- }>;
73
-
74
70
  const FlagsView: React.FC<{ allFlags: FlagType; overrideColor?: string }> = ({
75
71
  allFlags,
76
72
  overrideColor = ''
@@ -19,7 +19,7 @@ jest.mock('@times-components/ts-components', () => ({
19
19
  }));
20
20
 
21
21
  describe('ArticleFlag', () => {
22
- // GMT: Thursday, 14 March 2019 16:22:54
22
+ // GMT : Thursday, 14 March 2019 16:22:54
23
23
  beforeEach(() => {
24
24
  mockDate.set(1552580574000);
25
25
  });
@@ -1,4 +1,4 @@
1
- import { FlagType } from './ArticleFlag';
1
+ import { FlagType } from './types';
2
2
 
3
3
  const getActiveArticleFlags: (flags: FlagType) => FlagType = flags => {
4
4
  if (!flags) {
@@ -1,6 +1,6 @@
1
1
  import styled, { keyframes } from 'styled-components';
2
2
  import { fonts } from '@times-components/ts-styleguide';
3
- import { FlagType } from './ArticleFlag';
3
+ import { FlagType } from './types';
4
4
  import { gqlRgbaToStyle } from '@times-components/utils';
5
5
 
6
6
  export const LiveArticleFlagContainer = styled.div`
@@ -0,0 +1,4 @@
1
+ export type FlagType = Array<{
2
+ expiryTime: string | null;
3
+ type: string;
4
+ }>;
@@ -0,0 +1,66 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Banner renders the banner 1`] = `
4
+ <DocumentFragment>
5
+ <div
6
+ class="sc-bdVaJa VUwsZ"
7
+ >
8
+ <div
9
+ aria-label="Email verification banner"
10
+ class="sc-bwzfXH eWmkTr"
11
+ >
12
+ <div
13
+ class="sc-htpNat kKgziG"
14
+ role="region"
15
+ >
16
+ <div
17
+ class="sc-bxivhb iVoVQA"
18
+ >
19
+ <div
20
+ class="sc-ifAKCX fBzQxS"
21
+ >
22
+ <svg
23
+ fill="none"
24
+ height="24"
25
+ viewBox="0 0 24 24"
26
+ width="24"
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ >
29
+ <path
30
+ d="M22 9.98V19C22 20.1 21.1 21 20 21H4C2.9 21 2 20.1 2 19L2.01 7C2.01 5.9 2.9 5 4 5H14.1C14.04 5.32 14 5.66 14 6C14 6.34 14.04 6.68 14.1 7H4L12 12L15.67 9.71C16.14 10.14 16.69 10.47 17.3 10.69L12 14L4 9V19H20V10.9C20.74 10.75 21.42 10.42 22 9.98ZM16 6C16 7.66 17.34 9 19 9C20.66 9 22 7.66 22 6C22 4.34 20.66 3 19 3C17.34 3 16 4.34 16 6Z"
31
+ fill="#000"
32
+ />
33
+ </svg>
34
+ <p
35
+ class="sc-EHOje dMjtnD"
36
+ >
37
+ Title
38
+ </p>
39
+ </div>
40
+ <button
41
+ class="sc-gzVnrw hWbcjJ"
42
+ >
43
+ <svg
44
+ fill="none"
45
+ height="14"
46
+ viewBox="0 0 14 14"
47
+ width="14"
48
+ xmlns="http://www.w3.org/2000/svg"
49
+ >
50
+ <path
51
+ d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z"
52
+ fill="#000"
53
+ />
54
+ </svg>
55
+ </button>
56
+ </div>
57
+ <p
58
+ class="sc-bZQynM jtrtRX"
59
+ >
60
+ Body
61
+ </p>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ </DocumentFragment>
66
+ `;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import '@testing-library/jest-dom';
3
+ import { render } from '@testing-library/react';
4
+ import { Banner } from '../banner';
5
+
6
+ describe('Banner', () => {
7
+ it('renders the banner', () => {
8
+ const { asFragment } = render(
9
+ <Banner title="Title" body="Body" onClose={jest.fn} />
10
+ );
11
+ expect(asFragment()).toMatchSnapshot();
12
+ });
13
+ });
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+
3
+ const CloseIconBlack: React.FC<any> = ({
4
+ width = 24,
5
+ height = 24,
6
+ color = '#000',
7
+ ...props
8
+ }) => (
9
+ <svg
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ width={width}
12
+ height={height}
13
+ viewBox="0 0 14 14"
14
+ fill="none"
15
+ {...props}
16
+ >
17
+ <path
18
+ d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z"
19
+ fill={color}
20
+ />
21
+ </svg>
22
+ );
23
+
24
+ export default CloseIconBlack;
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+
3
+ const EmailIcon: React.FC<any> = ({
4
+ width = 24,
5
+ height = 24,
6
+ color = '#000',
7
+ ...props
8
+ }) => (
9
+ <svg
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ width={width}
12
+ height={height}
13
+ viewBox="0 0 24 24"
14
+ fill="none"
15
+ {...props}
16
+ >
17
+ <path
18
+ d="M22 9.98V19C22 20.1 21.1 21 20 21H4C2.9 21 2 20.1 2 19L2.01 7C2.01 5.9 2.9 5 4 5H14.1C14.04 5.32 14 5.66 14 6C14 6.34 14.04 6.68 14.1 7H4L12 12L15.67 9.71C16.14 10.14 16.69 10.47 17.3 10.69L12 14L4 9V19H20V10.9C20.74 10.75 21.42 10.42 22 9.98ZM16 6C16 7.66 17.34 9 19 9C20.66 9 22 7.66 22 6C22 4.34 20.66 3 19 3C17.34 3 16 4.34 16 6Z"
19
+ fill={color}
20
+ />
21
+ </svg>
22
+ );
23
+
24
+ export default EmailIcon;
@@ -0,0 +1,30 @@
1
+ import { Meta, Story, Props } from '@storybook/addon-docs'
2
+
3
+ import { Banner } from './banner';
4
+
5
+ <Meta
6
+ title="Components/Misc/Banner"
7
+ component={Banner}
8
+ />
9
+
10
+ # Banner component
11
+ The `Banner` component is used to show and hide related content.
12
+
13
+ This component takes in a two props, as below, to display text based content.
14
+
15
+ ## Props
16
+ <Props of={Banner} />
17
+
18
+ ## Code Example
19
+ `<Banner />`
20
+
21
+ ## View Component
22
+ Please click the 'Canvas' tab for a better viewing experience, where you can update the props and review at the different breakpoints by clicking the preview icon and selecting from our list of pre-defined breakpoints (XS, SM, MD, LG and XL).
23
+
24
+ export const BannerStory = ({ group }) => (
25
+ <Banner title="Banner title" body="Banner message" onClose={() => console.log('close')} />
26
+ );
27
+
28
+ <Story name="Banner">
29
+ {BannerStory.bind({})}
30
+ </Story>
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import {
3
+ Body,
4
+ CloseIconWrapper,
5
+ Title,
6
+ TitleWrapper,
7
+ Wrapper,
8
+ StyledBanner,
9
+ BannerWrapper,
10
+ BannerContentWrapper
11
+ } from './styles';
12
+ import CloseIconBlack from './assets/CloseIconBlack';
13
+ import EmailIcon from './assets/EmailIcon';
14
+
15
+ type Props = {
16
+ onClose: () => void;
17
+ title: string;
18
+ body: string;
19
+ };
20
+
21
+ export const Banner: React.FC<Props> = ({ title, body, onClose }) => {
22
+ return (
23
+ <BannerWrapper>
24
+ <StyledBanner aria-label="Email verification banner">
25
+ <BannerContentWrapper role="region">
26
+ <Wrapper>
27
+ <TitleWrapper>
28
+ <EmailIcon />
29
+ <Title>{title}</Title>
30
+ </TitleWrapper>
31
+ <CloseIconWrapper onClick={onClose}>
32
+ <CloseIconBlack width={14} height={14} />
33
+ </CloseIconWrapper>
34
+ </Wrapper>
35
+ <Body>{body}</Body>
36
+ </BannerContentWrapper>
37
+ </StyledBanner>
38
+ </BannerWrapper>
39
+ );
40
+ };
@@ -0,0 +1,80 @@
1
+ import styled from 'styled-components';
2
+ import { breakpoints } from '@times-components/ts-styleguide';
3
+
4
+ export const BannerWrapper = styled.div`
5
+ max-width: 498px;
6
+ box-shadow: 0px 16px 24px 0px rgba(17, 17, 17, 0.08);
7
+ z-index: 100;
8
+ width: 100%;
9
+ `;
10
+
11
+ export const StyledBanner = styled.div`
12
+ border-top: 3px solid #005c8a;
13
+ background-color: #fff;
14
+ flex-direction: column;
15
+ align-items: flex-start;
16
+ padding-left: 16px;
17
+ padding-block: 12px;
18
+ padding-right: 16px;
19
+ @media screen and (min-width: ${breakpoints.wide}px) {
20
+ padding-block: 10px;
21
+ }
22
+ @media screen and (min-width: ${breakpoints.medium}px) {
23
+ padding-right: 30px;
24
+ }
25
+ `;
26
+
27
+ export const BannerContentWrapper = styled.div`
28
+ flex-direction: inherit;
29
+ `;
30
+
31
+ export const Wrapper = styled.div`
32
+ display: flex;
33
+ justify-content: space-between;
34
+ align-items: center;
35
+ width: 100%;
36
+ margin-bottom: 12px;
37
+ @media screen and (min-width: ${breakpoints.medium}px) {
38
+ margin-bottom: 8px;
39
+ }
40
+ `;
41
+
42
+ export const TitleWrapper = styled.div`
43
+ display: flex;
44
+ align-items: center;
45
+ width: 100%;
46
+ `;
47
+
48
+ export const Title = styled.p`
49
+ color: #333;
50
+ font-weight: 700;
51
+ margin: 0 0 0 16px;
52
+ font-size: 24px;
53
+ line-height: 27px;
54
+ font-family: 'Times Modern';
55
+ letter-spacing: 0em;
56
+ @media (max-width: ${breakpoints.medium}px) {
57
+ font-size: 18px;
58
+ line-height: 20px;
59
+ }
60
+ `;
61
+
62
+ export const Body = styled.p`
63
+ color: #696969;
64
+ font-weight: 400;
65
+ margin: 0;
66
+ font-size: 16px;
67
+ line-height: 24px;
68
+ font-family: 'Roboto';
69
+ letter-spacing: 0em;
70
+ @media (max-width: ${breakpoints.medium}px) {
71
+ font-size: 14px;
72
+ line-height: 21px;
73
+ }
74
+ `;
75
+
76
+ export const CloseIconWrapper = styled.button`
77
+ background: #fff;
78
+ border: none;
79
+ cursor: pointer;
80
+ `;
@@ -0,0 +1,64 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Render Breadcrumbs should render a snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <nav
6
+ aria-label="breadcrumbs"
7
+ class="sc-bwzfXH jIEWCi"
8
+ >
9
+ <a
10
+ aria-current="false"
11
+ class="sc-bdVaJa gZsChJ"
12
+ href="/sport"
13
+ >
14
+ Sport
15
+ </a>
16
+ <div
17
+ class="sc-htpNat jVxkgC"
18
+ >
19
+ <svg
20
+ color="#aaaaaa"
21
+ fill="none"
22
+ height="16"
23
+ width="16"
24
+ xmlns="http://www.w3.org/2000/svg"
25
+ >
26
+ <path
27
+ d="m6.667 4-.94.94L8.78 8l-3.053 3.06.94.94 4-4-4-4Z"
28
+ fill="#aaaaaa"
29
+ />
30
+ </svg>
31
+ </div>
32
+ <a
33
+ aria-current="false"
34
+ class="sc-bdVaJa gZsChJ"
35
+ href="/sport/tennis"
36
+ >
37
+ Tennis
38
+ </a>
39
+ <div
40
+ class="sc-htpNat jVxkgC"
41
+ >
42
+ <svg
43
+ color="#aaaaaa"
44
+ fill="none"
45
+ height="16"
46
+ width="16"
47
+ xmlns="http://www.w3.org/2000/svg"
48
+ >
49
+ <path
50
+ d="m6.667 4-.94.94L8.78 8l-3.053 3.06.94.94 4-4-4-4Z"
51
+ fill="#aaaaaa"
52
+ />
53
+ </svg>
54
+ </div>
55
+ <a
56
+ aria-current="page"
57
+ class="sc-bdVaJa gItCja"
58
+ href="/australian open"
59
+ >
60
+ Australian Open
61
+ </a>
62
+ </nav>
63
+ </DocumentFragment>
64
+ `;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import '@testing-library/jest-dom';
3
+ import { render, fireEvent } from '@testing-library/react';
4
+ import { Breadcrumb } from '../breadcrumb';
5
+ import { breadcrumbItems } from '../fixtures/breadcrumbs.json';
6
+ import { TrackingContextProvider } from '../../../helpers/tracking/TrackingContextProvider';
7
+
8
+ describe('Render Breadcrumbs', () => {
9
+ const renderBreadcrumb = (analyticsStream?: (event: any) => void) =>
10
+ render(
11
+ <TrackingContextProvider
12
+ context={{
13
+ component: 'breadcrumb',
14
+ attrs: {}
15
+ }}
16
+ analyticsStream={analyticsStream}
17
+ >
18
+ <Breadcrumb data={breadcrumbItems} />
19
+ </TrackingContextProvider>
20
+ );
21
+ it('should render a snapshot', () => {
22
+ const { asFragment } = renderBreadcrumb();
23
+ expect(asFragment()).toMatchSnapshot();
24
+ });
25
+
26
+ it('should render the component', () => {
27
+ const { getByText } = renderBreadcrumb();
28
+ const getBreadcrumb = getByText('Tennis');
29
+ expect(getBreadcrumb).toBeInTheDocument();
30
+ });
31
+
32
+ it('items should have link with href', () => {
33
+ const { getAllByRole } = renderBreadcrumb();
34
+ const title = getAllByRole('link')[0];
35
+ expect(title).toHaveAttribute('href', '/sport');
36
+ });
37
+
38
+ it('last breadcrumb should be selected', () => {
39
+ const { getAllByRole } = renderBreadcrumb();
40
+ const title = getAllByRole('link')[2];
41
+ expect(title).toHaveAttribute('aria-current', 'page');
42
+ });
43
+
44
+ it('calls analyticsStream when you click', () => {
45
+ const analyticsStream = jest.fn();
46
+ const { getByText } = renderBreadcrumb(analyticsStream);
47
+ const breadcrumb = getByText('Tennis');
48
+ fireEvent.click(breadcrumb);
49
+ expect(analyticsStream).toHaveBeenCalledTimes(1);
50
+ });
51
+ });
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ const BreadcrumbIcon = (props: any) => (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width={16}
6
+ height={16}
7
+ fill="none"
8
+ {...props}
9
+ >
10
+ <path
11
+ fill={props.color}
12
+ d="m6.667 4-.94.94L8.78 8l-3.053 3.06.94.94 4-4-4-4Z"
13
+ />
14
+ </svg>
15
+ );
16
+ export default BreadcrumbIcon;
@@ -0,0 +1,47 @@
1
+ import { Meta, Story, Props } from '@storybook/addon-docs'
2
+ import { Breadcrumb } from './breadcrumb.tsx';
3
+ import { breadcrumbItems, breadcrumbItemsForTrackingDemo } from './fixtures/breadcrumbs.json';
4
+ import { TrackingContextProvider } from '../../helpers/tracking/TrackingContextProvider';
5
+ import analyticsStream from '../../fixtures/analytics-actions/analytics-actions';
6
+
7
+ <Meta
8
+ title="Components/Navigation/Breadcrumb"
9
+ component={Breadcrumb}
10
+ />
11
+
12
+ # Breadcrumb component
13
+ The `Breadcrumb` component displays your hierarchical position on the website.
14
+
15
+ This takes in a `data` prop, as below, to display the links in their order within the data object.
16
+
17
+ ## Props
18
+ <Props of={Breadcrumb} />
19
+
20
+ ## Code Example
21
+ `<Breadcrumb data={data} />`
22
+
23
+ An example of the `data` structure can be found in the 'Controls' section on the 'Canvas' tab, where you can customise the data being fed to the Breadcrumb component.
24
+
25
+ ## View Component
26
+ Please click the 'Canvas' tab for a better viewing experience, where you can update the props and review at the different breakpoints by clicking the preview icon and selecting from our list of pre-defined breakpoints (XS, SM, MD, LG and XL).
27
+
28
+ export const BreadcrumbStory = ({ data }) => (
29
+ <TrackingContextProvider
30
+ analyticsStream={analyticsStream}
31
+ context={{
32
+ component: 'breadcrumb',
33
+ attrs: {
34
+ }
35
+ }}
36
+ >
37
+ <Breadcrumb {...{ data }} />
38
+ </TrackingContextProvider>
39
+ );
40
+
41
+ <Story name="Breadcrumb" args={{ data: breadcrumbItems }}>
42
+ {BreadcrumbStory.bind({})}
43
+ </Story>
44
+
45
+ <Story name="Breadcrumb - tracking demo" args={{ data: breadcrumbItemsForTrackingDemo }}>
46
+ {BreadcrumbStory.bind({})}
47
+ </Story>
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { Breadcrumbs, BreadcrumbItem, IconContainer, styleMap } from './styles';
3
+ import BreadcrumbIcon from './assets/BreadcrumbIcon';
4
+ import {
5
+ TrackingContext,
6
+ TrackingContextProvider
7
+ } from '../../helpers/tracking/TrackingContextProvider';
8
+
9
+ type BreadcrumbsItem = {
10
+ title: string;
11
+ url?: string;
12
+ };
13
+
14
+ type BreadcrumbProps = {
15
+ data: BreadcrumbsItem[];
16
+ };
17
+
18
+ export const Breadcrumb = ({ data }: BreadcrumbProps) => {
19
+ const clickEvent = (title: string) => ({
20
+ object: 'Breadcrumb',
21
+ action: 'Clicked',
22
+ attrs: {
23
+ event_navigation_action: 'navigation',
24
+ event_navigation_name: 'header:selection',
25
+ event_navigation_browsing_method: 'click',
26
+ article_parent_name: `breadcrumb : ${title}`
27
+ }
28
+ });
29
+
30
+ const handleClick = (
31
+ fireAnalyticsEvent: (evt: TrackingContext) => void,
32
+ title: string
33
+ ) => {
34
+ fireAnalyticsEvent && fireAnalyticsEvent(clickEvent(title));
35
+ };
36
+
37
+ const getBreadcrumbSeparator = (index: number, arr: any[]) =>
38
+ index < arr.length - 1;
39
+
40
+ return (
41
+ <TrackingContextProvider>
42
+ {({ fireAnalyticsEvent }) => (
43
+ <Breadcrumbs aria-label="breadcrumbs">
44
+ {data.map((breadcrumbItem, breadcrumbIndex, breadcrumbArr) => {
45
+ const showSeparator = getBreadcrumbSeparator(
46
+ breadcrumbIndex,
47
+ breadcrumbArr
48
+ );
49
+ return showSeparator ? (
50
+ <>
51
+ <BreadcrumbItem
52
+ key={breadcrumbItem.title}
53
+ aria-current="false"
54
+ href={breadcrumbItem.url}
55
+ selected={false}
56
+ onClick={() =>
57
+ handleClick(fireAnalyticsEvent, breadcrumbItem.title)
58
+ }
59
+ >
60
+ {breadcrumbItem.title}
61
+ </BreadcrumbItem>
62
+ <IconContainer>
63
+ <BreadcrumbIcon color={styleMap.colors.inkNonEssential} />
64
+ </IconContainer>
65
+ </>
66
+ ) : (
67
+ <BreadcrumbItem
68
+ aria-current="page"
69
+ key={breadcrumbItem.title}
70
+ href={breadcrumbItem.url}
71
+ selected={true}
72
+ onClick={() =>
73
+ handleClick(fireAnalyticsEvent, breadcrumbItem.title)
74
+ }
75
+ >
76
+ {breadcrumbItem.title}
77
+ </BreadcrumbItem>
78
+ );
79
+ })}
80
+ </Breadcrumbs>
81
+ )}
82
+ </TrackingContextProvider>
83
+ );
84
+ };
@@ -0,0 +1,27 @@
1
+ {
2
+ "breadcrumbItems": [
3
+ {
4
+ "title": "Sport",
5
+ "url": "/sport"
6
+ },
7
+ {
8
+ "title": "Tennis",
9
+ "url": "/sport/tennis"
10
+ },
11
+ {
12
+ "title": "Australian Open",
13
+ "url": "/australian open"
14
+ }
15
+ ],
16
+ "breadcrumbItemsForTrackingDemo": [
17
+ {
18
+ "title": "Sport"
19
+ },
20
+ {
21
+ "title": "Tennis"
22
+ },
23
+ {
24
+ "title": "Australian Open"
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,43 @@
1
+ import styled from 'styled-components';
2
+
3
+ export const styleMap = {
4
+ colors: {
5
+ blue070: '#006699',
6
+ inkContrast: '#01000d',
7
+ inkSubtle: '#696969',
8
+ inkNonEssential: '#aaaaaa'
9
+ }
10
+ };
11
+
12
+ export const BreadcrumbItem = styled.a<{ selected: boolean }>`
13
+ color: inherit;
14
+ text-decoration: none;
15
+ display: inline-grid;
16
+ font-family: Roboto-Regular;
17
+ font-size: 12px;
18
+ font-weight: 500;
19
+ line-height: 1.250;
20
+ letter-spacing: 0%;
21
+ font-stretch: normal
22
+ display: inline-grid;
23
+ background-color: transparent;
24
+ min-height: 32px;
25
+ border: none;
26
+ place-content: center;
27
+ color: ${({ selected }) =>
28
+ selected ? styleMap.colors.inkContrast : styleMap.colors.inkSubtle};
29
+ &:hover {
30
+ color: ${styleMap.colors.blue070}
31
+ };
32
+ `;
33
+
34
+ export const Breadcrumbs = styled.nav`
35
+ display: flex;
36
+ `;
37
+
38
+ export const IconContainer = styled.div`
39
+ height: 32px;
40
+ display: flex;
41
+ align-items: center;
42
+ padding-inline: 8px;
43
+ `;