Skip to content

Jetpack notices: remove the CSS the notice migration left dead - #52159

Merged
CGastrell merged 3 commits into
trunkfrom
update/prune-dead-dops-notice-css
Sep 10, 2026
Merged

CGastrell merged 3 commits into
trunkfrom
update/prune-dead-dops-notice-css

Conversation

@CGastrell

@CGastrell CGastrell commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Fixes JETPACK-2542

Proposed changes

  • Removes CSS left dead by Jetpack notices: back SimpleNotice with the @wordpress/ui Notice #52015, which rewrote SimpleNotice to render the @wordpress/ui Notice and dropped the dops-notice class family from every React notice.
  • Nine rules across five stylesheets. Six from the notice migration: the .dops-notice margin and the unreachable .dops-section-header.is-working block in dash-item, a.dops-notice__action in at-a-glance, traffic and settings, and .dops-notice__text-no-underline / .dops-notice__button in components/notice.
  • Two more that review turned up: the whole .jp-stats-odyssey-disabled-notice block in traffic, and the dops-notice__text-no-underline class pro-status still put on its action link.
  • And three neighbours of that Odyssey block — .jp-stats-odyssey-toggle, its > .components-base-control, and .jp-stats-odyssey-badge. They lost their markup in Drop Legacy Stats experience #40384 alongside the notice, and nothing in projects/ emits them. .jp-stats-form-fieldset sits between them and is still live, so this is a three-rule removal rather than a range delete.

The chassis stylesheet stays. components/admin-notices/index.jsx still rebuilds server-rendered VaultPress, WooCommerce and core notices into dops-notice markup with jQuery, so components/notice/style.scss, scss/shared/_main.scss:45 and components/jetpack-notices/style.scss are all still live and untouched.

Why they are dead: AdminNotices prepends its rebuilt markup into #jp-admin-notices, rendered at _inc/client/main.jsx:855 and :885 as a sibling of the page content. A rule scoped under .jp-dash-item, .dops-card.is-compact or .jp-settings-container can never reach it.

One other producer exists and is also out of reach: plugins/vaultpress/vaultpress.php:963 prints the same class family server-side, but only from its own ui_* methods, so it lands on admin.php?page=vaultpress and never on a Jetpack screen. It ships its own copies of the two unscoped rules deleted here, in nav-styles.css.

.jp-stats-odyssey-disabled-notice is a different case: that container is emitted nowhere in the repo, so the whole block goes rather than just the rules inside it.

Related product discussion/links

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

No.

Testing instructions

CSS-only, and the point is that nothing changes visually. Two checks.

1. The deleted selectors match nothing. On a connected site running this branch, open Jetpack → Dashboard, then visit each Settings tab (Security, Performance, Writing, Sharing, Discussion, Traffic, Reader). On each, paste this in the browser console:

[
  '.jp-dash-item .dops-section-header__actions .dops-notice',
  '.jp-dash-item .dops-section-header.is-working, .jp-dash-item .dops-section-header.is-premium-inactive',
  '.dops-card.is-compact a.dops-notice__action',
  '.jp-stats-odyssey-disabled-notice a.dops-notice__action',
  '.jp-settings-container a.dops-notice__action',
  '.dops-notice__text a.dops-notice__text-no-underline',
  '.dops-notice__button',
].forEach( s => console.log( document.querySelectorAll( s ).length, s ) );

Every count must be 0 — on this branch and on trunk alike. A rule whose selector matches nothing cannot change rendering.

2. The chassis still works. The jQuery path is what keeps the rest of that stylesheet alive, so confirm it still renders. With VaultPress or WooCommerce active you will see their notices re-skinned at the top of any Jetpack screen. Without either, drop this in a mu-plugin:

add_action( 'admin_notices', function () {
	echo '<div class="wrap vp-notice vp-registered"><h3>Fixture</h3><p class="vp-message">Body copy. <a href="#">A link</a></p></div>';
} );

Then open Jetpack → Dashboard. The notice must render inside the dark Jetpack chassis with its icon, not as raw admin markup, and document.querySelectorAll( '#jp-admin-notices .dops-notice' ).length must be 1. It carries no dismiss control — the re-skinner adds one only on the vp-deactivated branch — so do not read its absence as a failure.

Also worth an eye while you are there: At a Glance cards, the Security and Traffic settings cards, and the Sharing screen should look exactly as they do on trunk.

I verified both checks on a local site: all seven selectors returned 0 across 8 screens, the fixture rendered in the chassis, and before/after screenshots of Traffic, Sharing and the fixture page were pixel-identical. pnpm run test-gui in projects/plugins/jetpack passes 56 suites / 498 tests, and stylelint is clean on all five files.

Proof on the screenshots is that they are byte identical

Header Header
before-vp-chassis after-vp-chassis
before-settings-security after-settings-security
before-settings-sharing after-settings-sharing
before-settings-traffic after-settings-traffic

PR #52015 rewrote SimpleNotice to render the @wordpress/ui Notice and
dropped the dops-notice class family from every React notice. After
that PR, the only remaining producer of dops-notice* markup is
components/admin-notices/index.jsx, which rebuilds server-rendered
VaultPress, WooCommerce and core notices with jQuery and prepends them
into #jp-admin-notices. That container renders as a sibling of the
page content (main.jsx renderMainContent), so any rule scoped under a
page-content selector can never match it.

Removed:
- dash-item/style.scss: the .dops-notice margin rule under
  .jp-dash-item .dops-section-header__actions, and the
  &.is-working/&.is-premium-inactive block under
  .jp-dash-item .dops-section-header. DashItem never passes a
  className to SectionHeader, so that selector never matched.
- at-a-glance/style.scss: a.dops-notice__action rule under
  .dops-card.is-compact.
- traffic/style.scss: both a.dops-notice__action rules under
  .jp-stats-odyssey-disabled-notice.
- settings/style.scss: the two &.dops-notice__action rules under
  .jp-settings-container.
- components/notice/style.scss: .dops-notice__text-no-underline and
  .dops-notice__button. No producer nests either class under a
  .dops-notice__text ancestor, which both selectors require.

Left untouched: the .dops-notice chassis in components/notice/style.scss,
_main.scss's .dops-notice__text a rule, jetpack-notices/style.scss, and
all of admin-notices/style.scss. The jQuery path still styles its
rebuilt markup with these.

Verified with stylelint on the changed files and
pnpm run test-gui in projects/plugins/jetpack (56 suites / 498 tests
passing).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SWVs5oUDimen1FeGJhJAkx
@CGastrell CGastrell added the [Status] Needs Review This PR is ready for review. label Sep 9, 2026
@CGastrell CGastrell self-assigned this Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 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), and enable the update/prune-dead-dops-notice-css branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/prune-dead-dops-notice-css

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 github-actions Bot added [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ Admin Page React-powered dashboard under the Jetpack menu labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026 •

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!


Jetpack plugin:

The Jetpack plugin has different release cadences depending on the platform:

  • WordPress.com Simple releases happen as soon as you deploy your changes after merging this PR (PCYsg-Jjm-p2).
  • WoA releases happen weekly.
  • Releases to self-hosted sites happen monthly:
    • Scheduled release: October 6, 2026

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@jp-launch-control

Copy link
Copy Markdown

Code Coverage Summary

This PR did not change code coverage!

That could be good or bad, depending on the situation. Everything covered before, and still is? Great! Nothing was covered before? Not so great. 🤷

Full summary · PHP report · JS report

@CGastrell

Copy link
Copy Markdown
Contributor Author

Verified: all six rules are dead. No remaining emitter for dops-notice__action, dops-notice__button or dops-notice__text-no-underline in the React tree, and the one live emitter — the jQuery path in components/admin-notices/index.jsx — prepends into #jp-admin-notices, a sibling of renderMainContent(), so it never sits under .jp-settings-container or .jp-dash-item.

Two cleanups:

1. traffic/style.scss:259 — the whole block is dead, not just the removed part. .jp-stats-odyssey-disabled-notice is emitted nowhere in the repo; git grep hits only this stylesheet. The PR leaves the selector behind with its >480px width rule. Delete it entirely. Also worth correcting the description: this one is dead because the container is never rendered, not because it is unreachable.

2. pro-status/index.jsx:155 still sets className="dops-notice__text-no-underline". The removed rule was correctly dead — StatusIndicator renders @wordpress/ui Text with CSS-module classes, no .dops-notice__text ancestor — but the class name should go with it.

Neither is a regression.

— Tangerine

`.jp-stats-odyssey-disabled-notice` is emitted nowhere in the repo — the only
hit is this stylesheet — so the container rule goes with the two action rules
inside it. That block was dead because nothing renders it, not because the
selector could not reach the jQuery notices.

`pro-status` still set `dops-notice__text-no-underline` on its action link.
Nothing styles that class now, and the rule it was named for required a
`dops-notice__text` ancestor the component never had.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SWVs5oUDimen1FeGJhJAkx
@CGastrell

Copy link
Copy Markdown
Contributor Author

Both actioned in 8c93190.

1. .jp-stats-odyssey-disabled-notice. Confirmed — git grep finds the selector only in this stylesheet, so the container is never rendered. The whole block is gone, and the description no longer claims it was scope-dead. It was dead for a different reason than the other four.

2. pro-status/index.jsx:155. Class removed. Worth noting the one other hit, which stays: plugins/vaultpress/nav-styles.css:101 has its own copy of .dops-notice__text a.dops-notice__text-no-underline. That is a separate plugin's stylesheet against its own markup, not ours to prune here.

56 suites / 498 tests still pass, stylelint and ESLint clean on both files.

— Terminator

@dhasilva dhasilva left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed with /jetpack-review-pr (standard depth — 68 lines, 1 project). No blockers; one optional suggestion inline.

For a deletion PR the load-bearing question is whether the CSS is really dead, so I verified each removal against the tree rather than taking the description's word for it. All seven check out:

  • After #52015, nothing in React emits dops-notice*. The only two remaining producers are components/admin-notices/index.jsx (the jQuery re-skinner — which never emits __button or __text-no-underline, and that is what makes those two removals safe) and vaultpress.php's ui_message(), which ships its own copies of both unscoped rules in nav-styles.css.
  • The scoping argument holds structurally, not just today. #jp-admin-notices renders in main.jsx (L855, L885) as a sibling of renderMainContent(), while .jp-settings-container is created downstream in settings/index.jsx:47 — so re-skinned notices can never be descendants of the scoped selectors. That stays true as markup changes, unlike "grep found nothing".
  • .dops-section-header.is-working is the one I expected to bite: ten at-a-glance cards do pass status="is-working" to DashItem, so grepping the value looks alive. But DashItem declares the prop and never reads it, and SectionHeader only composes className, which DashItem doesn't pass. The class has never reached the DOM.
  • The ProStatus className removal is inert — the rule was scoped .dops-notice__text a…, and ProStatus renders that link inside a @wordpress/ui Text, never inside .dops-notice__text.
  • No hits outside projects/, and no test, snapshot or e2e selector references any removed class.

RTL is a net improvement: every removed declaration was physical (margin-left, padding-left), and nothing physical was added. Changelog is correct — empty entry plus Comment: with Type: other is the right shape for a non-user-facing plugins/jetpack change, and no dependent-plugin entries are needed since this is confined to Jetpack's own admin bundle.

Small nit on the description: it says "Six rules across five stylesheets" and then adds "Two more that review turned up", which totals seven — the first bullet wasn't updated after the second commit. Cosmetic only.

CI: the single red check (Jetpack onboarding e2e, WP latest) fails in env-check.setup.ts with queryA ENOTFOUND …trycloudflare.com — the tunnel failing DNS during setup, before any test ran (1 failed, 4 did not run). The WP 7.0 variant of the same suite passed. Infrastructure flake, unrelated to this change; just re-run it.

Verdict: minor issues — can merge after addressing, and the one suggestion is genuinely optional.

Generated by Claude.

Comment on lines 259 to 261
.jp-stats-odyssey-toggle {
margin-bottom: 20px;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] Two more dead .jp-stats-odyssey-* blocks sit immediately below the one this PR removes, from the same #40384 fallout.

.jp-stats-odyssey-toggle (this rule), .jp-stats-odyssey-toggle > .components-base-control (L263) and .jp-stats-odyssey-badge (L271-281) have zero producers anywhere in projects/ — git grep -n "jp-stats-odyssey" -- projects/ returns only this file, on this branch and on trunk. They died alongside .jp-stats-odyssey-disabled-notice in aff168e ("Drop Legacy Stats experience", #40384).

Careful if you take it: .jp-stats-form-fieldset at L267 is still live (traffic/site-stats.jsx:232), so this is a three-rule removal, not a range delete. .jp-stats-odyssey-badge also carries a physical margin-left: 8px, so removing it retires an RTL wart too.

Entirely optional — keeping this PR scoped to notice CSS is a defensible call. Just worth deciding deliberately rather than by omission.

Generated by Claude.

The "Drop Legacy Stats experience" change (#40384) removed the markup that
carried `.jp-stats-odyssey-toggle`, its `.components-base-control` child and
`.jp-stats-odyssey-badge`, the same removal that stranded the
`.jp-stats-odyssey-disabled-notice` block this branch already deletes. No
`jp-stats-odyssey` class is left anywhere under `projects/`.

`.jp-stats-form-fieldset` sits between those rules and is still rendered by
`_inc/client/traffic/site-stats.jsx`, so this removes three rules rather than a
range. `.jp-stats-odyssey-badge` also carried a physical `margin-left`, so the
deletion retires an RTL wart with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SWVs5oUDimen1FeGJhJAkx
@CGastrell
CGastrell force-pushed the update/prune-dead-dops-notice-css branch from 07b7612 to 5ecb498 Compare September 10, 2026 16:06
@CGastrell
CGastrell merged commit a5d3471 into trunk Sep 10, 2026
79 checks passed
@CGastrell
CGastrell deleted the update/prune-dead-dops-notice-css branch September 10, 2026 19:09
@github-actions github-actions Bot removed the [Status] Needs Review This PR is ready for review. label Sep 10, 2026
@github-actions github-actions Bot added this to the jetpack/16.3 milestone Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Admin Page React-powered dashboard under the Jetpack menu [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants