@automattic/jetpack-components 0.40.0 → 0.40.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/CHANGELOG.md +12 -0
- package/components/button/stories/index.mdx +1 -1
- package/components/jetpack-footer/index.tsx +52 -49
- package/components/jetpack-footer/style.scss +67 -84
- package/components/jetpack-footer/test/__snapshots__/component.tsx.snap +117 -0
- package/components/jetpack-footer/test/component.tsx +140 -23
- package/components/jetpack-footer/types.ts +1 -1
- package/components/layout/col/README.md +8 -0
- package/components/layout/col/index.tsx +9 -2
- package/components/layout/container/README.md +8 -0
- package/components/layout/container/index.tsx +9 -5
- package/components/layout/types.ts +10 -0
- package/components/pricing-slider/index.tsx +23 -3
- package/components/pricing-slider/style.scss +14 -3
- package/components/stat-card/stories/index.mdx +1 -1
- package/components/text/stories/index.mdx +1 -1
- package/package.json +13 -12
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
### This is a list detailing changes for the Jetpack RNA Components package releases.
|
|
4
4
|
|
|
5
|
+
## [0.40.1] - 2023-07-05
|
|
6
|
+
### Changed
|
|
7
|
+
- Adjust component pricing slider border and box-shadow styling. [#31593]
|
|
8
|
+
- Updated package dependencies. [#31659]
|
|
9
|
+
- Updated package dependencies. [#31661]
|
|
10
|
+
- Update storybook mdx to use `@storybook/blocks` directly rather than `@storybook/addon-docs`. [#31607]
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Add tagName prop to Col and Container [#31606]
|
|
14
|
+
- Fix Jetpack footer accessibility issues [#31417]
|
|
15
|
+
|
|
5
16
|
## [0.40.0] - 2023-06-26
|
|
6
17
|
### Added
|
|
7
18
|
- Add authentication to Zendesk chat. [#31339]
|
|
@@ -748,5 +759,6 @@
|
|
|
748
759
|
### Changed
|
|
749
760
|
- Update node version requirement to 14.16.1
|
|
750
761
|
|
|
762
|
+
[0.40.1]: https://github.com/Automattic/jetpack-components/compare/0.40.0...0.40.1
|
|
751
763
|
[0.40.0]: https://github.com/Automattic/jetpack-components/compare/0.39.0...0.40.0
|
|
752
764
|
[0.39.0]: https://github.com/Automattic/jetpack-components/compare/0.38.1...0.39.0
|
|
@@ -8,6 +8,10 @@ import JetpackLogo from '../jetpack-logo';
|
|
|
8
8
|
import useBreakpointMatch from '../layout/use-breakpoint-match';
|
|
9
9
|
import type { JetpackFooterProps } from './types';
|
|
10
10
|
|
|
11
|
+
const JetpackIcon: React.FC = () => (
|
|
12
|
+
<JetpackLogo logoColor="#000" showText={ false } height={ 16 } aria-hidden="true" />
|
|
13
|
+
);
|
|
14
|
+
|
|
11
15
|
/**
|
|
12
16
|
* JetpackFooter component displays a tiny Jetpack logo with the product name on the left and the Automattic Airline "by line" on the right.
|
|
13
17
|
*
|
|
@@ -24,70 +28,69 @@ const JetpackFooter: React.FC< JetpackFooterProps > = ( {
|
|
|
24
28
|
} ) => {
|
|
25
29
|
const [ isSm ] = useBreakpointMatch( 'sm', '<=' );
|
|
26
30
|
const [ isMd ] = useBreakpointMatch( 'md', '<=' );
|
|
31
|
+
const [ isLg ] = useBreakpointMatch( 'lg', '>' );
|
|
32
|
+
|
|
33
|
+
const jetpackItemContent = (
|
|
34
|
+
<>
|
|
35
|
+
<JetpackIcon />
|
|
36
|
+
{ moduleName }
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
27
39
|
|
|
28
40
|
return (
|
|
29
|
-
<
|
|
41
|
+
<footer
|
|
30
42
|
className={ classnames(
|
|
31
43
|
'jp-dashboard-footer',
|
|
32
44
|
{
|
|
33
45
|
'is-sm': isSm,
|
|
34
46
|
'is-md': isMd,
|
|
47
|
+
'is-lg': isLg,
|
|
35
48
|
},
|
|
36
49
|
className
|
|
37
50
|
) }
|
|
51
|
+
aria-label={ __( 'Jetpack', 'jetpack' ) }
|
|
38
52
|
{ ...otherProps }
|
|
39
53
|
>
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
logoColor="#000"
|
|
43
|
-
showText={ false }
|
|
44
|
-
height={ 16 }
|
|
45
|
-
className="jp-dashboard-footer__jetpack-symbol"
|
|
46
|
-
aria-label={ __( 'Jetpack logo', 'jetpack' ) }
|
|
47
|
-
/>
|
|
48
|
-
<span className="jp-dashboard-footer__module-name">
|
|
54
|
+
<ul>
|
|
55
|
+
<li className="jp-dashboard-footer__jp-item">
|
|
49
56
|
{ moduleNameHref ? (
|
|
50
|
-
<a href={ moduleNameHref }
|
|
51
|
-
{ moduleName }
|
|
52
|
-
</a>
|
|
57
|
+
<a href={ moduleNameHref }>{ jetpackItemContent }</a>
|
|
53
58
|
) : (
|
|
54
|
-
|
|
59
|
+
jetpackItemContent
|
|
55
60
|
) }
|
|
56
|
-
</
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
'
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<Icon
|
|
78
|
-
|
|
79
|
-
</
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
>
|
|
88
|
-
|
|
89
|
-
</a>
|
|
90
|
-
</div>
|
|
61
|
+
</li>
|
|
62
|
+
{ menu?.map( item => {
|
|
63
|
+
const isButton = item.role === 'button';
|
|
64
|
+
const isExternalLink = ! isButton && item.target === '_blank';
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<li key={ item.label }>
|
|
68
|
+
<a
|
|
69
|
+
href={ item.href }
|
|
70
|
+
title={ item.title }
|
|
71
|
+
target={ item.target }
|
|
72
|
+
onClick={ item.onClick }
|
|
73
|
+
onKeyDown={ item.onKeyDown }
|
|
74
|
+
className={ classnames( 'jp-dashboard-footer__menu-item', {
|
|
75
|
+
'is-external': isExternalLink,
|
|
76
|
+
} ) }
|
|
77
|
+
role={ item.role }
|
|
78
|
+
rel={ isExternalLink ? 'noopener noreferrer' : undefined }
|
|
79
|
+
tabIndex={ isButton ? 0 : undefined }
|
|
80
|
+
>
|
|
81
|
+
{ item.label }
|
|
82
|
+
{ isExternalLink && <Icon icon={ external } size={ 16 } /> }
|
|
83
|
+
</a>
|
|
84
|
+
</li>
|
|
85
|
+
);
|
|
86
|
+
} ) }
|
|
87
|
+
<li className="jp-dashboard-footer__a8c-item">
|
|
88
|
+
<a href={ a8cLogoHref } aria-label={ __( 'An Automattic Airline', 'jetpack' ) }>
|
|
89
|
+
<AutomatticBylineLogo aria-hidden="true" />
|
|
90
|
+
</a>
|
|
91
|
+
</li>
|
|
92
|
+
</ul>
|
|
93
|
+
</footer>
|
|
91
94
|
);
|
|
92
95
|
};
|
|
93
96
|
|
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
.jp-dashboard-footer {
|
|
2
|
-
align-items: center;
|
|
3
|
-
color: var( --jp-black );
|
|
4
2
|
display: flex;
|
|
5
3
|
flex-wrap: wrap;
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
align-items: center;
|
|
5
|
+
|
|
8
6
|
max-width: 1128px;
|
|
9
7
|
width: 100%;
|
|
10
8
|
|
|
9
|
+
color: var( --jp-black );
|
|
10
|
+
|
|
11
|
+
font-size: var( --font-body-extra-small );
|
|
12
|
+
line-height: 1.333;
|
|
13
|
+
|
|
11
14
|
a {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
&:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
text-decoration: none;
|
|
16
|
+
|
|
17
|
+
&:any-link,
|
|
18
|
+
&[role=button] {
|
|
19
|
+
color: inherit;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:hover {
|
|
23
|
+
text-decoration: underline;
|
|
24
|
+
text-decoration-thickness: 1.5px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&:focus {
|
|
28
|
+
border-radius: 2px;
|
|
29
|
+
box-shadow: none;
|
|
30
|
+
outline: 1.5px solid currentColor;
|
|
31
|
+
outline-offset: 3px;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&.is-sm {
|
|
36
|
+
> ul {
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
align-items: flex-start;
|
|
39
|
+
gap: 0.125rem;
|
|
19
40
|
}
|
|
20
41
|
}
|
|
21
42
|
|
|
@@ -23,94 +44,56 @@
|
|
|
23
44
|
flex-direction: column;
|
|
24
45
|
align-items: flex-start;
|
|
25
46
|
}
|
|
26
|
-
}
|
|
27
47
|
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
> ul {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-wrap: wrap;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 1rem;
|
|
30
53
|
|
|
31
|
-
|
|
32
|
-
margin
|
|
33
|
-
|
|
34
|
-
|
|
54
|
+
width: 100%;
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 0;
|
|
57
|
+
|
|
58
|
+
list-style: none;
|
|
35
59
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
}
|
|
60
|
+
> li {
|
|
61
|
+
margin-bottom: 0;
|
|
40
62
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
63
|
+
> a {
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
gap: 0.25rem;
|
|
46
67
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
min-height: 44px; // Minimum target area size
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
50
72
|
}
|
|
51
73
|
|
|
52
|
-
.jp-dashboard-
|
|
53
|
-
|
|
74
|
+
.jp-dashboard-footer__jp-item {
|
|
75
|
+
padding-inline-end: 1rem;
|
|
54
76
|
|
|
55
|
-
|
|
56
|
-
margin-bottom: 24px;
|
|
57
|
-
}
|
|
77
|
+
font-weight: 600;
|
|
58
78
|
|
|
59
79
|
.jp-dashboard-footer.is-sm & {
|
|
60
|
-
|
|
61
|
-
align-items: flex-start;
|
|
62
|
-
margin-bottom: 48px;
|
|
63
|
-
|
|
64
|
-
.jp-dashboard-footer__menu-item {
|
|
65
|
-
margin-right: 0;
|
|
66
|
-
margin-bottom: 16px;
|
|
67
|
-
|
|
68
|
-
&:last-child {
|
|
69
|
-
margin-bottom: 0;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
80
|
+
padding-bottom: 1rem;
|
|
72
81
|
}
|
|
82
|
+
}
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
margin-right: 16px;
|
|
78
|
-
text-decoration: none;
|
|
79
|
-
|
|
80
|
-
&.is-external {
|
|
81
|
-
padding-right: 20px;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
&:focus {
|
|
85
|
-
border-radius: 2px;
|
|
86
|
-
outline-offset: 3px;
|
|
87
|
-
outline: 1.5px solid var( --jp-black );
|
|
88
|
-
box-shadow: none;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
&:hover {
|
|
92
|
-
text-decoration: underline;
|
|
93
|
-
text-decoration-thickness: 1.5px;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
&:hover:focus {
|
|
97
|
-
text-decoration: none;
|
|
98
|
-
}
|
|
84
|
+
.jp-dashboard-footer__a8c-item {
|
|
85
|
+
.jp-dashboard-footer.is-lg & {
|
|
86
|
+
margin-inline-start: auto;
|
|
99
87
|
}
|
|
100
88
|
|
|
101
|
-
.jp-dashboard-
|
|
102
|
-
|
|
103
|
-
height: 16px;
|
|
104
|
-
margin-left: 4px;
|
|
105
|
-
position: absolute;
|
|
106
|
-
right: 0;
|
|
89
|
+
.jp-dashboard-footer.is-sm & {
|
|
90
|
+
padding-top: 1rem;
|
|
107
91
|
}
|
|
108
92
|
}
|
|
109
93
|
|
|
110
|
-
.jp-dashboard-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
margin-left: 0;
|
|
94
|
+
.jp-dashboard-footer__jp-item,
|
|
95
|
+
.jp-dashboard-footer__a8c-item {
|
|
96
|
+
> a {
|
|
97
|
+
text-decoration: none; // Logos typically have no hover effect
|
|
115
98
|
}
|
|
116
|
-
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`JetpackFooter Render the component should match the snapshot: all props 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<footer
|
|
6
|
+
aria-label="Jetpack"
|
|
7
|
+
class="jp-dashboard-footer sample-classname"
|
|
8
|
+
>
|
|
9
|
+
<ul>
|
|
10
|
+
<li
|
|
11
|
+
class="jp-dashboard-footer__jp-item"
|
|
12
|
+
>
|
|
13
|
+
<a
|
|
14
|
+
href="https://jetpack.com/path/to-some-page"
|
|
15
|
+
>
|
|
16
|
+
<svg
|
|
17
|
+
aria-hidden="true"
|
|
18
|
+
aria-labelledby="jetpack-logo-title"
|
|
19
|
+
class="jetpack-logo"
|
|
20
|
+
height="16"
|
|
21
|
+
viewBox="0 0 32 32"
|
|
22
|
+
x="0px"
|
|
23
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
+
y="0px"
|
|
25
|
+
>
|
|
26
|
+
<desc
|
|
27
|
+
id="jetpack-logo-title"
|
|
28
|
+
>
|
|
29
|
+
Jetpack Logo
|
|
30
|
+
</desc>
|
|
31
|
+
<path
|
|
32
|
+
d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M15,19H7l8-16V19z M17,29V13h8L17,29z"
|
|
33
|
+
fill="#000"
|
|
34
|
+
/>
|
|
35
|
+
</svg>
|
|
36
|
+
Test module
|
|
37
|
+
</a>
|
|
38
|
+
</li>
|
|
39
|
+
<li>
|
|
40
|
+
<a
|
|
41
|
+
class="jp-dashboard-footer__menu-item"
|
|
42
|
+
href="/"
|
|
43
|
+
>
|
|
44
|
+
Link
|
|
45
|
+
</a>
|
|
46
|
+
</li>
|
|
47
|
+
<li>
|
|
48
|
+
<a
|
|
49
|
+
class="jp-dashboard-footer__menu-item is-external"
|
|
50
|
+
href="/"
|
|
51
|
+
rel="noopener noreferrer"
|
|
52
|
+
target="_blank"
|
|
53
|
+
>
|
|
54
|
+
External link
|
|
55
|
+
<svg
|
|
56
|
+
aria-hidden="true"
|
|
57
|
+
focusable="false"
|
|
58
|
+
height="16"
|
|
59
|
+
viewBox="0 0 24 24"
|
|
60
|
+
width="16"
|
|
61
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
62
|
+
>
|
|
63
|
+
<path
|
|
64
|
+
d="M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"
|
|
65
|
+
/>
|
|
66
|
+
</svg>
|
|
67
|
+
</a>
|
|
68
|
+
</li>
|
|
69
|
+
<li>
|
|
70
|
+
<a
|
|
71
|
+
class="jp-dashboard-footer__menu-item"
|
|
72
|
+
href="/"
|
|
73
|
+
role="button"
|
|
74
|
+
tabindex="0"
|
|
75
|
+
>
|
|
76
|
+
Button link
|
|
77
|
+
</a>
|
|
78
|
+
</li>
|
|
79
|
+
<li
|
|
80
|
+
class="jp-dashboard-footer__a8c-item"
|
|
81
|
+
>
|
|
82
|
+
<a
|
|
83
|
+
aria-label="An Automattic Airline"
|
|
84
|
+
href="https://automattic.com"
|
|
85
|
+
>
|
|
86
|
+
<svg
|
|
87
|
+
aria-hidden="true"
|
|
88
|
+
aria-labelledby="jp-automattic-byline-logo-title"
|
|
89
|
+
class="jp-automattic-byline-logo"
|
|
90
|
+
enable-background="new 0 0 935 38.2"
|
|
91
|
+
height="7"
|
|
92
|
+
role="img"
|
|
93
|
+
viewBox="0 0 935 38.2"
|
|
94
|
+
x="0"
|
|
95
|
+
y="0"
|
|
96
|
+
>
|
|
97
|
+
<desc
|
|
98
|
+
id="jp-automattic-byline-logo-title"
|
|
99
|
+
>
|
|
100
|
+
An Automattic Airline
|
|
101
|
+
</desc>
|
|
102
|
+
<path
|
|
103
|
+
d="M317.1 38.2c-12.6 0-20.7-9.1-20.7-18.5v-1.2c0-9.6 8.2-18.5 20.7-18.5 12.6 0 20.8 8.9 20.8 18.5v1.2C337.9 29.1 329.7 38.2 317.1 38.2zM331.2 18.6c0-6.9-5-13-14.1-13s-14 6.1-14 13v0.9c0 6.9 5 13.1 14 13.1s14.1-6.2 14.1-13.1V18.6zM175 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7L157 1.3h5.5L182 36.8H175zM159.7 8.2L152 23.1h15.7L159.7 8.2zM212.4 38.2c-12.7 0-18.7-6.9-18.7-16.2V1.3h6.6v20.9c0 6.6 4.3 10.5 12.5 10.5 8.4 0 11.9-3.9 11.9-10.5V1.3h6.7V22C231.4 30.8 225.8 38.2 212.4 38.2zM268.6 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H268.6zM397.3 36.8V8.7l-1.8 3.1 -14.9 25h-3.3l-14.7-25 -1.8-3.1v28.1h-6.5V1.3h9.2l14 24.4 1.7 3 1.7-3 13.9-24.4h9.1v35.5H397.3zM454.4 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7l19.2-35.5h5.5l19.5 35.5H454.4zM439.1 8.2l-7.7 14.9h15.7L439.1 8.2zM488.4 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H488.4zM537.3 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H537.3zM569.3 36.8V4.6c2.7 0 3.7-1.4 3.7-3.4h2.8v35.5L569.3 36.8 569.3 36.8zM628 11.3c-3.2-2.9-7.9-5.7-14.2-5.7 -9.5 0-14.8 6.5-14.8 13.3v0.7c0 6.7 5.4 13 15.3 13 5.9 0 10.8-2.8 13.9-5.7l4 4.2c-3.9 3.8-10.5 7.1-18.3 7.1 -13.4 0-21.6-8.7-21.6-18.3v-1.2c0-9.6 8.9-18.7 21.9-18.7 7.5 0 14.3 3.1 18 7.1L628 11.3zM321.5 12.4c1.2 0.8 1.5 2.4 0.8 3.6l-6.1 9.4c-0.8 1.2-2.4 1.6-3.6 0.8l0 0c-1.2-0.8-1.5-2.4-0.8-3.6l6.1-9.4C318.7 11.9 320.3 11.6 321.5 12.4L321.5 12.4z"
|
|
104
|
+
/>
|
|
105
|
+
<path
|
|
106
|
+
d="M37.5 36.7l-4.7-8.9H11.7l-4.6 8.9H0L19.4 0.8H25l19.7 35.9H37.5zM22 7.8l-7.8 15.1h15.9L22 7.8zM82.8 36.7l-23.3-24 -2.3-2.5v26.6h-6.7v-36H57l22.6 24 2.3 2.6V0.8h6.7v35.9H82.8z"
|
|
107
|
+
/>
|
|
108
|
+
<path
|
|
109
|
+
d="M719.9 37l-4.8-8.9H694l-4.6 8.9h-7.1l19.5-36h5.6l19.8 36H719.9zM704.4 8l-7.8 15.1h15.9L704.4 8zM733 37V1h6.8v36H733zM781 37c-1.8 0-2.6-2.5-2.9-5.8l-0.2-3.7c-0.2-3.6-1.7-5.1-8.4-5.1h-12.8V37H750V1h19.6c10.8 0 15.7 4.3 15.7 9.9 0 3.9-2 7.7-9 9 7 0.5 8.5 3.7 8.6 7.9l0.1 3c0.1 2.5 0.5 4.3 2.2 6.1V37H781zM778.5 11.8c0-2.6-2.1-5.1-7.9-5.1h-13.8v10.8h14.4c5 0 7.3-2.4 7.3-5.2V11.8zM794.8 37V1h6.8v30.4h28.2V37H794.8zM836.7 37V1h6.8v36H836.7zM886.2 37l-23.4-24.1 -2.3-2.5V37h-6.8V1h6.5l22.7 24.1 2.3 2.6V1h6.8v36H886.2zM902.3 37V1H935v5.6h-26v9.2h20v5.5h-20v10.1h26V37H902.3z"
|
|
110
|
+
/>
|
|
111
|
+
</svg>
|
|
112
|
+
</a>
|
|
113
|
+
</li>
|
|
114
|
+
</ul>
|
|
115
|
+
</footer>
|
|
116
|
+
</div>
|
|
117
|
+
`;
|
|
@@ -1,45 +1,162 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
1
2
|
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
2
4
|
import JetpackFooter from '../index';
|
|
3
5
|
|
|
4
6
|
describe( 'JetpackFooter', () => {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
const className = 'sample-classname';
|
|
8
|
+
const moduleName = 'Test module';
|
|
9
|
+
const moduleNameHref = 'https://jetpack.com/path/to-some-page';
|
|
10
|
+
const a8cLogoHref = 'https://automattic.com';
|
|
8
11
|
|
|
9
|
-
describe( 'Render the
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
describe( 'Render the component', () => {
|
|
13
|
+
const menu = [
|
|
14
|
+
{
|
|
15
|
+
label: 'Link',
|
|
16
|
+
href: '/',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
label: 'External link',
|
|
20
|
+
href: '/',
|
|
21
|
+
target: '_blank',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: 'Button link',
|
|
25
|
+
href: '/',
|
|
26
|
+
role: 'button',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
it( 'should include a footer tag', () => {
|
|
31
|
+
render( <JetpackFooter /> );
|
|
32
|
+
|
|
33
|
+
const element = screen.getByRole( 'contentinfo', { name: 'Jetpack' } );
|
|
34
|
+
|
|
35
|
+
expect( element ).toBeInTheDocument();
|
|
14
36
|
} );
|
|
15
37
|
|
|
16
|
-
it( '
|
|
38
|
+
it( 'should apply the class name', () => {
|
|
39
|
+
render( <JetpackFooter className={ className } /> );
|
|
40
|
+
|
|
41
|
+
const element = screen.getByRole( 'contentinfo' );
|
|
42
|
+
|
|
43
|
+
expect( element ).toHaveClass( className );
|
|
44
|
+
} );
|
|
45
|
+
|
|
46
|
+
it( 'should render the Jetpack logo', () => {
|
|
17
47
|
render( <JetpackFooter /> );
|
|
18
48
|
|
|
19
|
-
|
|
49
|
+
const element = screen.getByLabelText( 'Jetpack' );
|
|
50
|
+
|
|
51
|
+
expect( element ).toBeInTheDocument();
|
|
52
|
+
} );
|
|
53
|
+
|
|
54
|
+
it( 'should render the module name as a link', () => {
|
|
55
|
+
render( <JetpackFooter moduleName={ moduleName } moduleNameHref={ moduleNameHref } /> );
|
|
56
|
+
|
|
57
|
+
const element = screen.getByText( moduleName );
|
|
58
|
+
|
|
59
|
+
expect( element ).toBeInTheDocument();
|
|
60
|
+
expect( element ).toBeInstanceOf( HTMLAnchorElement );
|
|
61
|
+
expect( element ).toHaveAttribute( 'href', moduleNameHref );
|
|
62
|
+
} );
|
|
63
|
+
|
|
64
|
+
it( 'should render the module name as regular text', () => {
|
|
65
|
+
render( <JetpackFooter moduleName={ moduleName } moduleNameHref={ null } /> );
|
|
66
|
+
|
|
67
|
+
const element = screen.getByText( moduleName );
|
|
68
|
+
|
|
69
|
+
expect( element ).toBeInTheDocument();
|
|
70
|
+
expect( element ).not.toBeInstanceOf( HTMLAnchorElement );
|
|
71
|
+
} );
|
|
72
|
+
|
|
73
|
+
it( 'should render the Automattic logo', () => {
|
|
74
|
+
render( <JetpackFooter a8cLogoHref={ a8cLogoHref } /> );
|
|
75
|
+
|
|
76
|
+
const element = screen.getByLabelText( 'An Automattic Airline', { selector: 'a' } );
|
|
77
|
+
|
|
78
|
+
expect( element ).toBeInTheDocument();
|
|
79
|
+
expect( element ).toHaveAttribute( 'href', a8cLogoHref );
|
|
80
|
+
} );
|
|
81
|
+
|
|
82
|
+
it( 'should render a list', () => {
|
|
83
|
+
render( <JetpackFooter menu={ menu } /> );
|
|
84
|
+
|
|
85
|
+
const element = screen.getByRole( 'list' );
|
|
86
|
+
|
|
87
|
+
expect( element ).toBeInTheDocument();
|
|
88
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
89
|
+
expect( element.children ).toHaveLength( 2 + menu.length );
|
|
90
|
+
} );
|
|
91
|
+
|
|
92
|
+
it( 'should render the links', () => {
|
|
93
|
+
render( <JetpackFooter menu={ menu } /> );
|
|
94
|
+
|
|
95
|
+
const link = screen.getByRole( 'link', { name: menu[ 0 ].label } );
|
|
96
|
+
const externalLink = screen.getByRole( 'link', { name: menu[ 1 ].label } );
|
|
97
|
+
const button = screen.getByRole( 'button', { name: menu[ 2 ].label } );
|
|
98
|
+
|
|
99
|
+
expect( link ).toBeInTheDocument();
|
|
100
|
+
|
|
101
|
+
expect( externalLink ).toBeInTheDocument();
|
|
102
|
+
expect( externalLink ).toHaveAttribute( 'target', '_blank' );
|
|
103
|
+
expect( externalLink ).toHaveAttribute( 'rel', 'noopener noreferrer' );
|
|
104
|
+
expect( externalLink ).toContainHTML( 'svg' );
|
|
105
|
+
|
|
106
|
+
expect( button ).toBeInTheDocument();
|
|
107
|
+
expect( button ).toHaveAttribute( 'tabindex', '0' );
|
|
20
108
|
} );
|
|
21
109
|
|
|
22
|
-
it( '
|
|
23
|
-
render(
|
|
110
|
+
it( 'should match the snapshot', () => {
|
|
111
|
+
const { container } = render(
|
|
24
112
|
<JetpackFooter
|
|
25
|
-
|
|
26
|
-
|
|
113
|
+
className={ className }
|
|
114
|
+
moduleName={ moduleName }
|
|
115
|
+
moduleNameHref={ moduleNameHref }
|
|
116
|
+
a8cLogoHref={ a8cLogoHref }
|
|
117
|
+
menu={ menu }
|
|
27
118
|
/>
|
|
28
119
|
);
|
|
120
|
+
expect( container ).toMatchSnapshot( 'all props' );
|
|
121
|
+
} );
|
|
122
|
+
} );
|
|
29
123
|
|
|
30
|
-
|
|
124
|
+
describe( 'Fire events', () => {
|
|
125
|
+
const onClick = jest.fn();
|
|
126
|
+
const onKeyDown = jest.fn();
|
|
127
|
+
const menu = [
|
|
128
|
+
{
|
|
129
|
+
label: 'Link',
|
|
130
|
+
href: '/',
|
|
131
|
+
onClick,
|
|
132
|
+
onKeyDown,
|
|
133
|
+
},
|
|
134
|
+
];
|
|
31
135
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
136
|
+
it( 'should call the menu item onClick function', async () => {
|
|
137
|
+
const user = userEvent.setup();
|
|
138
|
+
|
|
139
|
+
render( <JetpackFooter menu={ menu } /> );
|
|
140
|
+
|
|
141
|
+
const element = screen.getByRole( 'link', { name: menu[ 0 ].label } );
|
|
142
|
+
|
|
143
|
+
await user.click( element );
|
|
144
|
+
|
|
145
|
+
expect( onClick ).toHaveBeenCalled();
|
|
35
146
|
} );
|
|
36
147
|
|
|
37
|
-
it( '
|
|
38
|
-
|
|
148
|
+
it( 'should call the menu item onKeyDown function', async () => {
|
|
149
|
+
const user = userEvent.setup();
|
|
150
|
+
|
|
151
|
+
render( <JetpackFooter menu={ menu } /> );
|
|
152
|
+
|
|
153
|
+
const element = screen.getByRole( 'link', { name: menu[ 0 ].label } );
|
|
154
|
+
|
|
155
|
+
// Need to focus on element first
|
|
156
|
+
await user.click( element );
|
|
157
|
+
await user.keyboard( '[Enter]' );
|
|
39
158
|
|
|
40
|
-
|
|
41
|
-
expect( element ).toBeInTheDocument();
|
|
42
|
-
}
|
|
159
|
+
expect( onKeyDown ).toHaveBeenCalled();
|
|
43
160
|
} );
|
|
44
161
|
} );
|
|
45
162
|
} );
|
|
@@ -21,6 +21,14 @@ import { Container, Col, Text } from '@automattic/jetpack-components';
|
|
|
21
21
|
|
|
22
22
|
## Props
|
|
23
23
|
|
|
24
|
+
### tagName
|
|
25
|
+
|
|
26
|
+
The HTML tag of the column element.
|
|
27
|
+
|
|
28
|
+
- Type: `String`
|
|
29
|
+
- Default: `div`
|
|
30
|
+
- Required: `false`
|
|
31
|
+
|
|
24
32
|
### className
|
|
25
33
|
|
|
26
34
|
A custom class to append with the default ones.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import classnames from 'classnames';
|
|
2
|
+
import { createElement } from 'react';
|
|
2
3
|
import { ColProps } from '../types';
|
|
3
4
|
import styles from './style.module.scss';
|
|
4
5
|
import type React from 'react';
|
|
@@ -14,7 +15,7 @@ const lgCols = Number( styles.lgCols );
|
|
|
14
15
|
* @returns {React.ReactElement} Col component.
|
|
15
16
|
*/
|
|
16
17
|
const Col: React.FC< ColProps > = props => {
|
|
17
|
-
const { children, className } = props;
|
|
18
|
+
const { children, tagName = 'div', className } = props;
|
|
18
19
|
|
|
19
20
|
const sm = Math.min( smCols, typeof props.sm === 'number' ? props.sm : smCols ); // max of 4, if undefined = 4
|
|
20
21
|
const smStart = Math.min( smCols, typeof props.sm === 'object' ? props.sm.start : 0 ); // max of 4, if undefined = 0
|
|
@@ -43,7 +44,13 @@ const Col: React.FC< ColProps > = props => {
|
|
|
43
44
|
[ styles[ `col-lg-${ lgEnd }-end` ] ]: lgEnd > 0,
|
|
44
45
|
} );
|
|
45
46
|
|
|
46
|
-
return
|
|
47
|
+
return createElement(
|
|
48
|
+
tagName,
|
|
49
|
+
{
|
|
50
|
+
className: colClassName,
|
|
51
|
+
},
|
|
52
|
+
children
|
|
53
|
+
);
|
|
47
54
|
};
|
|
48
55
|
|
|
49
56
|
export default Col;
|
|
@@ -20,6 +20,14 @@ import { Container, Col, Button } from '@automattic/jetpack-components';
|
|
|
20
20
|
|
|
21
21
|
## Props
|
|
22
22
|
|
|
23
|
+
### tagName
|
|
24
|
+
|
|
25
|
+
The HTML tag of the container.
|
|
26
|
+
|
|
27
|
+
- Type: `String`
|
|
28
|
+
- Default: `div`
|
|
29
|
+
- Required: `false`
|
|
30
|
+
|
|
23
31
|
### className
|
|
24
32
|
|
|
25
33
|
A custom class to append with the default ones.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
|
-
import { useMemo } from 'react';
|
|
2
|
+
import { createElement, useMemo } from 'react';
|
|
3
3
|
import { ContainerProps } from '../types';
|
|
4
4
|
import styles from './style.module.scss';
|
|
5
5
|
import type React from 'react';
|
|
@@ -13,6 +13,7 @@ import type React from 'react';
|
|
|
13
13
|
const Container: React.FC< ContainerProps > = ( {
|
|
14
14
|
children,
|
|
15
15
|
fluid = false,
|
|
16
|
+
tagName = 'div',
|
|
16
17
|
className,
|
|
17
18
|
horizontalGap = 1,
|
|
18
19
|
horizontalSpacing = 1,
|
|
@@ -32,10 +33,13 @@ const Container: React.FC< ContainerProps > = ( {
|
|
|
32
33
|
[ styles.fluid ]: fluid,
|
|
33
34
|
} );
|
|
34
35
|
|
|
35
|
-
return (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
return createElement(
|
|
37
|
+
tagName,
|
|
38
|
+
{
|
|
39
|
+
className: containerClassName,
|
|
40
|
+
style: containerStyle,
|
|
41
|
+
},
|
|
42
|
+
children
|
|
39
43
|
);
|
|
40
44
|
};
|
|
41
45
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
type ColSpan = number | { start: number; end: number };
|
|
2
2
|
|
|
3
3
|
export type ColProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Tag name of the column element.
|
|
6
|
+
*/
|
|
7
|
+
tagName?: string;
|
|
8
|
+
|
|
4
9
|
/**
|
|
5
10
|
* Custom className to be inserted.
|
|
6
11
|
*/
|
|
@@ -28,6 +33,11 @@ export type ColProps = {
|
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
export type ContainerProps = {
|
|
36
|
+
/**
|
|
37
|
+
* Tag name of the container.
|
|
38
|
+
*/
|
|
39
|
+
tagName?: string;
|
|
40
|
+
|
|
31
41
|
/**
|
|
32
42
|
* Make container not having a max width.
|
|
33
43
|
*/
|
|
@@ -22,7 +22,27 @@ const PricingSlider: React.FC< PricingSliderProps > = ( {
|
|
|
22
22
|
onAfterChange,
|
|
23
23
|
renderThumb,
|
|
24
24
|
} ) => {
|
|
25
|
-
const
|
|
25
|
+
const [ isThumbHolding, setIsThumbHolding ] = React.useState( false );
|
|
26
|
+
|
|
27
|
+
const componentClassName = classNames( 'jp-components-pricing-slider', className, {
|
|
28
|
+
'jp-components-pricing-slider--is-holding': isThumbHolding,
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
const onBeforeChangeCallback = beforeValue => {
|
|
32
|
+
setIsThumbHolding( true );
|
|
33
|
+
|
|
34
|
+
if ( typeof onBeforeChange === 'function' ) {
|
|
35
|
+
onBeforeChange( beforeValue );
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const onAfterChangeCallback = afterValue => {
|
|
40
|
+
setIsThumbHolding( false );
|
|
41
|
+
|
|
42
|
+
if ( typeof onAfterChange === 'function' ) {
|
|
43
|
+
onAfterChange( afterValue );
|
|
44
|
+
}
|
|
45
|
+
};
|
|
26
46
|
|
|
27
47
|
const renderThumbCallback = renderThumb
|
|
28
48
|
? renderThumb
|
|
@@ -43,8 +63,8 @@ const PricingSlider: React.FC< PricingSliderProps > = ( {
|
|
|
43
63
|
step={ step }
|
|
44
64
|
renderThumb={ renderThumbCallback } // eslint-disable-line react/jsx-no-bind
|
|
45
65
|
onChange={ onChange } // eslint-disable-line react/jsx-no-bind
|
|
46
|
-
onBeforeChange={
|
|
47
|
-
onAfterChange={
|
|
66
|
+
onBeforeChange={ onBeforeChangeCallback } // eslint-disable-line react/jsx-no-bind
|
|
67
|
+
onAfterChange={ onAfterChangeCallback } // eslint-disable-line react/jsx-no-bind
|
|
48
68
|
/>
|
|
49
69
|
</div>
|
|
50
70
|
);
|
|
@@ -8,6 +8,13 @@ $track-height: 8px;
|
|
|
8
8
|
border-radius: 8px; /* stylelint-disable-line scales/radii */
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
// On holding thumb styling
|
|
12
|
+
.jp-components-pricing-slider--is-holding {
|
|
13
|
+
.jp-components-pricing-slider__thumb {
|
|
14
|
+
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04), 0 0 0 3px rgba(6, 158, 8, 0.25);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
// Base styles
|
|
12
19
|
.jp-components-pricing-slider__control {
|
|
13
20
|
width: 100%;
|
|
@@ -35,8 +42,8 @@ $track-height: 8px;
|
|
|
35
42
|
padding: 8px 16px;
|
|
36
43
|
height: $thumb-height;
|
|
37
44
|
background-color: var(--jp-white);
|
|
38
|
-
border:
|
|
39
|
-
box-shadow: 0
|
|
45
|
+
border: 1.5px solid var(--jp-green-50);
|
|
46
|
+
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
40
47
|
border-radius: 4px;
|
|
41
48
|
color: var(--jp-black);
|
|
42
49
|
font-family: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif;
|
|
@@ -48,8 +55,12 @@ $track-height: 8px;
|
|
|
48
55
|
white-space: nowrap;
|
|
49
56
|
cursor: pointer;
|
|
50
57
|
|
|
58
|
+
// On focus thumb styling
|
|
51
59
|
&.jp-components-pricing-slider__thumb--is-active {
|
|
52
|
-
// On focus styling
|
|
53
60
|
outline: none;
|
|
54
61
|
}
|
|
62
|
+
|
|
63
|
+
&[aria-valuenow="0"] {
|
|
64
|
+
border-color: var(--jp-gray);
|
|
65
|
+
}
|
|
55
66
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/jetpack-components",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.1",
|
|
4
4
|
"description": "Jetpack Components Package",
|
|
5
5
|
"author": "Automattic",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -16,20 +16,20 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@automattic/format-currency": "1.0.1",
|
|
18
18
|
"@babel/runtime": "^7",
|
|
19
|
-
"@wordpress/browserslist-config": "5.
|
|
20
|
-
"@wordpress/components": "25.
|
|
21
|
-
"@wordpress/compose": "6.
|
|
22
|
-
"@wordpress/date": "4.
|
|
23
|
-
"@wordpress/element": "5.
|
|
24
|
-
"@wordpress/i18n": "4.
|
|
25
|
-
"@wordpress/icons": "9.
|
|
19
|
+
"@wordpress/browserslist-config": "5.19.0",
|
|
20
|
+
"@wordpress/components": "25.2.0",
|
|
21
|
+
"@wordpress/compose": "6.13.0",
|
|
22
|
+
"@wordpress/date": "4.36.0",
|
|
23
|
+
"@wordpress/element": "5.13.0",
|
|
24
|
+
"@wordpress/i18n": "4.36.0",
|
|
25
|
+
"@wordpress/icons": "9.27.0",
|
|
26
26
|
"classnames": "2.3.2",
|
|
27
27
|
"prop-types": "^15.7.2",
|
|
28
28
|
"qrcode.react": "3.1.0",
|
|
29
29
|
"react-slider": "2.0.5"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@automattic/jetpack-base-styles": "^0.6.
|
|
32
|
+
"@automattic/jetpack-base-styles": "^0.6.2",
|
|
33
33
|
"@babel/core": "7.21.5",
|
|
34
34
|
"@babel/preset-react": "7.18.6",
|
|
35
35
|
"@jest/globals": "29.4.3",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"@testing-library/user-event": "14.4.3",
|
|
42
42
|
"@types/jest": "29.2.5",
|
|
43
43
|
"@types/qrcode.react": "1.0.2",
|
|
44
|
-
"@types/react": "18.
|
|
45
|
-
"@types/react-dom": "18.
|
|
44
|
+
"@types/react": "18.2.14",
|
|
45
|
+
"@types/react-dom": "18.2.6",
|
|
46
46
|
"@types/react-slider": "1.3.1",
|
|
47
47
|
"@types/react-test-renderer": "18.0.0",
|
|
48
|
-
"@types/testing-library__jest-dom": "5.14.
|
|
48
|
+
"@types/testing-library__jest-dom": "5.14.6",
|
|
49
49
|
"jest": "29.4.3",
|
|
50
50
|
"jest-environment-jsdom": "29.4.3",
|
|
51
51
|
"react": "18.2.0",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"react-test-renderer": "18.2.0",
|
|
54
54
|
"require-from-string": "2.0.2",
|
|
55
55
|
"resize-observer-polyfill": "1.5.1",
|
|
56
|
+
"ts-dedent": "2.2.0",
|
|
56
57
|
"typescript": "5.0.4",
|
|
57
58
|
"webpack": "5.76.0",
|
|
58
59
|
"webpack-cli": "4.9.1"
|