diff --git a/projects/js-packages/components/changelog/add-social-add-connection-modal b/projects/js-packages/components/changelog/add-social-add-connection-modal new file mode 100644 index 0000000000000..ca75984c66759 --- /dev/null +++ b/projects/js-packages/components/changelog/add-social-add-connection-modal @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Social: Added add connection modal diff --git a/projects/js-packages/components/components/icons/index.tsx b/projects/js-packages/components/components/icons/index.tsx index 748f13e6d4aa5..bed624ca12b1c 100644 --- a/projects/js-packages/components/components/icons/index.tsx +++ b/projects/js-packages/components/components/icons/index.tsx @@ -278,11 +278,13 @@ export function getIconBySlug< Slug extends IconSlug >( slug: Slug ): IconsMap[ export const SocialServiceIcon: React.FC< { serviceName: React.ComponentProps< typeof SocialLogo >[ 'icon' ]; className?: string; -} > = ( { serviceName, className } ) => { + iconSize?: number; +} > = ( { serviceName, className, iconSize } ) => { return ( ); }; diff --git a/projects/js-packages/publicize-components/changelog/add-social-add-connection-modal b/projects/js-packages/publicize-components/changelog/add-social-add-connection-modal new file mode 100644 index 0000000000000..ca75984c66759 --- /dev/null +++ b/projects/js-packages/publicize-components/changelog/add-social-add-connection-modal @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Social: Added add connection modal diff --git a/projects/js-packages/publicize-components/index.ts b/projects/js-packages/publicize-components/index.ts index 18d4c6eb130a7..e19797da1d221 100644 --- a/projects/js-packages/publicize-components/index.ts +++ b/projects/js-packages/publicize-components/index.ts @@ -18,6 +18,7 @@ export { default as ReviewPrompt } from './src/components/review-prompt'; export { default as PostPublishReviewPrompt } from './src/components/post-publish-review-prompt'; export { default as PostPublishManualSharing } from './src/components/post-publish-manual-sharing'; export { default as RefreshJetpackSocialSettingsWrapper } from './src/components/refresh-jetpack-social-settings'; +export { default as AddConnectionModal } from './src/components/add-connection-modal'; export { default as ConnectionManagement } from './src/components/connection-management'; export { default as useSocialMediaConnections } from './src/hooks/use-social-media-connections'; diff --git a/projects/js-packages/publicize-components/package.json b/projects/js-packages/publicize-components/package.json index ddd3e582f7258..ba5e622ec4be4 100644 --- a/projects/js-packages/publicize-components/package.json +++ b/projects/js-packages/publicize-components/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-publicize-components", - "version": "0.50.0", + "version": "0.51.0-alpha", "description": "A library of JS components required by the Publicize editor plugin", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/publicize-components/#readme", "bugs": { diff --git a/projects/js-packages/publicize-components/src/assets/connections-button-facebook.png b/projects/js-packages/publicize-components/src/assets/connections-button-facebook.png new file mode 100644 index 0000000000000..5882335ce7c49 Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-button-facebook.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-button-linkedin.png b/projects/js-packages/publicize-components/src/assets/connections-button-linkedin.png new file mode 100644 index 0000000000000..fbb02c632709f Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-button-linkedin.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-button-tumblr.png b/projects/js-packages/publicize-components/src/assets/connections-button-tumblr.png new file mode 100644 index 0000000000000..0029fb1ee3c28 Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-button-tumblr.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-facebook.png b/projects/js-packages/publicize-components/src/assets/connections-facebook.png new file mode 100644 index 0000000000000..de2e00744782d Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-facebook.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-instagram-business.png b/projects/js-packages/publicize-components/src/assets/connections-instagram-business.png new file mode 100644 index 0000000000000..f4dedd427391a Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-instagram-business.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-linkedin.png b/projects/js-packages/publicize-components/src/assets/connections-linkedin.png new file mode 100644 index 0000000000000..b7be697d0c9cb Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-linkedin.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-nextdoor.png b/projects/js-packages/publicize-components/src/assets/connections-nextdoor.png new file mode 100644 index 0000000000000..28e2903d40718 Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-nextdoor.png differ diff --git a/projects/js-packages/publicize-components/src/assets/connections-tumblr.png b/projects/js-packages/publicize-components/src/assets/connections-tumblr.png new file mode 100644 index 0000000000000..eb40c6a10cf5e Binary files /dev/null and b/projects/js-packages/publicize-components/src/assets/connections-tumblr.png differ diff --git a/projects/js-packages/publicize-components/src/assets/index.d.ts b/projects/js-packages/publicize-components/src/assets/index.d.ts new file mode 100644 index 0000000000000..e2937d470ee8a --- /dev/null +++ b/projects/js-packages/publicize-components/src/assets/index.d.ts @@ -0,0 +1 @@ +declare module '*.png'; diff --git a/projects/js-packages/publicize-components/src/components/add-connection-modal/connect-page/connect-page.tsx b/projects/js-packages/publicize-components/src/components/add-connection-modal/connect-page/connect-page.tsx new file mode 100644 index 0000000000000..0f22238f56a74 --- /dev/null +++ b/projects/js-packages/publicize-components/src/components/add-connection-modal/connect-page/connect-page.tsx @@ -0,0 +1,52 @@ +import { Button, useBreakpointMatch } from '@automattic/jetpack-components'; +import { __ } from '@wordpress/i18n'; +import classNames from 'classnames'; +import { Connection } from '../constants'; +import styles from './style.module.scss'; + +type ConnectPageProps = { + service: Connection; + onBackClicked: () => void; +}; + +export const ConnectPage: React.FC< ConnectPageProps > = ( { service, onBackClicked } ) => { + const [ isSmall ] = useBreakpointMatch( 'sm' ); + + return ( + <> +
+ { service.examples.map( ( Example, idx ) => ( +
+ +
+ ) ) } +
+
+ +
+ { 'mastodon' === service.name ? ( + + ) : null } + +
+
+ + ); +}; diff --git a/projects/js-packages/publicize-components/src/components/add-connection-modal/connect-page/style.module.scss b/projects/js-packages/publicize-components/src/components/add-connection-modal/connect-page/style.module.scss new file mode 100644 index 0000000000000..b07292d0e8970 --- /dev/null +++ b/projects/js-packages/publicize-components/src/components/add-connection-modal/connect-page/style.module.scss @@ -0,0 +1,53 @@ +.example-wrapper { + display: grid; + grid-auto-columns: minmax(0, 1fr); + grid-auto-flow: column; + font-size: 15px; + margin-top: 0.4rem; + min-height: 300px; + + &.small { + grid-auto-flow: row; + grid-gap: 2rem; + height: auto; + min-height: unset; + } + + img { + max-height: 520px; + max-width: 100%; + } + + > div { + padding: 0.4rem; + + &:has(img) { + margin-inline-start: auto; + margin-inline-end: auto; + } + } +} + +.actions-wrapper { + display: flex; + justify-content: space-between; + margin-top: 1rem; +} + +.chevron-back { + display: block; +} + +.connect-form { + display: grid; + gap: 0.5rem; + + & > input { + height: 100%; + width: 18rem; + } + + &:not(.small) { + grid-auto-flow: column; + } +} \ No newline at end of file diff --git a/projects/js-packages/publicize-components/src/components/add-connection-modal/constants.tsx b/projects/js-packages/publicize-components/src/components/add-connection-modal/constants.tsx new file mode 100644 index 0000000000000..d96490aa29840 --- /dev/null +++ b/projects/js-packages/publicize-components/src/components/add-connection-modal/constants.tsx @@ -0,0 +1,265 @@ +import { SocialServiceIcon } from '@automattic/jetpack-components'; +import { ExternalLink } from '@wordpress/components'; +import { createInterpolateElement } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import connectionsButtonFacebook from '../../assets/connections-button-facebook.png'; +import connectionsButtonLinkedin from '../../assets/connections-button-linkedin.png'; +import connectionsButtonTumblr from '../../assets/connections-button-tumblr.png'; +import connectionsFacebook from '../../assets/connections-facebook.png'; +import connectionsInstagramBusiness from '../../assets/connections-instagram-business.png'; +import connectionsLinkedin from '../../assets/connections-linkedin.png'; +import connectionsNextdoor from '../../assets/connections-nextdoor.png'; +import connectionsTumblr from '../../assets/connections-tumblr.png'; + +const sharingButtonLink = 'https://wordpress.com/support/sharing/'; + +export interface Connection { + title: string; + icon: React.ComponentType< { iconSize: number } >; + description: string; + name: string; + examples?: Array< React.ComponentType >; +} + +export const getSupportedConnections = (): Connection[] => { + return [ + { + title: __( 'Facebook', 'jetpack' ), + icon: props => , + description: __( + "Facebook's massive active user base makes for a great place to share your posts and connect with your followers.", + 'jetpack' + ), + name: 'facebook', + examples: [ + () => ( + <> + { +
+
+ { createInterpolateElement( + __( + 'Connect to automatically share posts on your Facebook page.', + 'jetpack' + ), + { strong: } + ) } + + ), + () => ( + <> + { +
+
+ { createInterpolateElement( + __( + 'Add a to your posts so readers can share your story with their friends.', + 'jetpack' + ), + { + strong: , + link: ( + + { __( 'sharing button', 'jetpack' ) } + + ), + } + ) } + + ), + ], + }, + { + title: __( 'Instagram Business', 'jetpack' ), + icon: props => , + description: __( + 'Share photos from your site to your Instagram Business account.', + 'jetpack' + ), + name: 'instagram', + examples: [ + () => ( + <> + { __( + 'Drive engagement and save time by automatically sharing images to Instagram when you publish blog posts.', + 'jetpack' + ) } +
+

{ __( 'Requirements for connecting Instagram:', 'jetpack' ) }

+
    +
  1. { __( 'You must have an Instagram Business account.', 'jetpack' ) }
  2. +
  3. + { __( + 'Your Instagram Business account must be linked to a Facebook page.', + 'jetpack' + ) } +
  4. +
+
+ { createInterpolateElement( + __( + "When you click “connect” you'll be asked to log into Facebook. If your Instagram Business account isn't listed, ensure it's linked to a Facebook page.", + 'jetpack' + ), + { strong: , i: } + ) } +
+
+ + { __( 'Learn how to convert & link your Instagram account.', 'jetpack' ) } + + + ), + () => ( + { + ), + ], + }, + { + title: __( 'LinkedIn', 'jetpack' ), + icon: props => , + description: __( + 'Reach a professional audience and contribute valuable content by sharing your posts with the LinkedIn community.', + 'jetpack' + ), + name: 'linkedin', + examples: [ + () => ( + <> + { +
+
+ { createInterpolateElement( + __( + 'Connect to automatically share posts with your LinkedIn connections.', + 'jetpack' + ), + { strong: } + ) } + + ), + () => ( + <> + { +
+
+ { createInterpolateElement( + __( + 'Add a to your posts so readers can share your story with their connections.', + 'jetpack' + ), + { + strong: , + link: ( + + { __( 'sharing button', 'jetpack' ) } + + ), + } + ) } + + ), + ], + }, + { + title: __( 'Nextdoor', 'jetpack' ), + icon: props => , + description: __( + 'Share your posts with your local community on Nextdoor, facilitating meaningful interactions and fostering a sense of belonging among neighbors.', + 'jetpack' + ), + name: 'nextdoor', + examples: [ + () => ( + <> + { createInterpolateElement( + __( + 'Connect with friends, neighbors, and local businesses by automatically sharing your posts to Nextdoor.', + 'jetpack' + ), + { strong: } + ) } + + ), + () => {, + ], + }, + { + title: __( 'Tumblr', 'jetpack' ), + icon: props => , + description: __( + 'Share posts on your Tumblr blog to expand your reach to a diverse younger audience in a fun and creative community.', + 'jetpack' + ), + name: 'tumblr', + examples: [ + () => ( + <> + { +
+
+ { createInterpolateElement( + __( + 'Connect to automatically share posts to your Tumblr blog.', + 'jetpack' + ), + { strong: } + ) } + + ), + () => ( + <> + { +
+
+ { createInterpolateElement( + __( + 'Add a to your posts so readers can share your story with their followers.', + 'jetpack' + ), + { + strong: , + link: ( + + { __( 'sharing button', 'jetpack' ) } + + ), + } + ) } + + ), + ], + }, + { + title: __( 'Mastodon', 'jetpack' ), + icon: props => , + description: __( + 'Share your posts to an open-source social network with a community that values privacy and freedom.', + 'jetpack' + ), + name: 'mastodon', + examples: [ + () => ( + <> + { __( + 'To share to Mastodon please enter your Mastodon username below, then click connect.', + 'jetpack' + ) } + + ), + ], + }, + ]; +}; diff --git a/projects/js-packages/publicize-components/src/components/add-connection-modal/index.tsx b/projects/js-packages/publicize-components/src/components/add-connection-modal/index.tsx new file mode 100644 index 0000000000000..95cdf4eb959d3 --- /dev/null +++ b/projects/js-packages/publicize-components/src/components/add-connection-modal/index.tsx @@ -0,0 +1,96 @@ +import { Button, useBreakpointMatch } from '@automattic/jetpack-components'; +import { Modal } from '@wordpress/components'; +import { __, sprintf } from '@wordpress/i18n'; +import { Icon, chevronDown } from '@wordpress/icons'; +import classNames from 'classnames'; +import { useCallback, useState } from 'react'; +import { ConnectPage } from './connect-page/connect-page'; +import { getSupportedConnections } from './constants'; +import styles from './style.module.scss'; + +const AddConnectionModal = ( { onCloseModal } ) => { + const [ currentService, setCurrentService ] = useState( null ); + + const [ isSmall ] = useBreakpointMatch( 'sm' ); + + const onServiceSelected = useCallback( + service => () => { + setCurrentService( service ); + }, + [] + ); + + const onBackClicked = useCallback( () => { + setCurrentService( null ); + }, [] ); + + return ( + + { currentService ? ( + + ) : ( + + + + + + + + + + { getSupportedConnections().map( service => ( + + + + + + ) ) } + +
+ + +

{ service.title }

+ { ! isSmall ? ( +

{ service.description }

+ ) : null } +
+
+ + +
+
+ ) } +
+ ); +}; + +export default AddConnectionModal; diff --git a/projects/js-packages/publicize-components/src/components/add-connection-modal/style.module.scss b/projects/js-packages/publicize-components/src/components/add-connection-modal/style.module.scss new file mode 100644 index 0000000000000..618bf32ed0382 --- /dev/null +++ b/projects/js-packages/publicize-components/src/components/add-connection-modal/style.module.scss @@ -0,0 +1,66 @@ +.modal { + width: 65rem; + &.service-selector { + min-height: 700px; + } + + &:not(.small) { + display: table; + } +} + +.title { + margin: 0; +} + +.description { + font-size: 15px; + margin-top: 0.7rem; + margin-bottom: 0; +} + +.chevron { + display: block; +} + +// Table padding +td { + padding-top: 0.8rem; + padding-bottom: 0.8rem; + + &:first-child { + padding-inline-start: 1rem; + padding-inline-end: 1rem; + } + + &:last-child { + padding-inline-end: 1rem; + } +} + +// Table border +table { + border-collapse: separate; + border-spacing: 0; + border-radius: 4px; + outline: 1px solid var(--jp-gray-5); +} + +tr:not(:last-child) > td { + border-bottom: solid 1px var(--jp-gray-5); +} + +.column-description { + padding-inline-end: 6rem; +} + +.column-actions { + display: grid; + grid-auto-flow: column; +} + +.chevron-button.chevron-button.chevron-button { + padding-inline-start: 0.5rem; + padding-inline-end: 0.5rem; + margin-inline-start: 0.4rem; +} diff --git a/projects/js-packages/publicize-components/src/components/connection-management/index.tsx b/projects/js-packages/publicize-components/src/components/connection-management/index.tsx index d5dc2974786ba..09ea84ae86516 100644 --- a/projects/js-packages/publicize-components/src/components/connection-management/index.tsx +++ b/projects/js-packages/publicize-components/src/components/connection-management/index.tsx @@ -4,9 +4,10 @@ import { ExternalLink } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import classNames from 'classnames'; -import { useCallback, useEffect } from 'react'; +import { useCallback, useEffect, useReducer } from 'react'; import useSocialMediaConnections from '../../hooks/use-social-media-connections'; import { store } from '../../social-store'; +import AddConnectionModal from '../add-connection-modal'; import ConnectionIcon from '../connection-icon'; import styles from './style.module.scss'; @@ -24,7 +25,7 @@ const ConnectionManagement = ( { className = null } ) => { return a.service_name.localeCompare( b.service_name ); } ); - // const [ isModalOpen, toggleModal ] = useReducer( state => ! state, false ); + const [ isModalOpen, toggleModal ] = useReducer( state => ! state, false ); useEffect( () => { refresh(); @@ -97,8 +98,10 @@ const ConnectionManagement = ( { className = null } ) => { ) : ( { __( 'There are no connections added yet.', 'jetpack' ) } ) } - - { /* { isModalOpen && } */ } + + { isModalOpen && } ); }; diff --git a/projects/plugins/jetpack/changelog/add-social-add-connection-modal b/projects/plugins/jetpack/changelog/add-social-add-connection-modal new file mode 100644 index 0000000000000..176d81a3d098e --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-social-add-connection-modal @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +Fixed TS compile error for image imports in js-packages diff --git a/projects/plugins/jetpack/global.d.ts b/projects/plugins/jetpack/global.d.ts new file mode 100644 index 0000000000000..e2937d470ee8a --- /dev/null +++ b/projects/plugins/jetpack/global.d.ts @@ -0,0 +1 @@ +declare module '*.png'; diff --git a/projects/plugins/jetpack/tsconfig.json b/projects/plugins/jetpack/tsconfig.json index 3f22d2bb0df11..cd68380ba4f61 100644 --- a/projects/plugins/jetpack/tsconfig.json +++ b/projects/plugins/jetpack/tsconfig.json @@ -7,7 +7,7 @@ "*": [ "*", "./_inc/client/*" ] } }, - "include": [ "./_inc", "./extensions" ], + "include": [ "./_inc", "./extensions", "./global.d.ts" ], // Jetpack puts build files into `_inc`, so we need exclude rules to skip those. "exclude": [ "**/build/*", "_inc/blocks/*" ] } diff --git a/projects/plugins/social/changelog/add-social-add-connection-modal b/projects/plugins/social/changelog/add-social-add-connection-modal new file mode 100644 index 0000000000000..ca75984c66759 --- /dev/null +++ b/projects/plugins/social/changelog/add-social-add-connection-modal @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Social: Added add connection modal