Implement state UI for pseudo selectors on Global styles#75627
Implement state UI for pseudo selectors on Global styles#75627MaggieCabrera merged 8 commits intotrunkfrom
Conversation
|
Question: Should the canvas reflect the state we have selected or should it show the default state? I think we've had this problem before. The site editor doesn't really reflect well some of these states in certain blocks. |
|
Thanks for working on this, exciting! This is an important frontier to conquer. I had some trouble compiling the PR, got this error: It's very possibly an issue on my end, lmk. But I would say, your instincts sound on track: build this as a Global Styles first system for each block there. |
You caught me right in the middle of pushing changes, I think it should work now. |
|
At a glance, that looks like a good way to unstick this 👍 👍 |
|
Size Change: +847 B (+0.01%) Total Size: 6.89 MB
ℹ️ View Unchanged
|
|
Flaky tests detected in e160549. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/22953202250
|
|
Nice. This honestly feels so reasonable to me as a way to surface a UI, I feel it's worth landing, and certainly getting broader design feedback on soon. For me coming to mind mostly is that dropdown button: where should it sit and what should it look like. That's not an action item for you to work on right now, if anything it affirms: such a dropdown seems the right path forward. In saying that, I'm also affirming that means the UI will not afford making complex changes such as "hover+focus", or "resting+active". Is that even possible i theme.json? I.e. the equivalent of: I personally think it's fine, it's extra complexity for edge cases, and if you need something like the above, just update each selector. Re: showing the changes in the preview window, that seems reasonable too. I do wonder if we should—not in this PR—make a checkbox similar to what exists in the web-inspector? Something like, "preview changes in the canvas", which would effectively force every block in the editor to a particular state. |
Yeah I worked under the assumption that we are not working on combined selectors at the same time. I think it probably makes things too complicated for an edge case that can be handled by just styling each state separately. I'm also thinking about cases where states won't be 1:1 to pseudo selectors, but cases like "selected tab item" or "current nav item", where we are likely just targetting a class I like your idea of the state checkbox, it would work with a similar implementation of what I did for the preview, where I'm telling the preview to show a specific state, and add preview specific css for the state I want. The problem with my implementation is that we are missing the browser specific styles for pseudo selectors. This will not very noticeable in most themes, but an "empty" theme would be missing color changes to something like a link on hover state. |
|
@jasmussen how can we show states for elements? On a block like the paragraph it makes less sense to have the dropdown on top, but we still have ways to control the link element colors, and theme.json allows us to change its hover colors for example. |
That's the specific scenario I was thinking about. I forgot we already do hover, but there's other states we can control via theme.json. Maybe we don't need a UI for everything either as long as some things can be done via theme.json! I think it's safe and good to not want to cover every case on this first pass, but also important to discuss what the future pain points will be. I think elements is also conceptually a mesh of things that we don't know how much we want to unravel, so I defer to your judgement here. It makes a lot of sense to me that we could drill into elements. |
That's fine for now, but in general I think we should aspire to having 99% of theme.json properties be exposed in the UI in some way. But not in a "let's rush to do so", just an ongoing ideal. I agree with your assessments here, this is a solid path forward. But I also feel like if this PR works as well as I hope it will, expanding from blocks to elements will feel natural, including the UI. And if I can select A as an element there, I can design the focus style for it using borders and radiuses. |
|
Looks great, well done! Some questions to think about:
|
The blocks that support in theme.json only.
This is what we already support, and I think that's fine, but we could decide to conditionally hide some. I don't see why we would though.
Like I said, this only brings UI to something we were already supporting, so this has already been the case for a while. It's still valid to think about since I think it's about time we also think about which other blocks could benefit from these controls and what the consequences of that are.
That would be a follow up and we definitely want to explore that, but I don't think anything in this PR blocks that from happening |
|
@jasmussen we might want to have multiples when we combine pseudo selectors with "statuses" as you call them here:
|
|
Yes. The difficult one here is how do I design the focus style for the active state of a menu item? (I.e. menu item with Since that mockup you shared, I think it's probably best to separate those concerns a little bit. Both in terms of code, but also conceptually, and I think we can probably scale a little bit. The main thing is, truly the most important use case to solve for is that: navigation item active state, and that needs prominence in a way that I don't know the dropdown affords. Because of that, we might want to do something like this: So that would be a segmented control showing the two states of a custom link navigation item, then showing preview and styles below, as well as the state picker. It does need a design, but I think the main mental framing I have for this is a different hierarchy, of state first, then pseudo state, then styles. Is that helpful? |
I'm looking into #42299 at the same time as I think about the UI, to see how we want the architecture for that to look like from a theme.json perspective and later on the UI. I think your structure makes a lot of sense. That said, what I was thinking for the nav item would be something like: Current item base styles: Current item hover: All combined: |
|
Yes, that hierarchy would define @current as an ancestor to the states, which the hierarchy I'm pondering with the segmented control first also would 👍 👍 Ultimately I'll defer to you, but I can see it connecting with the idea I have too. |
|
Outside of the scope of this PR but would it make sense to show a preview of the block when a pseudo selector is being edited in the context of single block controls? @jasmussen
|
fa215f5 to
fe4a985
Compare
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
| export const VALID_ELEMENT_STATES: Record< string, StateDefinition[] > = { | ||
| link: [ | ||
| { value: ':link', label: __( 'Link' ) }, | ||
| { value: ':any-link', label: __( 'Any Link' ) }, |
There was a problem hiding this comment.
Why are the states for elements different to the states for blocks?
There was a problem hiding this comment.
I can't remember the reason, but this is how it already is in lib/class-wp-theme-json-gutenberg.php. It might have been an oversight so I'll double check
There was a problem hiding this comment.
I searched and there doesn't seem to be a particular reason why this was the case, but it feels off to introduce that change on this PR, let's move that to a follow up instead?
This was definitely happening and the UI changes just made it easier to see the bug in action. I added a fix over at #76326 |
scruffian
left a comment
There was a problem hiding this comment.
This is looking good, just found one bug but it might be unrelated...
packages/block-editor/src/components/global-styles/state-control.js
Outdated
Show resolved
Hide resolved
|
I opened a fix for what Ben found, I think we could ship this and iterate |
669c260 to
e160549
Compare
|
I found another bug. Enable textIndent for buttons: packages/block-library/src/button/block.json Now, when you apply textIndent in the hover state, it also gets applied to the default state. This isn't strictly an issue in this PR as buttons don't have textIndent, but if we want to apply states to blocks that do support it then the bug will arise. |
scruffian
left a comment
There was a problem hiding this comment.
Happy to bring this in and keep iterating.






What?
Related to #38277
Adds a UI for editing pseudo selector states (
:hover,:focus,:active, etc.) in Global Styles for blocks and elements.This is a starting point, that will need to be expanded to other areas if we feel like we need to (such as adding these controls to a single instance of the block) in subsequent PRs
Why?
Users need to customize how blocks and elements appear in interactive states. While theme.json already supports pseudo selectors, there was no visual UI to edit them.
How?
Adds a "State" dropdown next to block/element titles in Global Styles. When a state is selected (e.g., "Hover"), all style controls below (colors, typography, etc.) edit that specific state. The block preview automatically updates to show the selected state, giving users a live preview of how the block will appear on the frontend.
Testing Instructions
npm run test:e2e -- test/e2e/specs/site-editor/global-styles-button-states.spec.jsTesting Instructions for Keyboard
Screenshots or screencast