feat(newspack-ui): standardize snackbars + accessible notices#445
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cb1cf06 to
5db5c73
Compare
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5300906 to
698edd0
Compare
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
698edd0 to
77dc631
Compare
adekbadek
left a comment
There was a problem hiding this comment.
Solid, well-scoped refactor with a genuine accessibility win and no security or correctness blockers — the localized SVG innerHTML sink takes only static plugin-owned input, and the token rename is complete across the monorepo.
Notes on code outside this PR’s changed lines (can’t be posted inline, so collected here):
plugins/newspack-newsletters/includes/class-newspack-newsletters-subscription.php:1359— Nit: Sibling-plugin caller still passes removedcornerkey — A caller outside this PR's diff still passes'corner' => 'top-right'toNewspack_UI::add_notice(). It's harmless now —wp_parse_argsdrops the unknown key, no fatal, which confirms removingcorneris safe platform-wide — but it's dead config in a sibling plugin, and a reader of that file will assumecornerstill does something. Either clean it up in this monorepo branch or leave a note.plugins/newspack-plugin/includes/class-newspack-ui.php:141— Nit:noprivdismiss AJAX — keep the handler contract side-effect-safe —newspack_ui_notice_dismissedis registered fornoprivand fires the publicdo_action( 'newspack_ui_notice_dismissed', $id )with an attacker-supplied (but sanitized) id after nonce verification. The one current handler (WooCommerce_Update_Payment_Notice::handle_notice_dismissed) writesupdate_user_meta( wp_get_current_user()->ID … ), which no-ops for logged-out user 0 — so no impact today. The contract to uphold is that everynewspack_ui_notice_dismissedhandler stays side-effect-safe for arbitrary ids and anonymous callers; consider dropping thenoprivregistration if no anonymous notice actually needs server-side dismissal persistence.
|
Thanks for the thorough pass, @adekbadek — all addressed in
Re-requesting your review. |
There was a problem hiding this comment.
Pull request overview
Standardizes Newspack UI snackbars/notices (primarily front-end / my-account) with a single snackbar position/layout, updated design tokens, and improved accessibility via ARIA roles + live-region announcements.
Changes:
- Unifies snackbar markup/styles and removes per-corner variants; adds grid-based snackbar item layout and new
ghost-darkbutton variant. - Adds screen-reader announcements for snackbars (JS live regions) and assigns appropriate
rolevalues to inline notices. - Renames width tokens to
--newspack-ui-width-*and updates consumers accordingly.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| themes/newspack-theme/newspack-theme/sass/plugins/republication-tracker-tool.scss | Switches modal-width token usage to the new generic width token. |
| plugins/newspack-plugin/src/newspack-ui/scss/variables/_index.scss | Introduces --newspack-ui-width-* tokens (and deprecated aliases). |
| plugins/newspack-plugin/src/newspack-ui/scss/elements/woocommerce/_overrides.scss | Updates WooCommerce overrides to use new width token names. |
| plugins/newspack-plugin/src/newspack-ui/scss/elements/forms/_buttons.scss | Adds newspack-ui__button--ghost-dark and demo horizontal-stack spacing tweak. |
| plugins/newspack-plugin/src/newspack-ui/scss/elements/_notices.scss | Reworks snackbar container/item styling (single position, grid layout, motion/reflow behavior). |
| plugins/newspack-plugin/src/newspack-ui/scss/_modals.scss | Updates modal sizing to use --newspack-ui-width-* tokens. |
| plugins/newspack-plugin/src/newspack-ui/js/notices.js | Adds live-region announcements and updates snackbar creation/activation behavior. |
| plugins/newspack-plugin/src/newspack-ui/js/modals.js | Adds role="alert" to injected error notices in modals. |
| plugins/newspack-plugin/src/my-account/v1/global.js | Uses default createNotice() type (success) without passing an explicit type. |
| plugins/newspack-plugin/includes/reader-activation/class-my-account.php | Removes corner usage and updates inline CSS to new width tokens. |
| plugins/newspack-plugin/includes/plugins/woocommerce/my-account/templates/v1/notices/success.php | Removes now-unused notice args (type, corner) in success template. |
| plugins/newspack-plugin/includes/plugins/woocommerce/my-account/templates/v1/notices/notice.php | Removes corner from warning notice args. |
| plugins/newspack-plugin/includes/plugins/woocommerce/my-account/templates/v1/notices/error.php | Removes corner from error notice args. |
| plugins/newspack-plugin/includes/plugins/woocommerce/my-account/templates/v1/group-subscription-members.php | Adds role="status" to an informational inline notice. |
| plugins/newspack-plugin/includes/plugins/woocommerce/my-account/class-my-account-ui-v1.php | Removes explicit notice type/corner args for delete-account notice. |
| plugins/newspack-plugin/includes/plugins/woocommerce/class-woocommerce-update-payment-notice.php | Removes explicit notice type/corner args. |
| plugins/newspack-plugin/includes/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-invite.php | Simplifies invite-message mapping and aligns notice type behavior with new announcement rules. |
| plugins/newspack-plugin/includes/content-gate/class-ip-access-rule.php | Adjusts notice severity type for the IP access rule result message(s). |
| plugins/newspack-plugin/includes/class-newspack-ui.php | Flattens notice storage/printing, adds type icons, demo updates, and roles for inline notices. |
| plugins/newspack-plugin/includes/class-newspack-ui-icons.php | Adds a new “caution” SVG icon for warning notices. |
| plugins/newspack-newsletters/includes/class-newspack-newsletters-subscription.php | Removes corner usage when adding account notices. |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
10108a9 to
d5e1697
Compare
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
adekbadek
left a comment
There was a problem hiding this comment.
Re-reviewed on 44b835e and verified against the ?ui-demo page in a local env: every thread addressed, with two going beyond the ask (per-type border/icon cues for warning/error; server-side wp_kses on the localized icons). The two declined nits (token alias, width-xs) are reasonable calls. LGTM.
|
Hey @thomasguillot, good job getting this PR merged! 🎉 Now, the Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label. If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label. Thank you! ❤️ |
What
First of two PRs for the snackbar audit (DSGNEWS-185). Scoped to the
newspack-ui/ my-account (front-end) snackbar and notices. The wp-admin snackbar standardization (WizardSnackbar, advertising wizard, story-budget) is a separate follow-up PR.Layout
newspack-ui__snackbarposition variants into one: top-right, 24px inset (spacer-5), slide in from the right. The other three variants were dead code.topnow usesvar(--wp-admin--admin-bar--height, 0px), which WordPress sets responsively, so the breakpoint overrides are gone and it falls back to 0 on the public front end.__snackbar__itemis a CSS grid (icon | content | close, the icon and close columns added only when present via:has()). The icon pins to the top, the content wraps, and the close button is vertically centered.--newspack-ui-width-s(410px). A short snackbar no longer resizes when a longer one appears.openNotice(el, false)) collapse to zero height too, so they reserve no space in the stack.Motion
__content::after).prefers-reduced-motion: reducedisables the animation entirely.Buttons
newspack-ui__button--ghost-darkvariant for ghost buttons on dark surfaces (textneutral-0, hoverneutral-80, light focus ring).--icon --ghost-dark), so hover, focus-visible, and transitions come for free. It is 36px, vertically centered, with a 4px right inset.Error icon
newspack-ui__svg-icon--erroricon in the icon column, on both the PHP (print_notices) and JS (createNotice) paths.Tokens
--newspack-ui-width-{xs,s,m,l}(was--newspack-ui-modal-width-*, plus a newxsof 300px). All consumers (modals, woo overrides, my-account, newspack-theme) were updated; no aliases remain.Accessibility
Notices previously had no ARIA, so screen readers never announced them. Now:
typedrives the announcement politeness and the error icon (no color returns):erroris assertive, everything else is polite.role="status"/aria-live="polite"androle="alert"/aria-live="assertive") created inside.newspack-ui.openNotice()writes the message into the matching region, so both on-load notices (e.g. my-account messages after a redirect) and dynamic ones (group actions, copy-link) are announced reliably. On-load activation is deferred a tick so the regions are registered before content is injected.newspack-ui__noticemarkup carriesrole="alert"(--error) /role="status"(else).API
Newspack_UI::add_notice()/createNotice()carrytype(defaultsuccess); the string shorthandadd_notice( $msg, 'error' )is still supported.cornerwas removed (single position). Notices are stored flat and rendered in one container.errorso they announce assertively and show the error icon;login_neededstays polite (it is a call to action, not an error).Demo
?ui-demoNotices section has the snackbar triggers in a horizontal stack, a "Show persistent snackbar" example (icon + dismissible close), and "Show snackbar" now usescreateNoticeso it demonstrates the full auto-hide and reflow.Verification
lint:scss/lint:js/phpcsclean for changed files; built and confirmed in the enqueueddist/.?ui-demoand my-account: single and stacked snackbars, content sizing, graceful reflow, 36px centered ghost-dark close, error icon, and the admin-bar offset.