Repository navigation
Restyle all plugin badges per the refreshed design system #13361
Description
Feature Description
The hub's cards carry badges — New, Paid service — and the design system has moved on since Site Kit's badges were built: corners are less rounded now, and the New badge's colours are the other way round, the lighter shade behind the darker text rather than the reverse.
The design system gives those colours badge by badge, naming each by the words it carries — New, Recommended, Beta, Paid service, and so on — and read across the set they fall into a handful of groups by what they tell the user. So this issue is as much about which badge belongs to which group as it is about the colours: Beta and Experimental are both grey today while they say quite different things, and New is shown one way in some places and another elsewhere.
This is a design-system change, not a hub one. Rather than have the hub style its own badges and leave the rest of the plugin looking dated beside it, the shared badge styling is updated once and every badge in Site Kit picks up the new look, with the hub simply using them as they come. The work is plugin-wide, and so is the check on it.
For reference, see the UI component architecture section in the design doc, and the refreshed badge designs in the Figma design system.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
- Every badge in Site Kit takes a reduced corner radius, and its colours from the refreshed design system. Those colours group into six treatments by what the badge tells the user, and every badge belongs to one of them wherever it appears:
- Announcement — violet — New, Beta.
- Recommendation — blue — Recommended.
- Cost — green — Paid service.
- Experimental — pink — Experimental.
- Warning — amber — Action needed, Temporarily hidden, Partial data, Gathering data and Gathering breakdown data.
- A badge these groups don't name joins the one whose meaning fits it, rather than keeping its old look or being given a colour of its own. And where the same text is styled differently in different places — New is plain grey in selection panels, Recommended has a style of its own on the setup splash screen — it converges on a single look.
- Recommended for you and Requires plugin update are in the design system but unused in the plugin, so they're out of scope here.
- The empty badges used only to reserve space, in the visitor group tiles and the dashboard data blocks, go on reserving exactly the space they do now and take no colour.
- The badges whose text comes from data rather than a fixed label — the percentage change badges, and the PageSpeed ratings in the PDF report — keep the colours they have today and take the corner radius alone.
- The corner radius reaches every badge, including those drawn into the PDF report from outside Site Kit's stylesheets, and reaches nothing else: the rounding shared with buttons, chips and tabs is left as it is.
- The change is made to Site Kit's shared badges, so no hub-specific badge styling is left behind — including any the hub's cards introduced ahead of this issue (Build
FeatureCard+EffortIndicator(Storybook) #13320). - The badges match the Figma design system.
Implementation Brief
Establish the shared badge system first, then roll it out and remove the styling it supersedes.
In assets/sass/config/_variables-mui3.scss
- Add
$br-xxs: 4pxfor the reduced corner radius. Do not change$br-lg, which resolves to100pxand is shared with buttons, chips and tabs. - Add a
$c-badge-{group}-background/$c-badge-{group}-textpair for each semantic group in the ACs, pointing at existing ramps. Backgrounds take the-50step and text-500, except warning, whose text is-700. Note the AC colour names do not all map to the ramp/token of the same name: green is$c-site-kit-sk-*, and amber is$c-yellow-y-*. Leave the$c-utility-*tokens in place — around fourteen non-badge rules still use them.
Create assets/js/components/Badge/constants.ts
- Export a BADGE_VARIANTS const enum whose members are the semantic groups from the ACs, following Notice/constants.ts, including its per-member doc comments where a group needs explaining.
Move assets/js/components/Badge.js to assets/js/components/Badge/index.tsx
- Convert to TypeScript as part of the move. Replace the PropTypes block with a colocated
BadgePropsinterface and theFC< BadgeProps >plusforwardRef< HTMLSpanElement, BadgeProps >form documented incomponent-conventions.md, keeping the types in the component file rather than atypes.ts. The interface must admit arbitrary span attributes, since the component spreads the rest of its props andDataBlock/Contentpassesaria-hiddenthrough it. - Move
Badge.stories.jsalongside it asindex.stories.tsx, followingTypographyfor theindex.*naming andNoticefor the TypeScript story form. Existing@/js/components/Badgeimports resolve unchanged; only the story's relative import needs adjusting. - Add an optional
variantprop typed againstBADGE_VARIANTS, renderinggooglesitekit-badge--${ variant }alongside the base class asNoticedoes withtype. No default — omitting it must leave the badge uncoloured, which the space-reserving usage relies on. KeepclassNamefor layout and spacing. - Leave
NewBadge.jsandBadgeWithTooltip.jsflat.SetupModuleimportsNewBadgewith an explicit.jsextension, which a move would break.
In assets/js/components/BadgeWithTooltip.js
- Add the same
variantprop, defaulting to the warning group and overridable — mirroringNotice's default and preserving current behaviour, since the component is hardcoded amber today. Note it renders its own element rather than composingBadge, so it applies the variant class itself. This file is modified in place rather than moved, so it stays JavaScript and validates the prop withPropTypes.oneOf( Object.values( BADGE_VARIANTS ) ), asNotice/Icon.jsdoes againstNOTICE_TYPES.
In assets/sass/components/global/_googlesitekit-badge.scss
- Apply
$br-xxsand add a rule per semantic group reading from the new badge tokens. Re-point the existing--warningmodifier from$c-utility-warning-container/$c-utility-on-warning-containerto the badge tokens; these resolve to the same values, so its colour is unchanged and only its radius moves. Variant rules should never read$c-utility-*or a raw ramp directly. - Remove the
--primary,--betaand--warningcolour modifiers once callers are migrated. Keep--hiddenand--has-left-spacing, which are layout.
In assets/sass/components/global/_googlesitekit-badge-with-tooltip.scss and _googlesitekit-new-badge.scss
- Take the badge and info-icon colours from the variant rather than hardcoding them; the icon should use the variant's text colour.
- Reduce
_googlesitekit-new-badge.scssto its spacing and tooltip rules, dropping the colours the announcement variant now provides.
In assets/sass/components/global/_googlesitekit-change-badge.scss
- Apply
$br-xxsonly. Change badges are data-driven and keep their colours, as do the PageSpeed rating badges.
In assets/sass/components/key-metrics/_googlesitekit-chip-tab-group.scss
- Remove the badge override, which re-declares violet by hand and is why "New" renders differently in the chip tabs. Spacing-only badge overrides elsewhere may remain.
In assets/sass/components/setup/_googlesitekit-splash.scss
- Reduce the
.googlesitekit-splash__analytics-recommended-badgeselector to the spacing rules only (margin-left), dropping the colours and border-radius the variant now provides.
Across the badge call sites
- Pass the appropriate
variantper the groupings in the ACs, dropping the colour class where one is passed. 12 files need a variant added, 7 of which pass a colour class today. Note that Beta now belongs to the announcement group alongside New, so the four sites currently passinggooglesitekit-badge--betatake the same variant as the New badges:assets/js/components/NewBadge.jsassets/js/components/KeyMetrics/KeyMetricsNewBadge.jsassets/js/components/SelectionPanel/SelectionPanelItem.jsassets/js/components/settings/SettingsCardConsentMode.jsassets/js/components/settings/SetupModule.js— two badges, different variantsassets/js/components/settings/SettingsActiveModule/Header.js— two badges, different variantsassets/js/components/google-tag-gateway/GoogleTagGatewayToggle.jsassets/js/components/setup/SetupUsingProxyWithSignIn/AnalyticsOptIn.tsxassets/js/modules/adsense/components/common/UseSnippetSwitch.jsassets/js/modules/sign-in-with-google/components/setup/SetupMain.jsassets/js/modules/pagespeed-insights/components/common/ReportMetric.jsassets/js/modules/reader-revenue-manager/components/settings/SettingsStatus.tsx— a warning-group label renderingBadgedirectly, so it must state its variant rather than inheritingBadgeWithTooltip's defaultassets/js/components/feature-discovery/FeatureCard.tsx– Its badges come from a map of feature badge slugs to props carrying their labels, so each entry in that map needs a variant adding, rather than a variant being passed
- Components consuming the
NewBadgewrapper need no change, since the wrapper sets its own variant; nor do theBadgeWithTooltipcallers, which are all warning-group and inherit its default. - Define the Cost group's token pair, style rule, and story, but do not introduce that badge into any existing UI, since nothing renders it yet. The two design-system badges the ACs omit are out of scope, since the plugin doesn't use them.
- Leave the space-reserving badge in
assets/js/components/DataBlock/Content.jsas it is. It uses the--hiddenmodifier with a placeholder label to reserve height, passes no variant, and so keeps its current dimensions without colour.
In assets/js/components/pdf-export/
- Apply the new radius to
PDFBadge, whose radius is set in a React-PDF stylesheet rather than SCSS and so is not reached by the SCSS changes. - Align
PDFPartialDataBadgewith the warning group's text colour. It carries a fixed label rather than data-driven text, so the ACs' data-driven exemption does not cover it, and it currently takes its text fromYELLOW_Y_600— a step lighter than the warning token, so the PDF and on-screen versions of that badge differ today. This needsYELLOW_Y_700adding to thePDF_COLORSmap inpdf-theme.ts, which mirrors the SCSS tokens by hand with the token name in a trailing comment.
Test Coverage
- Add unit tests for
BadgeandBadgeWithTooltipas.tsx, neither of which has any today, covering that each variant produces its modifier class, that omittingvariantleavesBadgeuncoloured whileBadgeWithTooltipfalls back to its default, that an explicit variant overrides that default, and that a caller-suppliedclassNamestill applies. - Regenerate the four snapshots that capture badge markup —
GoogleTagGatewayToggle,SetupUsingProxyWithSignIn,AudienceTilesWidget/AudienceTileand the site-goalsIntroModalBanner. Two containgooglesitekit-badge--betaoutright, and all four capture aclassNamethat changes once badges carry a variant. - Update the two PDF badge tests that assert on values this issue changes:
PDFBadge.test.tsxasserts the oldborderRadiustwice, andPDFPartialDataBadge.test.tsxassertsYELLOW_Y_600.PDFChangeBadge.test.tsxasserts colours only and is unaffected. - No other existing unit tests need updating; the three that reference a badge class all query base classes that survive, and none asserts on the modifiers being removed.
- No PHPUnit or E2E changes needed; badges are entirely client-side and no E2E test references one.
- Add per-variant stories for both components, plus an aggregate "all variants" VRT story each, following the pattern used for buttons and links. This is required for capture — Backstop only emits a scenario for a story declaring a
scenarioobject, and the currentBadgestory declares none, which is why no badge reference image exists today. - VRT changes expected: two new references from the aggregate stories, plus re-approval of the five existing scenarios that render badges — the tooltip badge, the forced-open new badge, the selection panel, and the two audience selection panel scenarios. The warning badge's colours do not change, so an unchanged warning badge is the expected result there.
QA Brief
Every badge in the plugin changes shape in this issue, and most also change colour, to match the Figma design linked in the issue. Buttons, chips and tabs keep their pill shape and must be unchanged.
- Connect and complete setup for Analytics and AdSense.
- In Site Kit Tester → General, enable the
featureDiscoveryHubandsetupFlowRefreshfeature flags, and set Force initial Site Kit plugin version to1.0.0. The version is what makes the hub show its New badges;setupFlowRefreshkeeps the visitor groups and key metrics widgets from being hidden. - In Site Kit Tester → Analytics → General, set Force Analytics Audiences to
has-site-kit-created-audiencesand Force Analytics report data toall-reports-random-data. - In Site Kit Tester → Analytics → Partial Data, set Force Analytics audience partial data state to
last-7-days. - Go to Site Kit → Add Features → All services and features. On the card Increase your visibility in Search, check there is a violet New badge and a green Paid service badge, both matching Figma.
- Go to Site Kit → Settings → Connect More Services. Check the Beta badge beside Sign in with Google is violet — it was grey before this change.
- Go to Site Kit → Settings → Connected Services → AdSense → Edit. Check the Recommended badge beside Let Site Kit place AdSense code on your site is blue.
- Go to the Site Kit dashboard → Traffic tab and find the visitor groups tiles. Check each tile header shows an amber Partial data badge, and that the ⓘ icon inside the badge is the same dark amber as the badge's text — not grey.
- In Site Kit Tester → Analytics → Conversion Reporting, set Force "New" badge for selected events to Force new badge for selected events and select every event under "New" badge events. Save, then open Change metrics on the Key metrics tab: the New badges are now pale violet with violet text, where they were solid violet with white text before this change. This is the only badge in the plugin that inverts, so it is worth looking at closely.
- Open Select groups on the Traffic tab and check its New badges are the same pale violet. They were grey before this change.
- On the Key metrics tab, add a numeric metric such as New visitors via Change metrics. Check its percentage change badge keeps its existing colours — green for a rise, red for a fall, grey for no change — with the Figma corner radius.
- Use the Download PDF report icon in the top right of the dashboard header. Check the badges in the PDF have the same corner radius as on the dashboard, and that a Partial data badge in the PDF is the same amber as the dashboard one.
- Across all of the above, check that buttons, chips and dashboard tabs still have their pill shape. Their radius must not change.
Notes for the tester
The Experimental variant has no instance anywhere in the plugin, so check it in Storybook under Components/Badge rather than hunting for a screen.
The empty space-reserving badge is invisible by design and nothing renders it, so there is nothing to look at. It is covered by unit and visual regression tests.
Changelog entry
- Update all badges to match the new design.
Activity
techanvil commentedon Sep 7, 2026
Hi @ncoetzer! Thanks for drafting this IB, which is looking good. A few points:
PDFPartialDataBadgewill need updating to align with the text warning colour.19 remaining items
ncoetzer commentedon Sep 29, 2026
A few things changed between writing the IB and executing it, mostly because the work for #13320 merged into
developin between:Badgewas already TypeScript. The conversion the IB describes was already ondevelop, so only the directory move and thevariantprop were left to do.FeatureCardis now a call site, via aFEATURE_BADGE_PROPSmap carrying a// TODO: #13361marker. This makes the Cost group live, where the IB expected it to be defined but unused — the Ads module declares it. The map's third entry, Recommended for you, is given the recommendation variant for consistency but stays unused in the plugin, as the ACs describe.PDFChangeBadge.test.tsxneeded updating. Test Coverage says it is unaffected; it also assertsborderRadius, so three PDF tests changed rather than two.coloron.googlesitekit-info-tooltip, so acurrentColorfill turned the tooltip icon grey; reading a custom property keeps the badge's text colour in any context.EXPERIMENTAL_MODULESis empty and nothing passesexperimentalto the PageSpeed rows; nothing passesbadgetoDataBlock. Both are implemented and unit-tested but cannot be seen, which the QA Brief notes.I've left the IB and ACs as they are rather than editing them after the fact — happy to update either if you'd prefer.
techanvil commentedon Sep 29, 2026
Thanks for the context, @ncoetzer!
Leave the IB and AC as they were is the right call at this stage.
kelvinballoo commentedon Oct 8, 2026
QA Update⚠️
This is mostly tested good.
2 Items to flag however:
ITEM 1:
Based on Figma, the paddings are 4px top and bottom and 8 px on the sides.
Details
But our implementation shows 6px top, bottom and 10 px on the sides.
Is that an intentional change?
Details
ITEM 2:
I noticed that for the 'New' badges on the Key metrics selection panel, there is a 1px margin on the right side of the badges.
Again, is that intentional?
Details
ncoetzer commentedon Oct 8, 2026
@kelvinballoo Thanks for the review and feedback. In short, both are real, but the spacing in both cases predates this PR.
For item 1, the 6px/10px comes from the tooltip badge's own class. Badges without a tooltip are already 4px/8px. The same applies to item 2: the 1px margin was already there, and since the IB and AC only mentioned color and border radius updates, everything else was left as is.
That said, this should be fixed, and to avoid delays for this issue moving forward, I created a separate issue for it (#13822) — it needs its own PR that will include additional VRT updates.
kelvinballoo commentedon Oct 9, 2026
QA Update ✅
Thanks for the update @ncoetzer
With that, i'll move this to approval as the badges reflect the new design, inclusive of the PDF generated.
Details
13361 - 08 - PDF.pdf