@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.
- package/dist/components/article-flag/ArticleFlag.d.ts +1 -4
- package/dist/components/article-flag/ArticleFlag.js +1 -1
- package/dist/components/article-flag/__tests__/ArticleFlag.test.js +2 -2
- package/dist/components/article-flag/getActiveFlags.d.ts +1 -1
- package/dist/components/article-flag/styles.d.ts +1 -1
- package/dist/components/article-flag/types.d.ts +4 -0
- package/dist/components/article-flag/types.js +2 -0
- package/dist/components/banner/__tests__/banner.test.d.ts +1 -0
- package/dist/components/banner/__tests__/banner.test.js +11 -0
- package/dist/components/banner/assets/CloseIconBlack.d.ts +3 -0
- package/dist/components/banner/assets/CloseIconBlack.js +5 -0
- package/dist/components/banner/assets/EmailIcon.d.ts +3 -0
- package/dist/components/banner/assets/EmailIcon.js +5 -0
- package/dist/components/banner/banner.d.ts +8 -0
- package/dist/components/banner/banner.js +17 -0
- package/dist/components/banner/styles.d.ts +8 -0
- package/dist/components/banner/styles.js +73 -0
- package/dist/components/breadcrumb/__tests__/index.test.d.ts +1 -0
- package/dist/components/breadcrumb/__tests__/index.test.js +40 -0
- package/dist/components/breadcrumb/assets/BreadcrumbIcon.d.ts +2 -0
- package/dist/components/breadcrumb/assets/BreadcrumbIcon.js +5 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +9 -0
- package/dist/components/breadcrumb/breadcrumb.js +28 -0
- package/dist/components/breadcrumb/fixtures/breadcrumbs.json +27 -0
- package/dist/components/breadcrumb/styles.d.ts +13 -0
- package/dist/components/breadcrumb/styles.js +39 -0
- package/dist/components/delayed-component/__tests__/delayed-component.test.d.ts +1 -0
- package/dist/components/delayed-component/__tests__/delayed-component.test.js +23 -0
- package/dist/components/delayed-component/delayed-component.d.ts +6 -0
- package/dist/components/delayed-component/delayed-component.js +11 -0
- package/dist/components/in-article-info-card/Card.d.ts +1 -1
- package/dist/components/in-article-info-card/InfoCard.d.ts +0 -8
- package/dist/components/in-article-info-card/InfoCard.js +1 -1
- package/dist/components/in-article-info-card/types.d.ts +8 -0
- package/dist/components/in-article-info-card/types.js +2 -0
- package/dist/components/job-title/__tests__/index.test.d.ts +1 -0
- package/dist/components/job-title/__tests__/index.test.js +45 -0
- package/dist/components/job-title/assets/TooltipIcon.d.ts +2 -0
- package/dist/components/job-title/assets/TooltipIcon.js +11 -0
- package/dist/components/job-title/assets/close-icon.d.ts +2 -0
- package/dist/components/job-title/assets/close-icon.js +5 -0
- package/dist/components/job-title/job-title.d.ts +11 -0
- package/dist/components/job-title/job-title.js +31 -0
- package/dist/components/job-title/styles.d.ts +11 -0
- package/dist/components/job-title/styles.js +150 -0
- package/dist/components/save-star/ContentProvider.d.ts +0 -6
- package/dist/components/save-star/ContentProvider.js +1 -1
- package/dist/components/save-star/SaveStar.js +1 -1
- package/dist/components/save-star/SaveStarUI.d.ts +1 -4
- package/dist/components/save-star/SaveStarUI.js +1 -1
- package/dist/components/save-star/types.d.ts +8 -0
- package/dist/components/save-star/types.js +2 -0
- package/dist/components/update-button/__tests__/update-button-with-delay.test.d.ts +1 -0
- package/dist/components/update-button/__tests__/update-button-with-delay.test.js +24 -0
- package/dist/components/update-button/__tests__/update-button.test.d.ts +1 -0
- package/dist/components/update-button/__tests__/update-button.test.js +27 -0
- package/dist/components/update-button/assets/FilledArrowIcon.d.ts +3 -0
- package/dist/components/update-button/assets/FilledArrowIcon.js +5 -0
- package/dist/components/update-button/styles.d.ts +1 -0
- package/dist/components/update-button/styles.js +39 -0
- package/dist/components/update-button/update-button-with-delay.d.ts +11 -0
- package/dist/components/update-button/update-button-with-delay.js +27 -0
- package/dist/components/update-button/update-button.d.ts +6 -0
- package/dist/components/update-button/update-button.js +9 -0
- package/dist/fixtures/article-harness/__tests__/articleHarness.test.d.ts +1 -0
- package/dist/fixtures/article-harness/__tests__/articleHarness.test.js +11 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +8 -3
- package/package.json +17 -16
- package/rnw.js +1 -1
- package/src/components/article-flag/ArticleFlag.tsx +1 -5
- package/src/components/article-flag/__tests__/ArticleFlag.test.tsx +1 -1
- package/src/components/article-flag/getActiveFlags.ts +1 -1
- package/src/components/article-flag/styles.ts +1 -1
- package/src/components/article-flag/types.ts +4 -0
- package/src/components/banner/__tests__/__snapshots__/banner.test.tsx.snap +66 -0
- package/src/components/banner/__tests__/banner.test.tsx +13 -0
- package/src/components/banner/assets/CloseIconBlack.tsx +24 -0
- package/src/components/banner/assets/EmailIcon.tsx +24 -0
- package/src/components/banner/banner.stories.mdx +30 -0
- package/src/components/banner/banner.tsx +40 -0
- package/src/components/banner/styles.ts +80 -0
- package/src/components/breadcrumb/__tests__/__snapshots__/index.test.tsx.snap +64 -0
- package/src/components/breadcrumb/__tests__/index.test.tsx +51 -0
- package/src/components/breadcrumb/assets/BreadcrumbIcon.tsx +16 -0
- package/src/components/breadcrumb/breadcrumb.stories.mdx +47 -0
- package/src/components/breadcrumb/breadcrumb.tsx +84 -0
- package/src/components/breadcrumb/fixtures/breadcrumbs.json +27 -0
- package/src/components/breadcrumb/styles.ts +43 -0
- package/src/components/delayed-component/__tests__/delayed-component.test.tsx +30 -0
- package/src/components/delayed-component/delayed-component.stories.mdx +38 -0
- package/src/components/delayed-component/delayed-component.tsx +16 -0
- package/src/components/in-article-info-card/Card.tsx +1 -1
- package/src/components/in-article-info-card/InfoCard.tsx +1 -8
- package/src/components/in-article-info-card/types.ts +8 -0
- package/src/components/job-title/__tests__/__snapshots__/index.test.tsx.snap +271 -0
- package/src/components/job-title/__tests__/index.test.tsx +71 -0
- package/src/components/job-title/assets/TooltipIcon.tsx +37 -0
- package/src/components/job-title/assets/close-icon.tsx +18 -0
- package/src/components/job-title/job-title.stories.mdx +38 -0
- package/src/components/job-title/job-title.tsx +85 -0
- package/src/components/job-title/styles.ts +154 -0
- package/src/components/save-star/ContentProvider.tsx +1 -7
- package/src/components/save-star/SaveStar.tsx +2 -1
- package/src/components/save-star/SaveStarUI.tsx +1 -5
- package/src/components/save-star/types.ts +9 -0
- package/src/components/update-button/__tests__/__snapshots__/update-button-with-delay.test.tsx.snap +23 -0
- package/src/components/update-button/__tests__/__snapshots__/update-button.test.tsx.snap +23 -0
- package/src/components/update-button/__tests__/update-button-with-delay.test.tsx +67 -0
- package/src/components/update-button/__tests__/update-button.test.tsx +31 -0
- package/src/components/update-button/assets/FilledArrowIcon.tsx +17 -0
- package/src/components/update-button/styles.ts +40 -0
- package/src/components/update-button/update-button-with-delay.stories.mdx +40 -0
- package/src/components/update-button/update-button-with-delay.tsx +53 -0
- package/src/components/update-button/update-button.stories.mdx +32 -0
- package/src/components/update-button/update-button.tsx +17 -0
- package/src/fixtures/article-harness/__tests__/__snapshots__/articleHarness.test.tsx.snap +34 -0
- package/src/fixtures/article-harness/__tests__/articleHarness.test.tsx +11 -0
- package/src/index.ts +15 -7
- 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 = ''
|
|
@@ -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 './
|
|
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,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
|
+
`;
|