Social: modernize Add-account modal + connected-accounts onto WPDS (#48824 PR 2.5)#48833
Conversation
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! Jetpack plugin: The Jetpack plugin has different release cadences depending on the platform:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. Social plugin: No scheduled milestone found for this plugin. If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. |
Code Coverage SummaryCoverage changed in 5 files.
7 files are newly checked for coverage. Only the first 5 are listed here.
|
8713182 to
f6c81e3
Compare
6179a7a to
3e6290e
Compare
f6c81e3 to
7d0af04
Compare
3e6290e to
fe74066
Compare
8a66487 to
4e7d6d8
Compare
Round out PR 2's chassis Overview card and the legacy/chassis-shared
Add-account modal so they share one disclosure-row visual language:
- `ServiceItem` (modal) and `ConnectionInfo` (Overview) collapse onto a
single flat-row `Collapsible.Trigger` with a CSS-rotate chevron — each
list now lives inside a single `Card.Root` with edge-to-edge dividers
between rows. Inline Connect / Reconnect / Disconnect controls keep
their click handlers via a narrow `stopPropagation` wrapper.
- Custom Mastodon/Bluesky inputs swap raw `<input>`/`<label>` pairs for
`__experimentalInputControl`. Manage-modal footer text uses WPDS `Text`
with `body-sm`; the MarkAsShared info tooltip and the modal-context
one move from `IconTooltip` to WPDS `Tooltip` (z-index bumped above
the Modal portal so the popup is visible).
- `Tooltip.Provider delay={0}` mounted at the chassis page and the
modal so every info-icon tooltip in Social opens immediately.
- New `size="medium"` variant on `ConnectionIcon` (32×32 avatar +
16×16 service icon) for the chassis Overview rows; default `small`
preserves existing call sites.
- `Disconnect` button → `size="compact" tone="neutral"`; in-row Connect
button → `size="compact"` so it sits flush against the row height.
- Handle text drops to neutral foreground (`tone="neutral"` on
`<Link>`), 14px / 500 weight, with the network name beneath in
`--wpds-color-fg-content-neutral-weak`.
- SCSS pass replaces hard-coded gaps / paddings / focus widths with
`--wpds-dimension-*`, `--wpds-typography-*`, and
`--wpds-color-fg-content-neutral-weak` tokens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR 2.5's WPDS imports made the legacy `social-admin-page.js` bundle
unusable on WP < 7.0 in two ways:
- `@wordpress/ui` pulls `wp-theme` (and `wp-private-apis` / `wp-notices`)
through the dependency-extraction plugin. Those script handles ship
via `WP_Build_Polyfills` for the chassis but were never registered
on the legacy enqueue path, so WordPress silently dropped the
script on WP 6.9.4 and the page rendered blank. Now
`Social_Admin_Page::enqueue_admin_scripts()` calls
`WP_Build_Polyfills::register('jetpack-social', SCRIPT_HANDLES)`
with the same guard the chassis uses.
- `ConnectionInfo` and `ServiceConnectionInfo` now mount
`Tooltip.Root` from `@wordpress/ui` for the MarkAsShared info icon.
Without a `Tooltip.Provider` ancestor the primitive throws on mount
and crashes the legacy React tree. The chassis page and the modal
already provide one; this commit adds the same wrap at the legacy
entry point (`entry-points/social-admin-page.tsx`).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| .chevron { | ||
| color: var(--wpds-color-fg-content-neutral, #1e1e1e); | ||
| flex-shrink: 0; | ||
| transition: rotate 0.15s ease-out; |
There was a problem hiding this comment.
You could use Motion tokens, tho not sure if Jetpack's @wordpress/theme package is up-to-date enough to have them.
| flex-shrink: 0; | ||
| transition: rotate 0.15s ease-out; | ||
|
|
||
| @media (prefers-reduced-motion) { |
There was a problem hiding this comment.
Alternatively, you could wrap the whole transition above with using not: @media not (prefers-reduced-motion) { } like you're doing a few lines below.
| } | ||
|
|
||
| @media not (prefers-reduced-motion) { | ||
| transition: all 0.15s ease-out; |
| align-items: center; | ||
| display: flex; | ||
| gap: var(--wpds-dimension-gap-sm, 8px); |
| return ( | ||
| <> | ||
| <ModernServicesList /> | ||
| <Text variant="body-sm" render={ <p className={ styles[ 'manual-share' ] } /> }> |
There was a problem hiding this comment.
You could pass className directly to Text too I think 🤔
| 'Want to share to other networks? Use our Manual Sharing feature from the editor.', | ||
| 'jetpack-publicize-pkg' | ||
| ) } | ||
| |
There was a problem hiding this comment.
You can use Stack to add spacing between elements.
| const title = hasKeyringResult | ||
| ? __( 'Connection confirmation', 'jetpack-publicize-pkg' ) | ||
| : _x( 'Manage Jetpack Social connections', '', 'jetpack-publicize-pkg' ); |
There was a problem hiding this comment.
I think these ternaries tend to create i18n issues with how we bundle code, so might need to split to separate constants.
|
|
||
| const { setKeyringResult, closeConnectionsModal, setReconnectingAccount } = useDispatch( store ); | ||
|
|
||
| const [ isSmall ] = useBreakpointMatch( 'sm' ); |
There was a problem hiding this comment.
WDYT if we use core viewport package instead of the Jetpack one?
| @@ -0,0 +1,91 @@ | |||
| import { getRedirectUrl, useBreakpointMatch } from '@automattic/jetpack-components'; | |||
| import { Modal } from '@wordpress/components'; | |||
There was a problem hiding this comment.
You could use Dialog from @wordpress/ui instead here.
| .modal.modal { | ||
| width: 65rem; | ||
| } |
There was a problem hiding this comment.
Ideally we instead use size prop instead of custom modal sizes. Dialog component from wp-ui would be even better tho. :-)
| @@ -0,0 +1,176 @@ | |||
| import { | |||
| __experimentalInputControl as InputControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis | |||
| Notice, | |||
There was a problem hiding this comment.
You could use Notice from @wordpress/ui instead.
| import { Text } from '@automattic/jetpack-components'; | ||
| import { useSelect } from '@wordpress/data'; | ||
| import { __ } from '@wordpress/i18n'; | ||
| import { Icon, info } from '@wordpress/icons'; |
There was a problem hiding this comment.
Icon could be imported from @wordpress/ui instead.
| @@ -0,0 +1,122 @@ | |||
| import { Text } from '@automattic/jetpack-components'; | |||
There was a problem hiding this comment.
Could Text from @wordpress/ui work instead?
| <button | ||
| type="button" | ||
| className={ styles[ 'mark-shared-help' ] } | ||
| aria-label={ markAsSharedHelp } | ||
| > | ||
| <Icon icon={ info } size={ 18 } /> | ||
| </button> |
There was a problem hiding this comment.
Would IconButton work here instead of custom button styles?
| { /* | ||
| * The WPDS Tooltip positioner defaults to | ||
| * `z-index: var(--wp-ui-tooltip-z-index, initial)`, | ||
| * which falls back to `auto`. Inside the | ||
| * wp-components Modal (z-index ~100000), the | ||
| * popup ends up behind the modal frame. Pin | ||
| * the popup above the modal so the tooltip | ||
| * is visible when hovering inside the modal. | ||
| */ } | ||
| <Tooltip.Popup sideOffset={ 8 } style={ { zIndex: 100001 } }> |
There was a problem hiding this comment.
Instead of the hacky fix, you should try if the latest @wordpress/ui fixes it (it likely does), or if you have misconfigured portal support. Switching to Dialog instead of Modal might also fix it.
| @@ -0,0 +1,145 @@ | |||
| import { useBreakpointMatch } from '@automattic/jetpack-components'; | |||
There was a problem hiding this comment.
Using core viewport package instead of the Jetpack one might be good.
| import { useSelect } from '@wordpress/data'; | ||
| import { useCallback, useEffect, useRef, useState } from '@wordpress/element'; | ||
| import { __, _x } from '@wordpress/i18n'; | ||
| import { Icon, chevronDown } from '@wordpress/icons'; |
There was a problem hiding this comment.
Could import Icon from @wordpress/ui instead.
| } | ||
|
|
||
| .service-connection-list { | ||
| border-top: 1px solid var(--jp-gray-5); |
| display: flex; | ||
| gap: var(--wpds-dimension-gap-lg, 16px); |
There was a problem hiding this comment.
Could use Stack component instead.
| display: flex; | ||
| flex-direction: column; | ||
| gap: 1rem; |
| display: flex; | ||
| gap: 1rem; |
| flex: 1; | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: flex-start; | ||
| gap: 0.5rem; |
| display: flex; | ||
| flex-direction: column; | ||
| gap: 0.5rem; |
| align-items: center; | ||
| display: flex; | ||
| gap: var(--wpds-dimension-gap-sm, 8px); |
- Fix profile-name link toggling the disclosure row (stopPropagation wrapper, mirroring the status wrap) - Migrate the Add-account modal to the @wordpress/ui Dialog: drops the custom width + z-index tooltip hack; pin it below #wpadminbar and reserve the scrollbar gutter so rows don't shift on overflow - Swap to @wordpress/ui Notice / Icon / IconButton / Text / Stack, and body-lg Text for the name/title; use useViewportMatch from @wordpress/compose instead of the Jetpack breakpoint hook - Use WPDS motion tokens for the disclosure transitions; restore the Bluesky field error affordance; drop dead CSS - Add render-smoke + interaction tests for the modern components, including a click-on-name-doesn't-toggle regression test All changes live in *-modern variants rendered only inside ModernizationProvider, so the legacy admin page and block editor are unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Follow-up polish to PR 2 under the Social modernization umbrella (#48824). Refreshes the connected-accounts list and the shared Add-account modal onto a single WPDS disclosure-row visual language. Stacks on PR 2 — depends on it merging first.
Closes the umbrella's deferred "Per-account inline disclosure rows" item.
Highlights
ServiceItem(modal) andConnectionInfo(chassis Overview) render as a flat-rowCollapsible.Triggerwith a CSS-rotate chevron, and each list lives inside a singleCard.Rootwith edge-to-edge dividers. The whole row is one click target; the profile-name link and the status/action controls stop propagation so they don't toggle the row.Dialog. The modal moves from the wp-componentsModalto@wordpress/ui'sDialog(size="large",fullon mobile), dropping the custom65remwidth. The Dialog portals its own backdrop/popup, so the in-modal info-icon tooltip clears the frame without the previousz-index: 100001workaround. While listing services the frame is pinned (integer top/bottom insets) below#wpadminbarwithscrollbar-gutter: stable both-edges, so expanding a row scrolls inside the frame instead of growing/re-centering it or shifting its contents.__experimentalInputControlreplaces raw<input>s for Mastodon/Bluesky; the info-icon affordance is now anIconButton(built-in tooltip) from@wordpress/ui; the Bluesky reconnect message usesNoticefrom@wordpress/ui; layout flex wrappers useStack; typography usesText(withbody-lgfor the account name / service title); the chevron and decorative icons come from@wordpress/ui'sIcon. Breakpoint detection usesuseViewportMatchfrom@wordpress/compose.social-message-templatessticker or thesocial-enhanced-publishingplan is missing,ConnectionTemplateEditornow renders a disabled textarea seeded with the site's default share message plus an Upgrade link — previously it rendered nothing. Legacy, Simple, and block-editor surfaces are unchanged (still render nothing). This is a new user-facing free-plan nudge, not just a primitive swap.size="medium"variant onConnectionIcon— 32×32 avatar + 16×16 service icon for the chassis Overview rows. Default stayssmall(28×28 / 14×14) so other call sites (dataviews, scheduled posts, sharing activity) are untouched.Disconnectbutton →size="compact" tone="neutral"; in-row Connect / Reconnect button →size="compact". The account name renders in neutral foreground atbody-lg(15px), with the network label beneath in--wpds-color-fg-content-neutral-weak.--wpds-dimension-*/--wpds-typography-*/--wpds-color-*tokens (with safe physical fallbacks), and uses--wpds-motion-*tokens for the disclosure/chevron transitions.ModernConnectionInfo,ModernServiceItem,ModernServicesList,ModernServiceConnectionInfo,ModernCustomInputs,ModernManageConnectionsModal), including a click-on-name-doesn't-toggle regression test for the disclosure row.Screenshots
Chassis Overview — connected accounts card
Chassis Overview — expanded connection (MarkAsShared + WPDS Tooltip + neutral Disconnect)
Chassis Overview — expanded connection with Message Templates editor (sticker + paid plan)
Add-account modal — services joined as one Card
Add-account modal — Bluesky expanded with InputControl
Testing instructions:
jetpack build packages/publicize --deps(or rsync the Jetpack plugin to a Jurassic Ninja site —fortunately-specific-gentoo.jurassic.ninjais set up if you'd rather skip the build).wp jetpack module activate publicize.wp option update jetpack-social_show_pricing_page 0(otherwiseshould_preempt_to_legacy()routes the request back to the legacySocialAdminPage).add_filter( 'rsm_jetpack_ui_modernization_social', '__return_true' );and connect at least 2-3 social accounts (mix of OAuth services like LinkedIn/Tumblr and custom-input services like Mastodon/Bluesky if possible).wp-admin → Jetpack → Social→ Overview tab. Expected: a single "Connected accounts" Card with rows separated by dividers; 32×32 avatars on the left, account name in neutral foreground + network name underneath in muted gray, chevron on the right.iinfo icon next to it, the connection template editor, and a compact neutral "Disconnect" button.iinfo icon. Expected: theIconButtontooltip opens with zero delay showing "If enabled, the connection will be available to all administrators, editors, and authors." It renders fully (not clipped by the surrounding Card).Dialogopens; the services list is one continuous Card with rows separated by dividers (no per-service Card borders). The frame sits clear of the admin bar at the top.InputControlfields (Handle / App password), label above input, help text below. Type a Bluesky handle ending in.bsky.socialwith a dot in the middle (e.g.foo.bar.bsky.social) — the inline error text appears in red and the input border turns red.iinfo icon next to the "Mark the connection as shared" toggle inside the modal. Expected: tooltip opens with zero delay above the Dialog frame (not behind it) — no z-index workaround needed.Disconnectbutton inside the modal disclosure. Expected: it uses the same compact, neutraloutlinestyling as the chassis Overview disconnect button, and the confirmation dialog still opens.ModernizationProvider, so the shared components keep their original rendering.)Message Templates interoperability + free-plan upsell
The per-connection message template editor (
ConnectionTemplateEditor) is mounted inside bothConnectionInfoandServiceConnectionInfo. It self-gates onsocial-message-templates(WPCOM blog sticker) ANDsocial-enhanced-publishing(paid plan).JetpackScriptData.site.plan.features.active.includes('social-message-templates') && JetpackScriptData.site.plan.features.active.includes('social-enhanced-publishing')returnstrue. Expand a connection — a "Custom message for this connection" textarea appears between the "Mark the connection as shared" toggle and "Disconnect". Type a template with tokens like{title}/{content}; the value debounces and autosaves viaupdateConnectionById(~1s after typing pauses) and persists across reloads. The "Available placeholders" popover renders inside the disclosure panel without clipping.jetpack_social_per_network_customization_upgrade_clickTracks event and navigates to the upgrade flow. On Simple sites and in the block editor, no editor renders.Does this pull request change what data or activity we track or use?
Yes — one net-new Tracks event. The new free-plan upsell on
ConnectionTemplateEditorfiresjetpack_social_per_network_customization_upgrade_clickwhen the Upgrade link is clicked. It only fires on the modernized chassis (flag-gated) for sites missing the message-templates feature, carries no new personal data, and is the only tracking change.Everything else is a behavior-preserving primitive swap: the underlying components in
ConnectionInfo,ServiceItem,Disconnect,ConnectionName,ConnectionIcon,CustomInputs, andManageConnectionsModalmove to their WPDS equivalents without changing the data flow, REST calls, post-meta keys, or option reads/writes. No new REST endpoints, no new external requests. The form-submission path inside the modal (requestAccessviaFormData) is unchanged —InputControlforwardsnameto the underlying<input>soFormData(form)continues to pick up the handle / app-password values exactly as before.🤖 Generated with Claude Code