@automattic/jetpack-components 0.39.0

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 (235) hide show
  1. package/.gitattributes +8 -0
  2. package/CHANGELOG.md +747 -0
  3. package/LICENSE.txt +357 -0
  4. package/README.md +11 -0
  5. package/SECURITY.md +38 -0
  6. package/components/action-button/index.jsx +70 -0
  7. package/components/action-button/stories/index.stories.jsx +38 -0
  8. package/components/action-button/style.module.scss +11 -0
  9. package/components/action-button/test/component.jsx +16 -0
  10. package/components/action-popover/index.tsx +105 -0
  11. package/components/action-popover/stories/index.stories.jsx +115 -0
  12. package/components/action-popover/stories/styles.module.scss +7 -0
  13. package/components/action-popover/styles.module.scss +49 -0
  14. package/components/action-popover/types.ts +20 -0
  15. package/components/admin-page/index.tsx +58 -0
  16. package/components/admin-page/stories/index.stories.tsx +35 -0
  17. package/components/admin-page/stories/style.module.scss +13 -0
  18. package/components/admin-page/style.module.scss +11 -0
  19. package/components/admin-page/types.ts +41 -0
  20. package/components/admin-section/basic/index.tsx +15 -0
  21. package/components/admin-section/basic/style.module.scss +3 -0
  22. package/components/admin-section/hero/index.tsx +15 -0
  23. package/components/admin-section/hero/style.module.scss +3 -0
  24. package/components/admin-section/stories/index.stories.tsx +60 -0
  25. package/components/admin-section/types.ts +6 -0
  26. package/components/alert/index.tsx +61 -0
  27. package/components/alert/stories/index.stories.jsx +24 -0
  28. package/components/alert/style.module.scss +43 -0
  29. package/components/automattic-byline-logo/README.md +16 -0
  30. package/components/automattic-byline-logo/index.tsx +38 -0
  31. package/components/automattic-byline-logo/stories/index.stories.tsx +20 -0
  32. package/components/automattic-byline-logo/test/component.tsx +28 -0
  33. package/components/automattic-byline-logo/types.ts +18 -0
  34. package/components/boost-score-bar/index.tsx +103 -0
  35. package/components/boost-score-bar/stories/index.stories.tsx +39 -0
  36. package/components/boost-score-bar/style.scss +184 -0
  37. package/components/boost-score-bar/test/component.tsx +102 -0
  38. package/components/boost-score-bar/types.ts +9 -0
  39. package/components/button/index.tsx +84 -0
  40. package/components/button/stories/index.mdx +90 -0
  41. package/components/button/stories/index.stories.tsx +400 -0
  42. package/components/button/stories/style.module.scss +20 -0
  43. package/components/button/style.module.scss +212 -0
  44. package/components/button/types.ts +21 -0
  45. package/components/contextual-upgrade-trigger/README.md +81 -0
  46. package/components/contextual-upgrade-trigger/index.tsx +44 -0
  47. package/components/contextual-upgrade-trigger/stories/index.stories.tsx +25 -0
  48. package/components/contextual-upgrade-trigger/style.module.scss +75 -0
  49. package/components/contextual-upgrade-trigger/types.ts +9 -0
  50. package/components/decorative-card/index.tsx +44 -0
  51. package/components/decorative-card/stories/index.stories.tsx +18 -0
  52. package/components/decorative-card/style.scss +116 -0
  53. package/components/decorative-card/types.ts +16 -0
  54. package/components/dialog/index.tsx +69 -0
  55. package/components/dialog/stories/boost.png +0 -0
  56. package/components/dialog/stories/declaration.d.ts +1 -0
  57. package/components/dialog/stories/index.stories.tsx +118 -0
  58. package/components/dialog/stories/js-components.components.dialog.mdx +62 -0
  59. package/components/dialog/stories/js-components.components.dialog.stories.js +37 -0
  60. package/components/dialog/stories/style.module.scss +21 -0
  61. package/components/dialog/style.module.scss +30 -0
  62. package/components/donut-meter/index.tsx +147 -0
  63. package/components/donut-meter/stories/index.stories.tsx +51 -0
  64. package/components/donut-meter/style.scss +11 -0
  65. package/components/donut-meter/test/component.tsx +24 -0
  66. package/components/gridicon/index.tsx +298 -0
  67. package/components/gridicon/stories/index.stories.tsx +18 -0
  68. package/components/gridicon/style.scss +16 -0
  69. package/components/gridicon/types.ts +48 -0
  70. package/components/icon-tooltip/index.tsx +96 -0
  71. package/components/icon-tooltip/stories/index.stories.tsx +108 -0
  72. package/components/icon-tooltip/stories/style.scss +36 -0
  73. package/components/icon-tooltip/style.scss +121 -0
  74. package/components/icon-tooltip/test/component.tsx +15 -0
  75. package/components/icon-tooltip/types.ts +76 -0
  76. package/components/icons/README.md +98 -0
  77. package/components/icons/index.tsx +369 -0
  78. package/components/icons/stories/index.stories.tsx +65 -0
  79. package/components/icons/stories/style.module.scss +33 -0
  80. package/components/icons/style.module.scss +40 -0
  81. package/components/icons/types.ts +38 -0
  82. package/components/indeterminate-progress-bar/index.tsx +28 -0
  83. package/components/indeterminate-progress-bar/stories/index.stories.tsx +14 -0
  84. package/components/indeterminate-progress-bar/style.module.scss +34 -0
  85. package/components/indeterminate-progress-bar/types.ts +6 -0
  86. package/components/jetpack-footer/README.md +21 -0
  87. package/components/jetpack-footer/index.tsx +94 -0
  88. package/components/jetpack-footer/stories/index.stories.tsx +40 -0
  89. package/components/jetpack-footer/style.scss +116 -0
  90. package/components/jetpack-footer/test/component.tsx +45 -0
  91. package/components/jetpack-footer/types.ts +36 -0
  92. package/components/jetpack-logo/README.md +20 -0
  93. package/components/jetpack-logo/index.tsx +46 -0
  94. package/components/jetpack-logo/stories/index.stories.tsx +20 -0
  95. package/components/jetpack-logo/test/component.tsx +16 -0
  96. package/components/jetpack-logo/types.ts +7 -0
  97. package/components/jetpack-search-logo/README.md +20 -0
  98. package/components/jetpack-search-logo/index.tsx +93 -0
  99. package/components/jetpack-search-logo/stories/index.stories.tsx +21 -0
  100. package/components/jetpack-search-logo/test/component.tsx +16 -0
  101. package/components/jetpack-search-logo/types.ts +7 -0
  102. package/components/jetpack-vaultpress-backup-logo/README.md +19 -0
  103. package/components/jetpack-vaultpress-backup-logo/index.tsx +113 -0
  104. package/components/jetpack-vaultpress-backup-logo/stories/index.stories.tsx +20 -0
  105. package/components/jetpack-vaultpress-backup-logo/test/component.tsx +18 -0
  106. package/components/jetpack-vaultpress-backup-logo/types.ts +6 -0
  107. package/components/jetpack-videopress-logo/README.md +19 -0
  108. package/components/jetpack-videopress-logo/index.tsx +93 -0
  109. package/components/jetpack-videopress-logo/stories/index.stories.tsx +20 -0
  110. package/components/jetpack-videopress-logo/test/component.tsx +16 -0
  111. package/components/jetpack-videopress-logo/types.tsx +6 -0
  112. package/components/layout/README.md +9 -0
  113. package/components/layout/breakpoints.module.scss +20 -0
  114. package/components/layout/col/README.md +81 -0
  115. package/components/layout/col/index.tsx +49 -0
  116. package/components/layout/col/style.module.scss +28 -0
  117. package/components/layout/container/README.md +77 -0
  118. package/components/layout/container/index.tsx +42 -0
  119. package/components/layout/container/style.module.scss +35 -0
  120. package/components/layout/stories/index.stories.tsx +145 -0
  121. package/components/layout/stories/styles.module.scss +22 -0
  122. package/components/layout/types.ts +55 -0
  123. package/components/layout/use-breakpoint-match/README.md +43 -0
  124. package/components/layout/use-breakpoint-match/declaration.d.ts +9 -0
  125. package/components/layout/use-breakpoint-match/index.ts +79 -0
  126. package/components/loading-placeholder/README.md +22 -0
  127. package/components/loading-placeholder/index.tsx +23 -0
  128. package/components/loading-placeholder/stories/index.stories.tsx +78 -0
  129. package/components/loading-placeholder/style.module.scss +18 -0
  130. package/components/notice/index.tsx +98 -0
  131. package/components/notice/stories/index.stories.jsx +90 -0
  132. package/components/notice/style.module.scss +107 -0
  133. package/components/number-format/README.md +25 -0
  134. package/components/number-format/index.ts +16 -0
  135. package/components/pricing-card/index.tsx +127 -0
  136. package/components/pricing-card/stories/index.stories.tsx +55 -0
  137. package/components/pricing-card/style.scss +112 -0
  138. package/components/pricing-card/test/component.tsx +89 -0
  139. package/components/pricing-card/types.ts +52 -0
  140. package/components/pricing-slider/index.tsx +53 -0
  141. package/components/pricing-slider/stories/index.stories.tsx +44 -0
  142. package/components/pricing-slider/style.scss +55 -0
  143. package/components/pricing-slider/test/component.tsx +14 -0
  144. package/components/pricing-slider/types.ts +58 -0
  145. package/components/pricing-table/index.tsx +200 -0
  146. package/components/pricing-table/stories/index.stories.tsx +74 -0
  147. package/components/pricing-table/styles.module.scss +160 -0
  148. package/components/pricing-table/test/component.tsx +41 -0
  149. package/components/pricing-table/types.ts +84 -0
  150. package/components/product-offer/icons-card.tsx +47 -0
  151. package/components/product-offer/index.tsx +115 -0
  152. package/components/product-offer/product-offer-header.tsx +23 -0
  153. package/components/product-offer/stories/index.stories.tsx +104 -0
  154. package/components/product-offer/style.module.scss +93 -0
  155. package/components/product-offer/types.ts +125 -0
  156. package/components/product-price/index.tsx +90 -0
  157. package/components/product-price/price.tsx +35 -0
  158. package/components/product-price/stories/index.stories.tsx +33 -0
  159. package/components/product-price/style.module.scss +69 -0
  160. package/components/product-price/test/component.tsx +26 -0
  161. package/components/product-price/types.ts +73 -0
  162. package/components/qr-code/Readme.md +5 -0
  163. package/components/qr-code/index.tsx +78 -0
  164. package/components/qr-code/stories/index.stories.tsx +32 -0
  165. package/components/record-meter-bar/index.tsx +135 -0
  166. package/components/record-meter-bar/stories/index.stories.tsx +39 -0
  167. package/components/record-meter-bar/style.scss +38 -0
  168. package/components/record-meter-bar/test/component.tsx +52 -0
  169. package/components/spinner/README.md +28 -0
  170. package/components/spinner/index.jsx +45 -0
  171. package/components/spinner/stories/index.stories.jsx +20 -0
  172. package/components/spinner/style.scss +31 -0
  173. package/components/spinner/test/component.jsx +17 -0
  174. package/components/split-button/index.tsx +39 -0
  175. package/components/split-button/stories/index.stories.tsx +35 -0
  176. package/components/split-button/style.module.scss +21 -0
  177. package/components/split-button/types.ts +14 -0
  178. package/components/stat-card/index.tsx +49 -0
  179. package/components/stat-card/stories/index.mdx +35 -0
  180. package/components/stat-card/stories/index.stories.tsx +41 -0
  181. package/components/stat-card/style.module.scss +49 -0
  182. package/components/stat-card/test/component.tsx +24 -0
  183. package/components/stat-card/types.ts +28 -0
  184. package/components/status/README.md +42 -0
  185. package/components/status/index.tsx +40 -0
  186. package/components/status/stories/index.stories.tsx +44 -0
  187. package/components/status/style.module.scss +72 -0
  188. package/components/terms-of-service/index.tsx +63 -0
  189. package/components/terms-of-service/styles.scss +10 -0
  190. package/components/terms-of-service/test/index.test.jsx +52 -0
  191. package/components/terms-of-service/types.ts +30 -0
  192. package/components/testimonials/index.tsx +58 -0
  193. package/components/testimonials/style.scss +127 -0
  194. package/components/testimonials/test/component.tsx +103 -0
  195. package/components/testimonials/testimonial.tsx +47 -0
  196. package/components/testimonials/types.ts +17 -0
  197. package/components/text/constants.ts +30 -0
  198. package/components/text/index.tsx +91 -0
  199. package/components/text/stories/headings.index.stories.tsx +80 -0
  200. package/components/text/stories/index.mdx +195 -0
  201. package/components/text/stories/index.stories.tsx +69 -0
  202. package/components/text/stories/style.module.scss +64 -0
  203. package/components/text/stories/title.index.stories.tsx +34 -0
  204. package/components/text/style.module.scss +125 -0
  205. package/components/text/types.ts +53 -0
  206. package/components/theme-provider/Readme.md +49 -0
  207. package/components/theme-provider/globals.module.scss +6 -0
  208. package/components/theme-provider/index.tsx +151 -0
  209. package/components/theme-provider/stories/index.stories.tsx +164 -0
  210. package/components/theme-provider/stories/style.module.scss +79 -0
  211. package/components/theme-provider/types.ts +25 -0
  212. package/components/toggle-control/README.md +5 -0
  213. package/components/toggle-control/index.tsx +67 -0
  214. package/components/toggle-control/stories/index.stories.tsx +83 -0
  215. package/components/toggle-control/styles.module.scss +41 -0
  216. package/components/zendesk-chat/README.md +26 -0
  217. package/components/zendesk-chat/constants.ts +2 -0
  218. package/components/zendesk-chat/index.tsx +22 -0
  219. package/components/zendesk-chat/stories/index.stories.tsx +15 -0
  220. package/components/zendesk-chat/test/component.tsx +16 -0
  221. package/components/zendesk-chat/types.ts +3 -0
  222. package/index.ts +69 -0
  223. package/lib/locale/index.ts +48 -0
  224. package/lib/locale/test/index.ts +21 -0
  225. package/package.json +80 -0
  226. package/tools/get-product-checkout-url/Readme.md +32 -0
  227. package/tools/get-product-checkout-url/index.ts +31 -0
  228. package/tools/jp-redirect/README.md +61 -0
  229. package/tools/jp-redirect/index.ts +62 -0
  230. package/tools/jp-redirect/test/index.tsx +89 -0
  231. package/tools/jp-redirect/types.ts +49 -0
  232. package/tools/pricing-utils/README.md +16 -0
  233. package/tools/pricing-utils/index.ts +11 -0
  234. package/tools/pricing-utils/test/index.ts +39 -0
  235. package/tools/pricing-utils/types.ts +12 -0
@@ -0,0 +1,81 @@
1
+ # Contextual Upgrade Trigger
2
+
3
+ The CUT component is designed to push users to upgrade from a Free plan to a Paid one, or from lower tier paid plans to higher ones.
4
+
5
+ **Design Specs for Contextual Upgrade Trigger:** PbJqbW-5k-p2
6
+
7
+ [ Storybook Reference ](https://automattic.github.io/jetpack-storybook/?path=/story/js-packages-components-contextual-upgrade-trigger--default)
8
+
9
+ ## Usage
10
+
11
+ ```jsx
12
+ import { ContextualUpgradeTrigger } from '@automattic/jetpack-components';
13
+
14
+ <ContextualUpgradeTrigger
15
+ description="Current status of the product"
16
+ cta="Text action line, recommending the next tier"
17
+ onClick={ () => ... }
18
+ />
19
+ ```
20
+
21
+ To use as a link:
22
+
23
+ ```jsx
24
+ import { ContextualUpgradeTrigger } from '@automattic/jetpack-components';
25
+
26
+ <ContextualUpgradeTrigger
27
+ description="Current status of the product"
28
+ cta="Text action line, recommending the next tier"
29
+ href="https://jetpack.com"
30
+ />
31
+ ```
32
+
33
+ ## Props
34
+
35
+ ### className
36
+
37
+ A custom class to append with the default ones.
38
+
39
+ - Type: `String`
40
+ - Default: `undefined`
41
+ - Required: `false`
42
+
43
+ ### description
44
+
45
+ A text giving context for a user about the current status of the product (i.e., how many updates per day).
46
+
47
+ - Type: `String`
48
+ - Default: `""`
49
+ - Required: `true`
50
+
51
+ ### cta
52
+
53
+ Text action line, recommending the next tier
54
+
55
+ - Type: `String`
56
+ - Default: `""`
57
+ - Required: `true`
58
+
59
+ ### onClick
60
+
61
+ Callback that will be called when the user click/tap into the CUT
62
+
63
+ - Type: `Function`
64
+ - Default: `undefined`
65
+ - Required: `false`
66
+
67
+ ### href
68
+
69
+ URL to link to
70
+
71
+ - Type: `String`
72
+ - Default: `undefined`
73
+ - Required: `false`
74
+
75
+ ### openInNewTab
76
+
77
+ Indicate if the link should open in a new tab
78
+
79
+ - Type: `Boolean`
80
+ - Default: `false`
81
+ - Required: `false`
@@ -0,0 +1,44 @@
1
+ import { Icon, arrowRight } from '@wordpress/icons';
2
+ import classnames from 'classnames';
3
+ import IconTooltip from '../icon-tooltip';
4
+ import Text from '../text';
5
+ import styles from './style.module.scss';
6
+ import { CutBaseProps } from './types';
7
+ import type React from 'react';
8
+
9
+ const ContextualUpgradeTrigger: React.FC< CutBaseProps > = ( {
10
+ description,
11
+ cta,
12
+ onClick,
13
+ href,
14
+ openInNewTab = false,
15
+ className,
16
+ tooltipText = '',
17
+ } ) => {
18
+ const Tag = href !== undefined ? 'a' : 'button';
19
+ const tagProps =
20
+ Tag === 'a' ? { href, ...( openInNewTab && { target: '_blank' } ) } : { onClick };
21
+
22
+ return (
23
+ <div className={ classnames( styles.cut, className ) }>
24
+ <div>
25
+ <div>
26
+ <Text className={ styles.description }>{ description }</Text>
27
+ { tooltipText && (
28
+ <IconTooltip className={ styles.iconContainer } iconSize={ 16 } offset={ 4 }>
29
+ <Text variant="body-small">{ tooltipText }</Text>
30
+ </IconTooltip>
31
+ ) }
32
+ </div>
33
+ <div>
34
+ <Tag { ...tagProps }>
35
+ <Text className={ styles.cta }>{ cta }</Text>
36
+ </Tag>
37
+ </div>
38
+ </div>
39
+ <Icon icon={ arrowRight } className={ styles.icon } size={ 30 } />
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export default ContextualUpgradeTrigger;
@@ -0,0 +1,25 @@
1
+ import { action } from '@storybook/addon-actions';
2
+ import ContextualUpgradeTrigger from '../index';
3
+
4
+ export default {
5
+ title: 'JS Packages/Components/Contextual Upgrade Trigger',
6
+ component: ContextualUpgradeTrigger,
7
+ };
8
+
9
+ const Template = args => <ContextualUpgradeTrigger { ...args } />;
10
+
11
+ const DefaultArgs = {
12
+ description: 'Current status of the product (i.e. how many updates per day)',
13
+ cta: 'Text action line, recommending the next tier',
14
+ onClick: action( 'onClick' ),
15
+ };
16
+
17
+ export const Default = Template.bind( {} );
18
+ Default.args = DefaultArgs;
19
+
20
+ export const Link = Template.bind( {} );
21
+ Link.args = {
22
+ ...DefaultArgs,
23
+ onClick: null,
24
+ href: 'https://jetpack.com',
25
+ };
@@ -0,0 +1,75 @@
1
+ .cut {
2
+ border: 2px solid var( --jp-green-40 );
3
+ border-radius: var( --jp-border-radius );
4
+ padding: calc( var( --spacing-base ) * 2 ) calc( var( --spacing-base ) * 3 );
5
+ display: flex;
6
+ justify-content: space-between;
7
+ align-items: center;
8
+ gap: calc( var( --spacing-base ) * 3 );
9
+ text-align: left;
10
+ background: none;
11
+ width: 100%;
12
+ position: relative;
13
+ color: var(--jp-gray-80);
14
+
15
+ button,
16
+ a {
17
+ all: unset;
18
+ color: var(--jp-gray-80);
19
+ cursor: pointer;
20
+
21
+ &::after {
22
+ content: '';
23
+ position: absolute;
24
+ top: 0;
25
+ left: 0;
26
+ width: 100%;
27
+ height: 100%;
28
+ }
29
+ }
30
+
31
+ &:focus-within {
32
+ border-color: var( --jp-black );
33
+ }
34
+
35
+ &:focus-within,
36
+ &:hover {
37
+ & .icon {
38
+ transform: translateX( calc( var( --spacing-base ) * 2 ) );
39
+ }
40
+
41
+ & .cta {
42
+ text-decoration: underline;
43
+ text-decoration-thickness: 2px;
44
+ }
45
+ }
46
+
47
+ // Overwrite styles in Text component
48
+ .cta {
49
+ font-weight: bold;
50
+ }
51
+ }
52
+
53
+ .cta {
54
+ font-weight: bold;
55
+ }
56
+
57
+ .icon {
58
+ fill: var( --jp-green-40 );
59
+ transition: transform 0.1s ease-out;
60
+ }
61
+
62
+ .iconContainer {
63
+ margin: 0 0 0 calc( var( --spacing-base ) / 3);
64
+ display: inline;
65
+ vertical-align: middle;
66
+
67
+ svg {
68
+ z-index: 10;
69
+ position: relative;
70
+ }
71
+ }
72
+
73
+ .description {
74
+ display: inline;
75
+ }
@@ -0,0 +1,9 @@
1
+ export type CutBaseProps = {
2
+ description: string;
3
+ cta: string;
4
+ className?: string;
5
+ href?: string;
6
+ openInNewTab?: boolean;
7
+ onClick?: () => void;
8
+ tooltipText?: string;
9
+ };
@@ -0,0 +1,44 @@
1
+ import type { DecorativeCardProps } from './types';
2
+ import type React from 'react';
3
+ import './style.scss';
4
+
5
+ /**
6
+ * A decorative card used in the disconnection flow.
7
+ *
8
+ * @param {DecorativeCardProps} props - The properties.
9
+ * @returns {React.ReactNode} - The DecorativeCard component.
10
+ */
11
+
12
+ const DecorativeCard: React.FC< DecorativeCardProps > = ( {
13
+ format = 'horizontal',
14
+ icon,
15
+ imageUrl,
16
+ } ) => {
17
+ return (
18
+ <div
19
+ className={
20
+ 'jp-components__decorative-card ' +
21
+ ( format ? 'jp-components__decorative-card--' + format : '' )
22
+ }
23
+ >
24
+ <div
25
+ className="jp-components__decorative-card__image"
26
+ style={ { backgroundImage: imageUrl ? `url( ${ imageUrl } )` : '' } }
27
+ ></div>
28
+ <div className="jp-components__decorative-card__content">
29
+ <div className="jp-components__decorative-card__lines"></div>
30
+ </div>
31
+ { icon ? (
32
+ <div className="jp-components__decorative-card__icon-container">
33
+ <span
34
+ className={
35
+ 'jp-components__decorative-card__icon jp-components__decorative-card__icon--' + icon
36
+ }
37
+ ></span>
38
+ </div>
39
+ ) : null }
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export default DecorativeCard;
@@ -0,0 +1,18 @@
1
+ import DecorativeCard from '../index';
2
+ import type { ComponentStory, ComponentMeta } from '@storybook/react';
3
+
4
+ export default {
5
+ title: 'JS Packages/Components/Decorative Card',
6
+ component: DecorativeCard,
7
+ } as ComponentMeta< typeof DecorativeCard >;
8
+
9
+ // Export additional stories using pre-defined values
10
+ const Template: ComponentStory< typeof DecorativeCard > = args => <DecorativeCard { ...args } />;
11
+
12
+ // Export Default story
13
+ export const _default = Template.bind( {} );
14
+
15
+ export const Unlink = Template.bind( {} );
16
+ Unlink.args = {
17
+ icon: 'unlink',
18
+ };
@@ -0,0 +1,116 @@
1
+ @import '@automattic/jetpack-base-styles/style';
2
+
3
+ .jp-components__decorative-card {
4
+ display: flex;
5
+ border-radius: 8px;
6
+ overflow: hidden;
7
+ box-shadow: 0 0 15px var( --jp-gray );
8
+ position: relative;
9
+ width: 360px;
10
+ max-width: 100%;
11
+ height: 280px;
12
+ margin: 0 auto;
13
+ margin-bottom: 3rem;
14
+
15
+ &__image,
16
+ &__content {
17
+ width: 50%;
18
+ }
19
+
20
+ &__image {
21
+ background: var( --jp-gray );
22
+ background-size: cover;
23
+ position: relative;
24
+
25
+ &:before {
26
+ content: '';
27
+ display: block;
28
+ position: absolute;
29
+ top: 24px;
30
+ left: 24px;
31
+ width: 38px;
32
+ height: 8px;
33
+ background-image: url('data:image/svg+xml;uf8,<svg width="38" height="8" viewBox="0 0 38 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 7C1 7 2.37087 1 6.89831 1C11.4257 1 14.3709 7 18.8983 7C23.4257 7 26.7777 1 31.3051 1C35.912 1 37 7 37 7" stroke="white" stroke-width="1.5" stroke-linejoin="round"/></svg>');
34
+ }
35
+ }
36
+
37
+ &__content {
38
+ background: #FFFFFF;
39
+ padding: 2rem;
40
+ }
41
+
42
+ &__icon-container {
43
+ position: absolute;
44
+ top: 50%;
45
+ left: 50%;
46
+ transform: translate(-50%, -50%);
47
+ width: 80px;
48
+ height: 80px;
49
+ background: var(--jp-red);
50
+ border-radius: 50px;
51
+ }
52
+
53
+ &__icon {
54
+ width: 40px;
55
+ height: 40px;
56
+ position: absolute;
57
+ top: 50%;
58
+ left: 50%;
59
+ transform: translate( -50%, -50% );
60
+ background-position: center, center;
61
+ background-repeat: no-repeat;
62
+
63
+ &--unlink {
64
+ background-image: url('data:image/svg+xml;uf8,<svg width="34" height="37" viewBox="0 0 34 37" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.3335 10.001H25.0002C29.4184 10.001 33.0002 13.5827 33.0002 18.001V19.7788C33.0002 24.197 29.4184 27.7788 25.0002 27.7788H22.3335" stroke="white" stroke-width="1.5" stroke-linecap="square"/> <path d="M11.6675 27.7783L9.00082 27.7783C4.58254 27.7783 1.00081 24.1966 1.00081 19.7783L1.00081 18.0005C1.00081 13.5823 4.58253 10.0005 9.00081 10.0005L11.6675 10.0005" stroke="white" stroke-width="1.5" stroke-linecap="square"/> <path d="M10.9998 19.167L16.9998 19.167" stroke="white" stroke-width="1.5"/> <path d="M8.99951 35.998L24.9995 0.998048" stroke="white"/> </svg>')
65
+ }
66
+ }
67
+
68
+ &__lines {
69
+ display: block;
70
+ width: 100%;
71
+ height: 12px;
72
+ border-radius: 6px;
73
+ background: #E9EFF5;
74
+ position: relative;
75
+
76
+ &::before,
77
+ &::after {
78
+ content: '';
79
+ display: block;
80
+ width: 100%;
81
+ height: 12px;
82
+ border-radius: 6px;
83
+ background: #E9EFF5;
84
+ position: relative;
85
+ top: calc(100% + 16px);
86
+ }
87
+
88
+ &:after {
89
+ top: calc(100% + 32px);
90
+ width: 75%;
91
+ }
92
+ }
93
+
94
+ // Variants
95
+ &--vertical {
96
+ flex-direction: column;
97
+
98
+ .jp-components__decorative-card__image,
99
+ .jp-components__decorative-card__content {
100
+ width: 100%;
101
+ height: 50%;
102
+ }
103
+
104
+ .jp-components__decorative-card__lines {
105
+ max-width: 135px;
106
+ margin-left: auto;
107
+ margin-right: auto;
108
+
109
+ &::before,
110
+ &::after {
111
+ margin-left: auto;
112
+ margin-right: auto;
113
+ }
114
+ }
115
+ }
116
+ }
@@ -0,0 +1,16 @@
1
+ export type DecorativeCardProps = {
2
+ /**
3
+ * The format of the card (horizontal or vertical)
4
+ */
5
+ format?: 'horizontal' | 'vertical';
6
+
7
+ /**
8
+ * An icon slug that can be used to show an icon (options are limited to what is in the stylesheet)
9
+ */
10
+ icon?: 'unlink';
11
+
12
+ /**
13
+ * URL for an image to show in the card.
14
+ */
15
+ imageUrl?: string;
16
+ };
@@ -0,0 +1,69 @@
1
+ import classnames from 'classnames';
2
+ import React from 'react';
3
+ import Col from '../layout/col';
4
+ import Container from '../layout/container';
5
+ import useBreakpointMatch from '../layout/use-breakpoint-match';
6
+ import styles from './style.module.scss';
7
+
8
+ type DialogProps = {
9
+ primary: React.ReactNode;
10
+ secondary?: React.ReactNode;
11
+ isTwoSections?: boolean;
12
+ isCard?: boolean;
13
+ containerProps: object;
14
+ };
15
+
16
+ /**
17
+ * Dialog component.
18
+ *
19
+ * @param {object} props - React component props.
20
+ * @param {React.ReactNode} props.primary - Primary-section content.
21
+ * @param {React.ReactNode} props.secondary - Secondary-section content.
22
+ * @param {boolean} props.isTwoSections - Handle two sections layout when true.
23
+ * @param {object} props.containerProps - Props to pass to the container component.
24
+ * @returns {React.ReactNode} Rendered dialog
25
+ */
26
+ const Dialog: React.FC< DialogProps > = ( {
27
+ primary,
28
+ secondary,
29
+ isTwoSections = false,
30
+ ...containerProps
31
+ } ) => {
32
+ const [ isSmall, isLowerThanLarge ] = useBreakpointMatch( [ 'sm', 'lg' ], [ null, '<' ] );
33
+
34
+ /*
35
+ * By convention, secondary section is not shown when:
36
+ * - layout is a two-sections setup
37
+ * - on mobile breakpoint (sm)
38
+ */
39
+ const hideSecondarySection = ! isTwoSections && isSmall;
40
+
41
+ const classNames = classnames( {
42
+ [ styles[ 'one-section-style' ] ]: ! isTwoSections,
43
+ [ styles[ 'is-viewport-small' ] ]: isSmall,
44
+ } );
45
+
46
+ return (
47
+ <Container
48
+ className={ classNames }
49
+ horizontalSpacing={ 0 }
50
+ horizontalGap={ 0 }
51
+ fluid={ false }
52
+ { ...containerProps }
53
+ >
54
+ { ! hideSecondarySection && (
55
+ <>
56
+ <Col sm={ 4 } md={ isLowerThanLarge ? 4 : 5 } lg={ 7 } className={ styles.primary }>
57
+ { primary }
58
+ </Col>
59
+ <Col sm={ 4 } md={ isLowerThanLarge ? 4 : 3 } lg={ 5 } className={ styles.secondary }>
60
+ { secondary }
61
+ </Col>
62
+ </>
63
+ ) }
64
+ { hideSecondarySection && <Col>{ primary }</Col> }
65
+ </Container>
66
+ );
67
+ };
68
+
69
+ export default Dialog;
@@ -0,0 +1 @@
1
+ declare module '*.png';
@@ -0,0 +1,118 @@
1
+ /* eslint-disable react/react-in-jsx-scope */
2
+ import React from 'react';
3
+ import Dialog from '..';
4
+ import ProductOffer from '../../product-offer';
5
+ import BoostImage from './boost.png';
6
+
7
+ export default {
8
+ title: 'JS Packages/Components/Dialog',
9
+ component: Dialog,
10
+ parameters: {
11
+ actions: { argTypesRegex: '^on.*' },
12
+ layout: 'centered',
13
+ },
14
+ argTypes: {
15
+ primary: {
16
+ table: {
17
+ disable: true,
18
+ },
19
+ },
20
+ secondary: {
21
+ table: {
22
+ disable: true,
23
+ },
24
+ },
25
+ isTwoSections: {
26
+ table: {
27
+ disable: true,
28
+ },
29
+ },
30
+ },
31
+ };
32
+
33
+ const Template = args => <Dialog { ...args } />;
34
+
35
+ export const JetpackBoost = Template.bind( {} );
36
+ JetpackBoost.parameters = {};
37
+ JetpackBoost.args = {
38
+ primary: (
39
+ <ProductOffer
40
+ slug="boost"
41
+ name="Boost"
42
+ title="Jepack Boost"
43
+ description="Jetpack Boost gives your site the same performance advantages as the world’s leading websites, no developer required."
44
+ features={ [
45
+ 'Check your site performance',
46
+ 'Enable improvements in one click',
47
+ 'Standalone free plugin for those focused on speed',
48
+ ] }
49
+ pricing={ {
50
+ isFree: true,
51
+ } }
52
+ className={ '' }
53
+ isCard={ false }
54
+ supportedProducts={ [] }
55
+ hasRequiredPlan={ false }
56
+ addProductUrl={ '' }
57
+ />
58
+ ),
59
+ secondary: <img src={ BoostImage } alt="Boost" />,
60
+ isTwoSections: false,
61
+ };
62
+
63
+ export const JetpackBackup = Template.bind( {} );
64
+ JetpackBackup.parameters = {};
65
+ JetpackBackup.args = {
66
+ primary: (
67
+ <ProductOffer
68
+ slug={ 'backup' }
69
+ name={ 'Backup' }
70
+ title={ 'Jepack Backup' }
71
+ description={
72
+ 'Never lose a word, image, page, or time worrying about your site with automated backups & one-click restores.'
73
+ }
74
+ features={ [
75
+ 'Real-time cloud backups',
76
+ '10GB of backup storage',
77
+ '30-day archive & activity log',
78
+ 'One-click restores',
79
+ ] }
80
+ pricing={ {
81
+ currency: 'USD',
82
+ price: 24.92,
83
+ offPrice: 12.42,
84
+ } }
85
+ isCard={ true }
86
+ className={ '' }
87
+ supportedProducts={ [] }
88
+ hasRequiredPlan={ false }
89
+ addProductUrl={ '' }
90
+ />
91
+ ),
92
+ secondary: (
93
+ <ProductOffer
94
+ name="Security"
95
+ title="Security"
96
+ description="Comprehensive site security, including Backup, Scan, and Anti-spam."
97
+ isBundle={ true }
98
+ supportedProducts={ [ 'backup', 'scan', 'anti-spam' ] }
99
+ features={ [
100
+ 'Real time cloud backups with 10GB storage',
101
+ 'Automated real-time malware scan',
102
+ 'One click fixes for most threats',
103
+ 'Comment & form spam protection',
104
+ ] }
105
+ pricing={ {
106
+ currency: 'USD',
107
+ price: 24.92,
108
+ offPrice: 12.42,
109
+ } }
110
+ hasRequiredPlan={ false }
111
+ isLoading={ false }
112
+ className={ '' }
113
+ isCard={ false }
114
+ addProductUrl={ '' }
115
+ />
116
+ ),
117
+ isTwoSections: true,
118
+ };
@@ -0,0 +1,62 @@
1
+ import { Meta, Source, Story } from '@storybook/blocks';
2
+ import dedent from 'ts-dedent';
3
+ import * as JsComponentsComponentsDialogStories from './js-components.components.dialog.stories';
4
+
5
+ <Meta of={JsComponentsComponentsDialogStories} />
6
+
7
+ # Dialog
8
+
9
+ Render a two-sections layout simple composition, built based on the primary <a href="?path=/docs/js-packages-components-layout--default">Layout component</a>.
10
+
11
+ <Source
12
+ language="jsx"
13
+ code={dedent`
14
+ import Dialog from '@automattic/jetpack-components';
15
+ // ...
16
+
17
+ <Dialog
18
+ primary={ <PrimaryComponent /> }
19
+ secondary={ <SecondaryComponent /> }
20
+ isTwoSections={ true }
21
+ />
22
+ `}
23
+ />
24
+
25
+ <Story of={JsComponentsComponentsDialogStories.Readme} />
26
+
27
+ The cols number for each section depends on the viewport width. The following table shows how they are defined:
28
+
29
+ &nbsp; | Small (sm) | Medium (md) | Large (lg)
30
+ ------|------|------|-----
31
+ primary | 4 | 5 | 7
32
+ secondary | 4 | 3 | 5
33
+
34
+ Finally, when the Dialog is defined as not a two-sections layout (<a href="#istwosections">isTwoSections property</a>), the secondary section won't show in Mobile (sm breakpoint).
35
+
36
+ ## API
37
+
38
+ The components accepts the following properties:
39
+
40
+ ### primary
41
+
42
+ * Type: `React.ReactNode`, `string`.
43
+
44
+ Primary-section content.
45
+
46
+ ### secondary
47
+
48
+ * Type: `React.ReactNode`, `string`.
49
+ * Optional.
50
+
51
+ Primary-section content.
52
+
53
+ ### isTwoSections
54
+
55
+ * Type: `boolean`.
56
+ * Optional.
57
+ * Default: `false`
58
+
59
+ It handles two sections layout:
60
+
61
+ * Add card styles to the main wrapper when it is not a two-sections layout.
62
+ * When it's false, the secondary section won't show in Mobile.