Skip to content

ui: Use standard icons for Stepper indicators - #111628

Draft
bogiii wants to merge 12 commits into
trunkfrom
update/stepper-indicator-icons
Draft

bogiii wants to merge 12 commits into
trunkfrom
update/stepper-indicator-icons

Conversation

@bogiii

@bogiii bogiii commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Part of the review feedback on #111036

Proposed Changes

  • Replace CSS-drawn bullet indicators with standard @wordpress/icons for upcoming, current, completed, and error states.
  • Use a 24px indicator layout box with 18px visible icon and number circles.
  • Keep number indicators for upcoming and current steps in the number variant. Completed and error steps still use icons.
  • Use semantic WPDS colors for each state and hover.
Vertical Stepper variants Horizontal Stepper variants

Why are these changes being made?

  • The review on feat(ui): add Stepper component to @automattic/ui #111036 asked for standard WordPress icons and one indicator layout size.
  • The stock icons keep the Stepper aligned across states and remove custom SVG and CSS indicator drawing. Their filled rings are slightly thicker than the 1px Figma ring; design accepted that tradeoff while stroke-based icons are unavailable.

Testing Instructions

  1. Run yarn workspace @automattic/ui storybook:start.
  2. Open UI/Stepper/Vertical → Step Variants and confirm that upcoming, current, completed, error, and disabled states use the expected icon and color.
  3. Open UI/Stepper/Horizontal → Step Variants, set indicatorVariant to number, and confirm that upcoming and current steps use 18px number circles while completed and error steps use 18px icons.
  4. Hover enabled steps and confirm that the title and icon use the brand color.
  5. Open UI/Stepper/Horizontal → Mobile View at 375px and confirm that indicators and connectors remain aligned.

Pre-merge Checklist

  • Has the general code quality been checked?
  • Have you written new tests for your changes, if applicable?
  • Have you created or updated development documentation for your changes?
  • Have you checked for TypeScript, React or other console errors?
  • Have you checked the functionality in dark mode?
  • Have you checked the functionality for accessibility? (e.g. Keyboard, screen readers, etc.)
  • Have you checked the functionality on different browser sizes?
  • Have you considered using useCallback() for event handlers passed to child components?
  • Have you considered memoizing derived values that may be expensive to compute?
  • Have you considered string freeze implications for new user-facing strings?
    • Have you considered localization implications for new user-facing strings?
  • For changes affecting Jetpack: Have you added or updated privacy annotations where needed?

@github-actions

Copy link
Copy Markdown

Looks like one of the E2E tests has failed.

You can fix them following these steps:

  1. Check out this branch locally:
    gh pr checkout 111628
  2. Start Claude Code in the repo:
    claude
  3. Run the /fix-e2e-tests skill, passing this PR number:
    /fix-e2e-tests 111628
    

@matticbot

matticbot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

This PR modifies the release build for the following Calypso Apps:

For info about this notification, see here: PCYsg-OT6-p2

  • agents-manager
  • blaze-dashboard
  • help-center
  • notifications
  • odyssey-stats
  • wpcom-block-editor
  • wpcom-smart-dictation

To test WordPress.com changes, run install-plugin.sh $pluginSlug update/stepper-indicator-icons on your sandbox.

@bogiii bogiii self-assigned this Jun 12, 2026
// Render the glyph circle at the Figma size (16 -> 18) without affecting
// the 24px layout box.
svg {
transform: scale( calc( 18 / 16 ) );

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The default glyph size for the 24px viewBox is 16px (the icons bake the circle into the path). I initially kept everything at the library defaults, but the circles looked too small next to the Figma spec, so I scale them up to 18px here, which matches much better.

Still not ideal: the ring is baked into the glyph at 1.5 units, so after scaling it renders at ~1.7px, thicker than the 1px in Figma. Thinning it would require custom SVGs, which conflicts with the "use standard icons" feedback.

@ciampo, @nuriapenya, @jameskoster; I'm open to suggestions.

16px icon
Image
18px icon
Image

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.

Maybe the play here is to use a custom icon for the circle / half-circle icons.

I wonder if this will improve if/when we switch these icons to be stroke-based (instead of fill-based), since we should be able to scale them up while retaining the correct stroke width

cc @jasmussen

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi, thanks for the ping, and generally I'm always happy to respond to pings both on the system side (even if I'm not as versed as Jay is, he's out for a bit), and especially on the icon side as I've drawn a lot of them.

And if we need a custom icon, I can help make that happen. But if the question is: do we go 16px or 18px, there are a couple of near term answers, but one long term answer that if all goes well brings still more flexibility.

I'll start with the perspective. In WordPress/gutenberg#78808 I'm redrawing all the icons to be stroke-based, and to maintain their stroke-width when scaling down. That means you will be able to show the icons at any size and they will maintain their stroke-width. Theoretically it also opens the door to customizing the stroke-width to be just right for the context. We'll likely want to author some guidelines on best practices here, but for implementations like this, well that's what the PR exists to mitigate. The PR has been a while in review, but there's recent feedback, I'm hoping to rebas e

In the mean time, I find that 16px and 18 both alias reasonably, but theoretically 18 should interpolate better. Badge uses icons at 16px. But 18 seems fine too. Shown below, 16, 18, 24

Frame 1

If we zoom in the interpolation math of the 18 scale checks out:

aliased

But to get to the heart of it: you can use icons, we're happy to provide new ones, and stroke-based should bring lots of options to this specific option.

But, as Marco says, if doing something custom here (and honestly it could be CSS) is better for the time being, I'm not personally opposed to it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks @jasmussen, that's really helpful, and great to hear the stroke-based redraw in WordPress/gutenberg#78808 is close.

In this PR I found and matched the proper existing @wordpress/icons for the Stepper indicators, replacing the previous ad-hoc approach. That part worked out well. The one new wrinkle is the circle ring: at the 18px size I settled on, it renders a touch thick. There's only one consumption of the Stepper component so far, and I'll share screenshots below showing how it looks with this PR's changes, which should make the tradeoff clearer.

I had a look through that PR, and the icons we use for the Stepper are already covered there (they're marked in black in the screenshot), which is a nice sign that this is well in hand.

Given that, I'd rather not invest in custom SVGs now. My proposal: keep the standard @wordpress/icons at 18px for this PR and accept the slightly thicker ring as a known, temporary tradeoff until we update to the stroke-based icons. At that point we can scale them cleanly and dial the stroke-width in to match the spec, with no custom maintenance burden.

Does that work for you ( @ciampo, @jasmussen, @nuriapenya ) as an interim step?

Image Image Image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Noting also as soon as the first set of stroke based icons land, I will immediately follow up with WordPress/gutenberg#78812, and then more for the rest of the icons.

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.

Good for me technically (I'll review the rest of the PR once it's out of draft), this feels like more of a design decision (cc @nuriapenya )

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.

I'd rather not invest in custom SVGs now. My proposal: keep the standard @wordpress/icons at 18px for this PR and accept the slightly thicker ring as a known, temporary tradeoff until we update to the stroke-based icons.

That's reasonable and works for me, too! Thanks @bogiii

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Noting by the way that stroke-based icons are on the way: WordPress/gutenberg#81274

@github-actions

Copy link
Copy Markdown

This PR has been marked as stale. This happened because:

  • It has been inactive for the past 3 months.
  • It hasn't been labeled `[Pri] BLOCKER`, `[Pri] High`, `[Status] Keep Open`, etc.

If this PR is still useful, please do a trunk merge or rebase and otherwise make sure it's up to date and has clear testing instructions. You may also want to ping possible reviewers in case they've forgotten about it. Please close this PR if you think it's not valid anymore — if you do, please add a brief explanation.

If the PR is not updated (or at least commented on) in another month, it will be automatically closed.

bogiii and others added 12 commits August 27, 2026 17:38
The state icons draw a 16px circle inside their 24px viewBox. Draw the
number-variant circle on the inner number span at the same 16px size
(via a component token) so both variants render identically, while the
24px indicator layout box is unchanged. The number span only exists for
statusless number-variant steps, so the completed/error guards on the
circle rules are no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scale the icon glyphs (which draw a 16px circle inside the 24px
viewBox) by 18/16 and size the number-variant circle from the same
18px token, so both variants match the Figma circle size while the
24px layout box is unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drop the separate icon-indicators describe block; the error-status test
already asserts bullet icons render, and the indicatorVariant test now
covers status steps rendering icons instead of numbers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The error indicator no longer renders a literal "!", so asserting its
absence checks nothing; the svg assertion covers the icon rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ciampo
ciampo force-pushed the update/stepper-indicator-icons branch from e12922e to 3855fe3 Compare August 27, 2026 15:42
@ciampo ciampo changed the title ui: Stepper indicators with standard @wordpress/icons at a single 24px size ui: Use standard icons for Stepper indicators Aug 27, 2026
@github-actions

Copy link
Copy Markdown

Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

Sections (~809 bytes added 📈 [gzipped])

Details
Name Parsed Gzip
async-step-unified-plans +2.44 kB +0.2% +773 B +0.2%
a8c-for-agencies-express-checkout +1.44 kB +0.1% +613 B +0.1%
a8c-for-agencies-client +1.44 kB +0.0% +613 B +0.1%
a8c-for-agencies-marketplace +1.44 kB +0.1% +613 B +0.1%
checkout +1.44 kB +0.1% +613 B +0.1%

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.

Async-loaded Components (~773 bytes added 📈 [gzipped])

Details
Name Parsed Gzip
async-load-signup-steps-plans-theme-preselected +2.44 kB +0.3% +773 B +0.3%
async-load-signup-steps-plans +2.44 kB +0.3% +773 B +0.3%

React components that are loaded lazily, when a certain part of UI is displayed for the first time.

Legend

What is parsed and gzip size?

Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
Gzip Size: Compressed size of the JS and CSS files. This much data needs to be downloaded over network.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants