Commit 1dc265b0cd6 for woocommerce
commit 1dc265b0cd6cf39205c66deb4d6e38fce1607a7e
Author: Jill Q. <jill.quek@automattic.com>
Date: Tue May 19 14:24:05 2026 +0800
Floating header: polish + WP design token alignment (#64885)
* Home header polish: View store icon, even spacing, click race, avatar fallback
Follow-up to #64643. Four small fixes to the Home page floating header
that surfaced after the chrome consolidation landed:
- Add a store-icon to the View store / Preview store tab — after tabs
went icon-only, this tab was missing an `icon` prop and rendered as
an empty button.
- Match DisplayIcon's SVG element size to the rest of the bar (18px,
was 24px). The wider button knocked tab spacing visibly out of
alignment to the left of Display options.
- Lock the User options DropdownMenu trigger to the same 18px box as
the other tabs regardless of sign-in state (avatar previously
rendered at 30px when connected), drop the duplicate
`woocommerce-layout__activity-panel-tab` class from the outer
DropdownMenu wrapper so its 8px horizontal padding doesn't
compound on top of the inner toggle's, and scope the existing
40px height override to the marketplace page where it actually
belongs (it was leaking onto Home and forcing the User button
shorter than its neighbours).
- Fix the first-click race when switching to User from an open
Activity / Finish setup / Help panel. Root cause: the headerAccount
tab passed an inline `() => <HeaderAccount ... />` arrow as its
`component` reference, so every parent re-render handed React a
fresh component type and React responded by unmounting + remounting
HeaderAccount — wiping the DropdownMenu's internal isOpen state
mid-click. Switching to the stable component reference + options
pattern that DisplayOptions already uses fixes it.
- Tidy `commentAuthorAvatar` fallback in header-account.tsx so a
missing wccomSettings.userAvatar doesn't briefly render an SVG
component as an <img src> (caught while we were in here).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add changefile(s) from automation for the following project(s): woocommerce, woocommerce/client/admin
* Payments settings: grey tab strip, white content panel
Follow-up to #64643. @chihsuan flagged that Payments settings looked
inconsistent with the rest of Settings now that the floating header and
nav tab strip on every other Settings tab read as one continuous grey
chrome region. On Payments, an existing override painted #wpcontent
and #mainform white, breaking that continuity.
Drop the #wpcontent override (let it inherit the wp-admin body grey
that every other Settings page uses), then give .nav-tab-wrapper an
explicit grey background so the strip matches the chrome above and
behind it. #mainform keeps its white background — the Payments
content panel stays white inside the grey frame, same shape as
General / Tax / Shipping.
Outer selector is doubled (body.woocommerce_page_wc-settings
.woocommerce-settings-payments-tab) to lift specificity above the
legacy body.woocommerce_page_wc-settings #wpbody-content rule in
admin.scss, which would otherwise win on load order.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add changefile(s) from automation for the following project(s): woocommerce, woocommerce/client/admin
* Floating header: align typography + spacing + shadow to WP design tokens
Audit pass on every literal in the floating-header chrome, replacing
one-off Woo values with the closest token from @wordpress/base-styles,
Gutenberg WPDS, or — where Core hasn't exposed a CSS custom property
yet — a literal that visually matches the upstream direction and a
TODO referencing https://core.trac.wordpress.org/ticket/65085 and the
unified-admin-header discussion in WordPress/gutenberg#76709.
Heading typography (header/style.scss):
- font-size: 14px → 15px (matches `--wpds-typography-font-size-lg` and
the unified-header direction discussed in WP Core; sits at the
intersection of both proposed token systems).
- font-weight: 600 → 500 (matches `--wpds-typography-font-weight-medium`;
was bolding to compensate for being small, now reads quieter at 15px).
- color: implicit / #070707 (Settings) / $gray-900 (Payments) → all now
$gray-900 on the shared rule (single source of truth, Gutenberg's
standard dark-text colour).
- padding-left: $gutter-large (var(--large-gap), ~40px) → $gap-large
(24px) to match the future-state design and the proposed
`--wp-admin-grid-unit-30` token in Trac #65085.
Chrome heights + spacing:
- Drop local `$woo-chrome-only-header-height` SCSS var, use
`$adminbar-height` from @wordpress/base-styles directly (same 32px,
same semantic intent: collapse to admin-bar height).
- `padding: 0 8px` literal on `.header-meta-icon` and
`.activity-panel-tab` → `padding: 0 $grid-unit-10` from base-styles.
Scroll shadow (internal-style-build/_variables.scss):
- Rewrite `$header-scroll-shadow` from a single 30%-alpha rgba drop to
a 4-layer subtle stack matching Gutenberg's `--wpds-elevation-xs`
aesthetic. Visually aligns with the modern WP elevation scale
without claiming a token name that isn't finalised yet.
Settings tab nav (legacy admin.scss):
- font-size: 14px → 13px (matches `$default-font-size` from
base-styles and `--wpds-typography-font-size-md`).
- padding-left: 30px → 24px to match the floating-header h1 above it
so the Settings title and tab labels sit on the same left edge.
- Drop the `.woocommerce-layout__header-heading` Settings-specific
block entirely — Settings now inherits the same heading typography,
weight, colour, and padding as Home and every other floating-header
page on every axis.
Title flash on chrome-only pages (header/style.scss):
- Add a CSS `:has(.wrap > h1.wp-heading-inline)` safety net that
collapses the bar to chrome-only height and hides the floating
h1 as soon as the page parses — before React has had a chance to
set the JS-driven `.is-chrome-only` class. Eliminates the brief
flash of the floating-header h1 that previously appeared on Edit
Order / Edit Product / Add Product / Products list / Orders list.
Net result: 4 Woo-specific overrides removed
(`#070707` near-black, `font-size: 16px` on Settings, `font-weight: 600`
on Settings, font-size + weight duplicates on Payments' `__title`,
`padding-left: 30px` on Settings, `$woo-chrome-only-header-height`
duplicate token, the single-layer `$header-scroll-shadow`). Plus 4
new alignments with WP base-styles tokens ($gap-large, $grid-unit-10,
$adminbar-height, $default-font-size) and 3 new alignments with the
direction of Gutenberg's design-tokens.css / Trac #65085 (font-size,
font-weight, elevation).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add changefile(s) from automation for the following project(s): woocommerce, woocommerce/client/admin
* Add changefile(s) from automation for the following project(s): woocommerce, woocommerce/client/admin
* Floating header: fix Marketplace User toggle vertical alignment
Side-effect of removing the `.woocommerce-layout__activity-panel-tab`
class from the HeaderAccount DropdownMenu outer wrapper — it was
unintentionally giving Marketplace's User toggle a 60px outer that
overflowed the 60px grid row symmetrically, masking the 7px delta
between the search input's `margin-top: 15px` and `__header-meta`'s
`padding-top: 8px`.
Add an explicit `margin-top: 7px` on the Marketplace-scoped
`__user-menu` rule to compensate. Net result: User toggle now sits
flush with the search input vertically — also accidentally fixing a
~1px misalignment that's been in production for a while.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Floating header: fix stylelint scss/comment-no-empty failures
Six `//` "paragraph break" lines inside multi-paragraph comment blocks
were tripping `scss/comment-no-empty`. Replaced each with a direct
join — the surrounding comment lines still read clearly without the
visual separator. Affects three files: header/style.scss, header-account.scss,
and settings-payments-body.scss.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Floating header: fix prettier formatting in header-account.tsx
Drop the redundant parens around the single-line `<Icon icon={ commentAuthorAvatar } size={ 18 } />` return — prettier wants the inline shorthand. Pure formatting, no behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Floating header: dedupe changelog entries
Two changelog files described the same change — one auto-generated by
the changelogger bot (PR-number-prefixed, canonical) and one I created
manually before the bot fired. Drop the manual one; the bot's entry has
the broader and more accurate description (mentions Settings, the WP
design-token alignment, and the override cleanup, not just the Home
header polish).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Floating header: address chihsuan review feedback
- Merge duplicate changelog into one entry
- Remove now-redundant adminbar-height comment in style.scss
- Drop orphaned __menu-avatar-image CSS rule and trim stale comment in header-account.scss
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add changefile(s) from automation for the following project(s): woocommerce, woocommerce/client/admin
* Floating header: address chihsuan round-2 feedback
- Fix flash of native Screen Options / Help buttons by hiding via the
server-rendered .woocommerce-admin-page body class instead of :has()
- Trim bug-context from DisplayIcon and HeaderAccount comments; keep only
the durable WHY (token source / React remount prevention)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/packages/js/internal-style-build/abstracts/_variables.scss b/packages/js/internal-style-build/abstracts/_variables.scss
index 6eb3c5ff840..9270dda6a4b 100644
--- a/packages/js/internal-style-build/abstracts/_variables.scss
+++ b/packages/js/internal-style-build/abstracts/_variables.scss
@@ -25,7 +25,20 @@ $gap-smallest: 4px;
// Header
$header-height: 60px;
$header-border-width: 1px;
-$header-scroll-shadow: 0 8px 8px 0 rgba(85, 93, 102, 0.3);
+// Matches Gutenberg's `--wpds-elevation-xs` (subtle 4-layer drop with
+// very low alphas) visually without binding to a CSS custom property
+// that isn't loaded on wp-admin pages yet. Previously a single heavy
+// 30% rgba drop — replaced with the modern WPDS layered shadow
+// aesthetic.
+// TODO: swap to `var(--wpds-elevation-xs, [these layers as fallback])`
+// once WP exposes design-tokens.css globally on wp-admin pages
+// (tracked in https://core.trac.wordpress.org/ticket/65085 and the
+// unified admin header discussion at WordPress/gutenberg#76709).
+$header-scroll-shadow:
+ 0 1px 1px 0 #00000008,
+ 0 1px 2px 0 #00000005,
+ 0 3px 3px 0 #00000005,
+ 0 4px 4px 0 #00000003;
// Sidebar
$sidebar-width: 272px;
diff --git a/packages/js/internal-style-build/changelog/sprinkle-header-tokens-alignment b/packages/js/internal-style-build/changelog/sprinkle-header-tokens-alignment
new file mode 100644
index 00000000000..b64d30fa88a
--- /dev/null
+++ b/packages/js/internal-style-build/changelog/sprinkle-header-tokens-alignment
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Rewrite `$header-scroll-shadow` to a 4-layer subtle drop matching Gutenberg's `--wpds-elevation-xs` aesthetic, replacing the previous single heavy rgba shadow.
diff --git a/plugins/woocommerce/changelog/64885-sprinkle-preview-store-icon b/plugins/woocommerce/changelog/64885-sprinkle-preview-store-icon
new file mode 100644
index 00000000000..948726983f1
--- /dev/null
+++ b/plugins/woocommerce/changelog/64885-sprinkle-preview-store-icon
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Polish the floating WC Admin header across Home and Settings: store icon for View store / Preview store, even icon spacing, fix the user-options click race, align title typography / colour / padding to WordPress design tokens, and remove a bunch of one-off overrides that were drifting from the rest of the wp-admin chrome.
\ No newline at end of file
diff --git a/plugins/woocommerce/client/admin/client/activity-panel/activity-panel.js b/plugins/woocommerce/client/admin/client/activity-panel/activity-panel.js
index 4996024ccda..651a274a1a7 100644
--- a/plugins/woocommerce/client/admin/client/activity-panel/activity-panel.js
+++ b/plugins/woocommerce/client/admin/client/activity-panel/activity-panel.js
@@ -13,6 +13,7 @@ import {
bellUnread,
listView,
comment,
+ store,
} from '@wordpress/icons';
import { STORE_KEY as CES_STORE_KEY } from '@woocommerce/customer-effort-score';
import { H, Section } from '@woocommerce/components';
@@ -354,7 +355,11 @@ export const ActivityPanel = ( { isEmbedded, query } ) => {
};
const headerAccount = {
- component: () => <HeaderAccount page="wc-admin" />,
+ // Stable component reference — an inline arrow would give React a
+ // new component type on every parent render, remounting HeaderAccount
+ // and resetting its DropdownMenu's internal isOpen state.
+ component: HeaderAccount,
+ options: { page: 'wc-admin' },
visible: isHomescreen,
};
@@ -380,6 +385,12 @@ export const ActivityPanel = ( { isEmbedded, query } ) => {
( comingSoon === 'yes' &&
__( 'Preview store', 'woocommerce' ) ) ||
__( 'View store', 'woocommerce' ),
+ // Tiny shopfront icon for the literal "View store" / "Preview
+ // store" semantic, distinct from the other icons in the bar.
+ // Required because activity-panel tabs are now icon-only —
+ // a tab without an icon renders as an empty button on the
+ // floating header.
+ icon: <Icon icon={ store } />,
visible: isHomescreen && query.task !== 'appearance',
onClick: () => {
window.open( getAdminSetting( 'shopUrl' ) );
diff --git a/plugins/woocommerce/client/admin/client/activity-panel/display-options/icons/display.js b/plugins/woocommerce/client/admin/client/activity-panel/display-options/icons/display.js
index b9d30082201..581e30c78ac 100644
--- a/plugins/woocommerce/client/admin/client/activity-panel/display-options/icons/display.js
+++ b/plugins/woocommerce/client/admin/client/activity-panel/display-options/icons/display.js
@@ -1,7 +1,8 @@
export const DisplayIcon = () => (
<svg
- width="24"
- height="24"
+ // 18px matches every other floating-header icon (bell, listView, store, gear, ?).
+ width="18"
+ height="18"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
diff --git a/plugins/woocommerce/client/admin/client/activity-panel/style.scss b/plugins/woocommerce/client/admin/client/activity-panel/style.scss
index f99e629b267..41bd1604eff 100644
--- a/plugins/woocommerce/client/admin/client/activity-panel/style.scss
+++ b/plugins/woocommerce/client/admin/client/activity-panel/style.scss
@@ -72,9 +72,11 @@
background-color: transparent;
// Match wp-admin admin-bar item padding so all five icons in the bar
// (bell / list / megaphone / gear / ?) sit at the same tight spacing.
+ // $grid-unit-10 (8px from @wordpress/base-styles) instead of a
+ // literal so the value tracks the WP spacing scale automatically.
width: auto;
min-width: 0;
- padding: 0 8px;
+ padding: 0 $grid-unit-10;
height: $header-height;
// $gray-900 across all states (default, hover, active) — the blue
// underline alone signals active, matching Gutenberg's icon tab group.
diff --git a/plugins/woocommerce/client/admin/client/header/style.scss b/plugins/woocommerce/client/admin/client/header/style.scss
index 48c5be76a7f..2781542a05d 100644
--- a/plugins/woocommerce/client/admin/client/header/style.scss
+++ b/plugins/woocommerce/client/admin/client/header/style.scss
@@ -16,31 +16,19 @@
}
// Hide ONLY the two standard wp-admin meta-toggle wraps (Screen Options +
-// Help) that we proxy via the floating header's gear / ? icons. The parent
-// #screen-meta-links container is left alone so any third-party sibling
-// buttons (the rare plugin that injects its own `.screen-meta-toggle` div
-// directly into the strip) remain visible. Visually-hidden pattern (rather
-// than display:none) keeps the elements in the layout tree so wp-admin's
-// jQuery delegated click handlers still fire when we proxy .click() into
-// #show-settings-link / #contextual-help-link.
-// Defensive guard: only hide when the floating header's meta-icon button
-// has actually rendered (`:has(.woocommerce-layout__header-meta-icon)`).
-// If hasScreenOptions / hasContextualHelp detection misses for any reason,
-// :has() doesn't match and the user keeps access to the original wp-admin
-// strip rather than losing it entirely. Browsers without :has() support
-// (Firefox <121) also fall through to the safe state.
-.woocommerce-admin-page:has(.woocommerce-layout__header-meta-icon),
-body.woocommerce_page_wc-admin:has(.woocommerce-layout__header-meta-icon) {
+// Help) that we proxy via the floating header's gear / ? icons. Applied via
+// the server-rendered body class so the hide is immediate — no flash before
+// React mounts. The parent #screen-meta-links container is left alone so
+// third-party .screen-meta-toggle siblings remain visible. Visually-hidden
+// (not display:none) keeps the elements in the layout tree so wp-admin's
+// jQuery delegated click handlers still fire when we proxy .click().
+.woocommerce-admin-page {
#screen-options-link-wrap,
#contextual-help-link-wrap {
@include visually-hidden;
}
}
-// Chrome-only narrow-bar height (Edit Order, Edit Product, Add Product, etc.).
-// Now that activity-panel tabs are icon-only globally, they fit cleanly in 32px.
-$woo-chrome-only-header-height: 32px;
-
.woocommerce-layout__header {
// Background matches the wp-admin body grey so the bar reads as
// infrastructure rather than content. Needs to be explicit (not inherited)
@@ -87,12 +75,42 @@ $woo-chrome-only-header-height: 32px;
.woocommerce-layout__header-heading {
display: flex;
align-items: center;
- padding: 0 0 0 $fallback-gutter-large;
- padding: 0 0 0 $gutter-large;
+ // $gap-large (24px from @wordpress/base-styles) — matches the
+ // future-state design and the `--wp-admin-grid-unit-30` token
+ // proposed in https://core.trac.wordpress.org/ticket/65085.
+ // Previously $gutter-large (40px-ish, via var(--large-gap)),
+ // which left the floating-header h1 indented further than the
+ // Settings tab nav below it.
+ padding: 0 0 0 $gap-large;
height: $header-height;
background: transparent;
- font-weight: 600;
- font-size: 14px;
+ // 15px to align with the direction WP Core is heading for admin
+ // chrome headings (see WordPress/gutenberg#76709 for the
+ // in-progress unified admin header discussion). It's also the
+ // shared "lg" step between two parallel WP token systems:
+ // `--wpds-typography-font-size-lg: 15px` in Gutenberg's
+ // design-tokens.css, and `--wp-admin-font-size-l: 15px` in the
+ // admin tokens proposal at
+ // https://core.trac.wordpress.org/ticket/65085.
+ // Weight 500 (medium) instead of the previous 600 (semibold) —
+ // aligns with `--wpds-typography-font-weight-medium`. The old
+ // 14px + 600 combo was bolding to compensate for being small;
+ // 15px + 500 reads quieter while still clearly title-y.
+ // TODO: replace these literals with CSS custom properties once
+ // WP Core exposes admin design tokens at `:root`. Tracked in
+ // the Trac ticket above. Hardcoded for now because the proposed
+ // variable names (`--wp-admin-*` vs `--wpds-*`) aren't finalised
+ // yet.
+ font-size: 15px;
+ font-weight: 500;
+ // $gray-900 (#1e1e1e) from @wordpress/base-styles — Gutenberg's
+ // standard dark-text colour. Previously this rule had no explicit
+ // colour so Home picked up whatever default <Text> inherits,
+ // Settings overrode with `#070707` (custom near-black, not a
+ // token), and Payments overrode with `$gray-900`. Setting it
+ // once on the shared rule lets Settings + Payments drop their
+ // duplicates so all three pages render the same.
+ color: $gray-900;
&.woocommerce-layout__header-left-align {
flex: 1 auto;
@@ -121,9 +139,11 @@ $woo-chrome-only-header-height: 32px;
background-color: transparent;
height: $header-height;
// wp-admin admin-bar items use ~0 8px horizontal padding each side;
- // match it for a tight, infrastructure-y spacing.
+ // match it for a tight, infrastructure-y spacing. $grid-unit-10
+ // (8px from @wordpress/base-styles) instead of a literal so the
+ // value tracks the WP spacing scale automatically.
min-width: 0;
- padding: 0 8px;
+ padding: 0 $grid-unit-10;
// $gray-900 across all states (default, hover, active) — the blue
// underline alone signals active, matching Gutenberg's icon tab group.
color: $gray-900;
@@ -186,22 +206,52 @@ $woo-chrome-only-header-height: 32px;
// Inner activity-panel and meta-icon items also collapse so they fit cleanly.
&.is-chrome-only {
.woocommerce-layout__header-wrapper {
- height: $woo-chrome-only-header-height;
- min-height: $woo-chrome-only-header-height;
- max-height: $woo-chrome-only-header-height;
+ height: $adminbar-height;
+ min-height: $adminbar-height;
+ max-height: $adminbar-height;
overflow: hidden;
}
.woocommerce-layout__activity-panel-tabs,
.woocommerce-layout__activity-panel-tab,
.woocommerce-layout__header-meta-icon {
- height: $woo-chrome-only-header-height;
- min-height: $woo-chrome-only-header-height;
- max-height: $woo-chrome-only-header-height;
+ height: $adminbar-height;
+ min-height: $adminbar-height;
+ max-height: $adminbar-height;
}
}
}
+// CSS-level safety net for the chrome-only treatment. When wp-admin
+// renders its own `<h1 class="wp-heading-inline">` (Edit Order / Edit
+// Product / Add Product / Products list / Orders list / etc.), apply
+// the same hide-title + collapse-to-adminbar-height treatment as the
+// JS-set `.is-chrome-only` class above — but as soon as the browser
+// parses the DOM, before React has had a chance to set the class.
+// This kills the brief flash of the floating-header h1 that
+// previously appeared between first paint and React state commit.
+// `:has()` is in every browser we support (Chrome 105+, Safari 15.4+,
+// Firefox 121+). Older browsers fall through to the JS-driven class
+// path above and still work — they just get the small flash.
+body:has(.wrap > h1.wp-heading-inline) {
+ .woocommerce-layout__header-heading {
+ display: none;
+ }
+ .woocommerce-layout__header-wrapper {
+ height: $adminbar-height;
+ min-height: $adminbar-height;
+ max-height: $adminbar-height;
+ overflow: hidden;
+ }
+ .woocommerce-layout__activity-panel-tabs,
+ .woocommerce-layout__activity-panel-tab,
+ .woocommerce-layout__header-meta-icon {
+ height: $adminbar-height;
+ min-height: $adminbar-height;
+ max-height: $adminbar-height;
+ }
+}
+
.folded .woocommerce-layout__header {
width: calc(100% - 36px);
diff --git a/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.scss b/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.scss
index 884e930b576..3c822c947ac 100644
--- a/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.scss
+++ b/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.scss
@@ -1,14 +1,19 @@
@import "../../stylesheets/_variables.scss";
.woocommerce-marketplace {
- &__menu-item span {
- white-space: normal;
+ // Connected-user avatar in the floating-header toggle — locked to 18px
+ // so the User button matches every other tab in the bar regardless of
+ // sign-in state.
+ &__header-account-avatar {
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ display: block;
+ object-fit: cover;
}
- &__menu-avatar-image {
- border-radius: 50%;
- height: $grid-unit-30;
- width: $grid-unit-30;
+ &__menu-item span {
+ white-space: normal;
}
&__menu-icon {
@@ -37,9 +42,39 @@
}
}
- &__user-menu {
+ // HeaderAccount renders in two places — the WC Home floating-header
+ // activity-panel tab strip, and the Marketplace page's own header
+ // next to a search input. The default toggle structure doesn't
+ // stretch / centre vertically on its own, so we explicitly handle
+ // both contexts:
+ // - Floating header (inside `.woocommerce-layout__activity-panel-tabs`):
+ // wrapper stretches to the 60px bar height so the User tab aligns
+ // with its neighbours (bell / store / display / help).
+ // - Marketplace page (inside `.woocommerce-marketplace__header`):
+ // wrapper sits at 40px to match the WP 7.0-height search input
+ // beside it.
+ // Both rules scope to their parent container rather than styling
+ // `__user-menu` unconditionally, otherwise the Home rule would leak
+ // onto Marketplace (and vice versa).
+ .woocommerce-layout__activity-panel-tabs &__user-menu {
+ display: flex;
+ align-items: stretch;
+ height: $header-height;
+ }
+
+ &__header &__user-menu {
+ // Inner toggle button is 40px to match the WP 7.0-height search
+ // input next to it. The 7px top offset compensates for the
+ // difference between the search input's `margin-top: 15px` (in
+ // search.scss) and the `padding-top: 8px` already on the parent
+ // `__header-meta` — without it, the User toggle visually sits
+ // ~7px higher than the search input. Previously masked by the
+ // removed `.activity-panel-tab` class overflowing the 60px grid
+ // cell.
+ margin-top: 7px;
+
> button.components-dropdown-menu__toggle {
- height: 40px; // Match WP 7.0 input height and align with adjacent search input.
+ height: 40px;
}
}
diff --git a/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.tsx b/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.tsx
index d9c99b907df..85fc88b6868 100644
--- a/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.tsx
+++ b/plugins/woocommerce/client/admin/client/marketplace/components/header-account/header-account.tsx
@@ -50,22 +50,33 @@ export default function HeaderAccount( {
const isConnected = wccomSettings?.isConnected ?? false;
const connectionURL = connectUrl( page );
const userEmail = wccomSettings?.userEmail;
- const avatarURL = wccomSettings?.userAvatar ?? commentAuthorAvatar;
+ const avatarURL = wccomSettings?.userAvatar;
const accountURL = MARKETPLACE_HOST + '/my-dashboard/';
const accountOrConnect = isConnected ? accountURL : connectionURL;
const isInApp = page === 'wc-addons';
const avatar = () => {
- if ( ! isConnected || useDefaultAvatar ) {
- return commentAuthorAvatar;
+ // Render the default avatar SVG when the user isn't connected, when
+ // the connected user has no avatar URL, or when the avatar image
+ // failed to load. Previously `avatarURL` fell back to the
+ // `commentAuthorAvatar` icon component, which is a JSX element —
+ // passing it as <img src> rendered `[object Object]` and only
+ // recovered via the onError handler below.
+ if ( ! isConnected || ! avatarURL || useDefaultAvatar ) {
+ return <Icon icon={ commentAuthorAvatar } size={ 18 } />;
}
+ // Lock the avatar to 18x18 to match every other floating-header tab
+ // icon (bell, store, listView, gear, ?). Without this the
+ // connected-user state renders the avatar at 30x30, making the User
+ // button wider than its neighbours — which knocks tab spacing out
+ // of alignment and creates timing issues with adjacent click flows.
return (
<img
src={ avatarURL }
alt=""
- className="woocommerce-marketplace__menu-avatar-image"
+ className="woocommerce-marketplace__header-account-avatar"
onError={ () => setUseDefaultAvatar( true ) }
/>
);
@@ -142,7 +153,15 @@ export default function HeaderAccount( {
return (
<>
<DropdownMenu
- className="woocommerce-layout__activity-panel-tab woocommerce-marketplace__user-menu"
+ // woocommerce-layout__activity-panel-tab is intentionally
+ // only on toggleProps (the inner button) — not on the outer
+ // DropdownMenu wrapper. Doubling it up made the User button
+ // 16px wider than its neighbours (padding compounded on
+ // both elements) and created a click "dead zone" on the
+ // outer wrapper that swallowed the first click when
+ // switching focus from another tab. Outer alignment is
+ // handled by `__user-menu` styles in header-account.scss.
+ className="woocommerce-marketplace__user-menu"
icon={ dropdownTrigger() }
label={ __( 'User options', 'woocommerce' ) }
toggleProps={ {
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/header/header.scss b/plugins/woocommerce/client/admin/client/settings-payments/components/header/header.scss
index 2309f42671f..4d24182c6e0 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/header/header.scss
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/header/header.scss
@@ -5,10 +5,13 @@
.woocommerce-layout__header-heading {
.woocommerce-settings-payments-header__title {
- color: $gray-900;
- font-size: 16px;
+ // font-size, font-weight, AND color all inherit from the
+ // shared `.woocommerce-layout__header-heading` rule
+ // (15px / 500 / $gray-900, in client/admin/client/header/
+ // style.scss). Dropped the duplicate 16px + 600 + $gray-900
+ // overrides here so all floating-header titles stay in
+ // lockstep on the same tokens.
font-style: normal;
- font-weight: 600;
line-height: 24px;
}
}
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss
index 44240eb9423..c6a553ba411 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss
+++ b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss
@@ -4,9 +4,21 @@ html {
font-family: $font-sf-pro-display;
}
-body.woocommerce-settings-payments-tab {
- #mainform,
- #wpcontent {
+// Payments tab keeps its main content panel white while letting the tab
+// strip above it sit on the wp-admin body grey, matching every other
+// Settings tab. Target the strip and the form explicitly rather than
+// changing #wpbody-content — that container's background is set by the
+// parent body.woocommerce_page_wc-settings rule in legacy admin.scss,
+// and the bg-color isn't doing structural work inside it, just
+// determining what shows through the (transparent) .nav-tab-wrapper.
+// Doubled-up body class on the outer selector is intentional: same
+// flat specificity as the legacy rule, so the doubled class wins it
+// regardless of load order.
+body.woocommerce_page_wc-settings.woocommerce-settings-payments-tab {
+ .nav-tab-wrapper {
+ background-color: #f0f0f1;
+ }
+ #mainform {
background-color: #fff;
}
}
diff --git a/plugins/woocommerce/client/legacy/css/admin.scss b/plugins/woocommerce/client/legacy/css/admin.scss
index 1f94df85062..90fcffa7520 100644
--- a/plugins/woocommerce/client/legacy/css/admin.scss
+++ b/plugins/woocommerce/client/legacy/css/admin.scss
@@ -9359,12 +9359,15 @@ body.woocommerce_page_wc-settings {
}
}
- .woocommerce-layout__header-heading {
- padding: 0 0 0 30px;
- font-weight: 600;
- font-size: 16px;
- color: #070707;
- }
+ // Heading typography (font-size, font-weight, colour) AND left
+ // padding now all live in the shared
+ // `client/admin/client/header/style.scss` rule (15px / 500 /
+ // $gray-900 / $gutter-large — aligned to Gutenberg's WPDS tokens
+ // and the unified admin header direction in
+ // WordPress/gutenberg#76709). Dropped the entire Settings-specific
+ // override (font-size 16px, font-weight 600, color #070707, padding
+ // 30px) so Settings renders identically to Home and every other
+ // floating-header page on every axis.
#wpbody .woocommerce-layout,
.woocommerce-layout__notice-list-hide + .wrap {
@@ -9410,7 +9413,15 @@ body.woocommerce_page_wc-settings {
display: flex;
flex-wrap: wrap;
list-style: none;
- padding-left: 30px;
+ // 24px to match the floating-header title's `$gap-large` (from
+ // @wordpress/base-styles) so the "Settings" h1 above and the
+ // "General / Products / ..." tab labels below line up on the
+ // same left edge. Also matches the future-state design and
+ // `$grid-unit-30` / `--wp-admin-grid-unit-30` in the admin
+ // tokens proposal at https://core.trac.wordpress.org/ticket/65085.
+ // Legacy admin.scss can't import the shared SCSS variables file
+ // directly, hence the literal.
+ padding-left: 24px;
padding-right: 24px;
gap: 24px;
@@ -9433,7 +9444,13 @@ body.woocommerce_page_wc-settings {
border: 0;
background: none;
font-weight: 500;
- font-size: 14px;
+ // 13px to match WP's `$default-font-size` (from
+ // @wordpress/base-styles) and Gutenberg's
+ // `--wpds-typography-font-size-md` (13px). Reads as quieter
+ // chrome below the 15px floating-header h1, restoring the
+ // chrome → tabs → content hierarchy the previous 14px size
+ // was already aiming at.
+ font-size: 13px;
line-height: 20px;
color: #505050;
padding: 0 0 10px 0;