Skip to content

Components: Move Newsletter's placement card to @automattic/jetpack-components as CheckboxCard - #53733

Merged
jeherve merged 8 commits into
trunkfrom
update/placement-card-shared-component
Oct 19, 2026
Merged

jeherve merged 8 commits into
trunkfrom
update/placement-card-shared-component

Conversation

@jeherve

@jeherve jeherve commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Fixes CM-978

Proposed changes

Newsletter's Subscriptions section draws its placements as selectable cards, but that card lived inside the Newsletter package. The Sharing & Likes screen needs the same cards for its template placements (CM-976), so this moves the card to @automattic/jetpack-components, where both screens can use it.

  • CheckboxCard is a card with a checkbox: an illustration, a title under it that also names the checkbox, and an optional "Preview and edit" link. Only a click on the illustration toggles it; the title and link don't. Props are the ones Newsletter already used (id, name, title, illustration, checked, onChange, previewUrl, onPreviewClick, disabled).
  • CheckboxCardGrid lays the cards out in two columns, one below 720px, so both screens use the same grid.
  • Both come from the main entry point and from a new @automattic/jetpack-components/checkbox-card subpath. wp-build screens import components through those subpaths, so they don't bundle every export the package has.
  • The classes are jp-checkbox-card*, and "Preview and edit" uses the jetpack-components text domain.
  • Newsletter imports the shared card and grid, and its own copy goes. Its illustrations stay in the Newsletter package.

Jetpack > Newsletter looks the same as on trunk, apart from a few checkbox details (see the note under Screenshots) :)

import CheckboxCard, { CheckboxCardGrid } from '@automattic/jetpack-components/checkbox-card';

<CheckboxCardGrid>
	<CheckboxCard
		id="sharing-buttons-after-content"
		name="after_content"
		title={ __( 'After the post content', 'jetpack-sharing-likes' ) }
		illustration={ <AfterContentIllustration /> }
		checked={ placement === 'after_content' }
		onChange={ handlePlacementChange }
		previewUrl={ isSaved ? siteEditorUrl : undefined }
	/>
</CheckboxCardGrid>

Screenshots

Note

@simison suggested a few changes in the review comments on the card's index.tsx and style.scss (thanks!), so af7a007 rebuilds the card from @wordpress/ui primitives:

  • The checkbox is the Checkbox primitive inside a Field, with the illustration as the field's label, instead of CheckboxControl from @wordpress/components. Clicking the illustration still toggles the card, and the title still names the checkbox without toggling it.
  • Card.FullBleed makes the illustration span the card, so the CSS that reset the old checkbox's spacing is gone.
  • The card's focus ring uses the outset-ring__focus() mixin from base styles.

@simison also suggested a more generic name, since nothing in the card is specific to placements, so ec6b333 renames it from PlacementCard to CheckboxCard. The subpath export is now ./checkbox-card.

The first version of this PR was pixel-identical to trunk; this one isn't quite. On a phone, the checkbox is now 16px instead of 24px (the old CheckboxControl grew on small screens, the primitive doesn't), and on desktop the check mark is drawn a little differently. The screenshots below show the current version.

Jetpack > Newsletter > Settings, Subscriptions section, with two placements saved:

Before (trunk) After
Desktop Placement cards on desktop on trunk Placement cards on desktop with this PR
Phone Placement cards on a phone on trunk Placement cards on a phone with this PR

A focused card shows the checkbox's own focus ring and the card outline:

A focused placement card, with the checkbox's focus ring and the card outline

The new Storybook story:

The Checkbox Card grid story in Storybook, with two cards

Rationale

Props stay the same. Keeping Newsletter's props means Newsletter barely changes, and CM-976 builds on an API that already works on one screen. The card is a checkbox, though, so it doesn't handle an either/or choice between cards; a section that needs one card at a time (CM-976) enforces that itself.

Styles come with the card. The card imports its own stylesheet, like the other subpath components, so Newsletter's style.scss no longer loads it. The card's CSS still lands in both of Newsletter's bundles, the wp-build dashboard and the legacy settings page.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

On a connected Jetpack site running a block theme:

  • Go to Jetpack > Newsletter > Settings, and scroll to the Subscriptions section.
  • Check the four "Homepage and posts" cards look as they do on trunk: two columns on desktop, one on a phone.
  • Click a card's illustration: the checkbox toggles. Click its title: nothing happens.
  • Tab to a checkbox: the card shows a focus ring, and Space toggles it.
  • Tick a card and save: a "Preview and edit" link appears under its title, and opens the Site Editor.

In Storybook, open JS Packages > Components > Checkbox Card and click through its stories.

Fixes CM-978

The Sharing & Likes screen needs the same selectable placement cards
as the Subscriptions section of Jetpack > Newsletter (CM-976). Moving
the card to @automattic/jetpack-components lets both screens share one
component, so they look and behave the same.

The card ships with a PlacementCardGrid wrapper, the two-column grid
that drops to one column below 720px, so both screens lay the cards out
the same way. Both are exported from the main entry point and from a
./placement-card subpath: wp-build screens import components through
subpaths so they don't bundle the package's whole set of exports.

Newsletter now imports the shared card and grid and drops its own copy.
Its illustrations stay in the newsletter package. The props are
unchanged; the classes move from jetpack-newsletter-placement__* to
jp-placement-card__*, and "Preview and edit" is translated against the
jetpack-components domain.
@jeherve jeherve added the [Status] Needs Review This PR is ready for review. label Oct 16, 2026
@jeherve jeherve self-assigned this Oct 16, 2026
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the update/placement-card-shared-component branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/placement-card-shared-component
bin/jetpack-downloader test jetpack-mu-wpcom-plugin update/placement-card-shared-component

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

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:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

… test

The card only renders the link when it gets a previewUrl; the saved-state
gating lives in the Newsletter section and is tested there.
… renders

CheckboxControl only renders its label element when given a non-empty
label, so the rule hiding it matched nothing.
@jp-launch-control

jp-launch-control Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

2 files are newly checked for coverage.

File Coverage
projects/js-packages/components/components/checkbox-card/index.tsx 6/7 (85.71%) 💚
projects/js-packages/components/components/checkbox-card/types.ts 0/0 (—%) 🤷

Full summary · PHP report · JS report

Comment thread projects/js-packages/components/components/placement-card/index.tsx Outdated
Comment thread projects/js-packages/components/components/placement-card/index.tsx Outdated
Comment thread projects/js-packages/components/components/checkbox-card/style.scss
Comment thread projects/js-packages/components/components/placement-card/style.scss Outdated
The card used CheckboxControl from @wordpress/components, which the
new @wordpress/use-recommended-components lint rule flags, and needed
CSS overrides to strip that control's chrome and to make the
illustration span the card.

The checkbox is now the @wordpress/ui Checkbox primitive inside a
Field, with the illustration as the Field's label, so a click on it
still toggles the card. The title still names the checkbox through
aria-labelledby, and still sits outside the label. Card.FullBleed
makes the illustration span the card edge to edge, and the focus ring
uses the outset-ring__focus mixin from @wordpress/base-styles, so it
matches core's components. None of the component overrides remain.
…de list

The file moved to @automattic/jetpack-components on this branch, so
CI's exclude-list check flags its entry as fixed.
@jeherve
jeherve requested a review from a team as a code owner October 19, 2026 13:23
@simison

simison commented Oct 19, 2026

Copy link
Copy Markdown
Member

BTW the component name "PlacementCard" refers closely to subscription form's placement; something more generic might work as Jetpack component name better. E.g. CheckboxCard

"Placement" describes what Newsletter and Sharing & Likes use the card
for, not what the card is: a card with a checkbox, an illustration and
a title. A generic name fits a component shared across Jetpack better.

PlacementCard, PlacementCardGrid and their props types become
CheckboxCard, CheckboxCardGrid, CheckboxCardProps and
CheckboxCardGridProps; the subpath export moves from ./placement-card
to ./checkbox-card, and the classes from jp-placement-card* to
jp-checkbox-card*. Nothing outside this branch used the old names.
@jeherve

jeherve commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

Good point, thanks! Renamed in ec6b333: it's now CheckboxCard and CheckboxCardGrid, exported from @automattic/jetpack-components/checkbox-card, with jp-checkbox-card* classes. Nothing changes on the Newsletter screen :)

@jeherve jeherve changed the title Components: Move Newsletter's PlacementCard to @automattic/jetpack-components Components: Move Newsletter's placement card to @automattic/jetpack-components as CheckboxCard Oct 19, 2026
@jeherve
jeherve merged commit dad837e into trunk Oct 19, 2026
130 of 131 checks passed
@jeherve
jeherve deleted the update/placement-card-shared-component branch October 19, 2026 15:26
@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] Needs Review This PR is ready for review. labels Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants