WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.16k stars 4.05k forks source link

Standardized way to modify interactive states (:hover, :focus .etc) for blocks #38277

Open getdave opened 2 years ago

getdave commented 2 years ago

What problem does this address?

Currently it's not possible to modify the visual styles when the block items are in a given state (hover, focus, etc).

States (#57719) was designed as a solution that could work for this use case, including the hidden complexity that isn't immediately obvious. Consider a navigation menu, you'd want to be able to change colors of menu items in their neutral, hover, focused states. But most likely, you'd also want to be able to change their border, background, perhaps font-weight or text-decoration in those states.

Secondly there is the need to combine properties into new states. Consider the same navigation menu, menu items can have current states. E.g. when you navigate to /about, the "About" menu item should be highlighted as the current menu item. This state cannot inherit the hover and focus states from default menu items, you might have a blue hover color which wouldn't work if you added a black background:

State matrix

In other words, the state proposal suggests that "Hover" is one property that can make a state. "Current" and "Hover" properties together, make a new state.

The state design can solve both those complexities:

Here are mockups that extrapolate on Saxon's work to test it for both a Button state, and a navigation "current menu item" state:

Button, i4 Nav item, i4

This could work as a starting point, and as the states concept gains features, it can be expanded upon.

Figma.

Issue updated May 7th.

Past version of this issue Examples include: - hovered - focused - active ## Update We've iterated on this in #1786 and #41976. [A video overview](https://www.youtube.com/watch?v=XikXzLLojhk) is available. After #41976, the next steps are: - [x] Fix https://github.com/WordPress/gutenberg/issues/42055 - [ ] support `:hover` on `link` elements _within **blocks_** in Global Styles UI (currently only top level is supported). - [ ] implement the "disclosure" pattern from @javierarce's designs from https://github.com/WordPress/gutenberg/pull/41976#issuecomment-1170067066. - [ ] add support for `:focus` and `:active` states in the Global Styles UI for `link`. - [ ] Add color swatches for the first two "states" in the Global Styles element overview item (see https://github.com/WordPress/gutenberg/pull/41976#issuecomment-1170078408) - [ ] Enable setting Navigation block link color from global styles. Requires https://github.com/WordPress/gutenberg/pull/42092 to be resolved as [Global Styles checks supports to decide whether to enable the panel](https://github.com/WordPress/gutenberg/blob/b5de5fc1af8acbd83495d045f7d86aa902c9ae2f/packages/edit-site/src/components/global-styles/hooks.js#L173). ## What is your proposed solution? Provide design tools that allow setting visual presentation for those states. Likely these will be [implemented as an editor-wide feature](https://github.com/WordPress/gutenberg/issues/27075) rather than something that's specific to the Nav block. I will defer to @jasmussen and @javierarce for their thoughts on how this might happen. Also pinging @jorgefilipecosta who may have some insight onto whether Global Styles intends to handle this in future.
getdave commented 2 years ago

Also cc'ing @annezazu who suggested this idea.

jasmussen commented 2 years ago

Definitely a good challenge. I wonder if we shouldn't zoom out from the navigation block, and look at this issue in more generic terms across all buttons and links. That would put the effort in global styles and design tools territory. One of the interesting challenges to tackle there, is building some confidence on exactly how we should support pseudo states. Do we need them all, or could we start with just hover/focus?

MaggieCabrera commented 2 years ago

Related: https://github.com/WordPress/gutenberg/issues/27075

jorgefilipecosta commented 2 years ago

I think controlling these states from global styles makes sense and I agree with what @jasmussen said. But we need to be very careful how this is going to happen. It does not make sense to control states for a paragraph but maybe for the button block, it does? How do we specify which blocks this makes sense? I guess a block.json support? I guess for the link element it also makes sense so for some elements we are going to have states. We would need to have a design exploration on how we can expose this UI in an easy-to-use way covering both states for blocks and for elements like but not taking much space so the global styles UI is still clean.

getdave commented 2 years ago

Thanks @jorgefilipecosta. I agree it needs to be carefully thought through. Block supports sounds like a good way to indicate whether a given block is suitable for interactive state design tools.

I wonder whether UX wise this could behave in a similar way to the how Devtools handles these states:

Screen Shot 2022-02-02 at 09 12 21

@jasmussen are there any designers working (or planning to work) on this that you know of?

andrewserong commented 2 years ago

block supports sounds like a good way to indicate whether a given block is suitable for interactive state design tools.

Just adding a +1 that this would be both a very cool feature, and it will also need to be thought through carefully, both in the UI design, and how we wish to store the styling state. Over in #38167 there is a project underway (the style engine) to explore how we might improve our saving/rendering of block styles (this come out of the discussion in https://github.com/WordPress/gutenberg/discussions/37495). There's an initial PR for how the style engine might work in #37978.

Aside from the UI, how might hover, focus, active states be represented in the style object, both at the block level and in global styles? Do we need the style object to support nested values, scoped by a list of states, or something like that? How do we ensure we reduce duplication of data so we're not storing too many sets of the same values across multiple states (e.g. if we want the hover, focus, and active states to all be the same colours).

If it's first explored as an individual block support, it'd be good to also get an idea of how it could be centralised in the style engine (and / or made easy to change after the fact).

scruffian commented 2 years ago

I think it makes sense to add this control to the theme.json before we build a UI for it. That gives us a chance to focus on the data structure and functionality and get that right without needing to think about the UI.

jasmussen commented 2 years ago

are there any designers working (or planning to work) on this that you know of?

I responded partially in Slack then forgot to copy it here. Here's an expansion:

It's likely necessary to start with a combination of visuals and pseudo code to figure out a structure that works, and is able to grow if we find the need for a bespoke :active state after all.

paaljoachim commented 2 years ago

The following a "rough" sketch made with Affinity Photo associated with the Button block settings and one for Global Styles. Meant to inspire. Example using Default, Hover and Visited states. Inspired by the Colors panel and the toggle between Solid and Gradient colors.

Buttons block

Buttons-block-Default-Hover-Visited-link-states

Global Styles

Global-Styles-Link-States

I removed the Links which is currently in the Elements section.

getdave commented 2 years ago
  • Consider that each state isn’t just a single property change. A focus state is usually underlined, but it could also be a border with a radius, bold text, or a combination.

I want to emphasis this as it's important.


@paaljoachim Thank you for the exploration!

jasmussen commented 2 years ago

Since this ticket is about the pseudo states which we need for menu items, buttons, and links, should we rename this ticket to reflect that? It can still be labelled for Navigation and be on that tracking issue, but it seems important to not design a nav-block only UI for this.

getdave commented 2 years ago

Since this ticket is about the pseudo states which we need for menu items, buttons, and links, should we rename this ticket to reflect that? It can still be labelled for Navigation and be on that tracking issue, but it seems important to not design a nav-block only UI for this.

@jasmussen I think that's why we have https://github.com/WordPress/gutenberg/issues/27075. This Issue [i.e. 38277] specifically tracks this for the Nav block.

jasmussen commented 2 years ago

Ah, gotcha. Just wanted to make sure that it's built in a reusable standardized way!

getdave commented 2 years ago

I've updated the description with a note that we should implement as an editor wide feature and not specific to the Nav block.

HILAYTRIVEDI commented 2 years ago

I think it's better to add the option for the hover state effect to the inspector controls. As it will allow users to make it more personalized.

javierarce commented 2 years ago

After some thinking, the approach that @paaljoachim proposed makes a lot of sense to me. I'd like to suggest some tweaks to that idea though:

Instead of using segment controls, I think we should go for a different interface. We use segments (or dropdowns, another possibility I explored), to set values… a tabbed list, on the other hand, immediately implies that the elements below belong to the highlighted tab.

I also think we shouldn't show that interface by default, but allow users to enable it through the ellipsis menu:

image

Another reason to avoid using segment controls is that they will limit the number of states we can show (due to internationalization). On the other hand, a tabbed list could be easily modified to indicate that it contains extra states (for example, using small chevrons).

image

Global Styles

One difficulty when it comes to stylizing links and blocks inside the Global Style interface is that Global Styles split the management of colors and typography into two different places.

In the typography section, we could have a new module under the basic settings to customize specific properties.

Limiting the number of properties users can customize will help keep uniformity and good design practices throughout the design (although it'll reduce the expressiveness of the websites users can create).

image

Alternatively, we could show those settings in this way instead:

image

And there are several possibilities to give color styles to links and other blocks, but the one that I think is more simple is to implement the tabbed list after the user select “Links” from the list of elements.

image

That said, in my opinion, using popovers to change colors would be the ideal solution because it would remove the need to navigate through several stacks.

Here's the Figma file where I explored these ideas. Props to @jasmussen to help me with some good feedback.

getdave commented 2 years ago

@javierarce I've added this to the agenda for this week's Core Editor chat.

javierarce commented 2 years ago

@getdave great, thanks!

getdave commented 2 years ago

It was discussed in Core Editor chat here.

fabiankaegy commented 2 years ago

One thing that I think we should be cautious of with the "Show states" toggle is, that it adds a lot of additional clicks to your workflow if you want to modify the hover state of multiple blocks. Instead of a local component state, I would recommend that this toggle is a more persistent setting that a user may be able to activate.

I'm not sure what the mechanism should be but just calling this out as a concern :)

Besides that, I think these are great designs for this interaction and I am excited about this being worked on 🚀

Thanks to everyone involved!

getdave commented 2 years ago

I wonder should we drop :visited as I"m not sure if that's possible to style due to security concerns.

I was thinking :focus would be better as that's important for a11y.

Also I'd like to see what folks thinking about potential data structure for this in Theme JSON. Perhaps @jorgefilipecosta would have a view?

MaggieCabrera commented 2 years ago

I wonder if these states will end up showing in many places? depending on the block, they may affect very different properties. If we are talking links I expect to be able to control text color, text decoration, outline?. If it's a button or, in the future, an input, I may need to control borders and border colors or styles. I can think of cases where I may want to change the padding on hover for example if I want to get creative.

javierarce commented 2 years ago

I wonder if these states will end up showing in many places? depending on the block, they may affect very different properties. If we are talking links I expect to be able to control text color, text decoration, outline?. If it's a button or, in the future, an input, I may need to control borders and border colors or styles. I can think of cases where I may want to change the padding on hover for example if I want to get creative.

That's something I considered and mentioned in the Figma file:

Limiting the number of properties users can customize will allow keeping uniformity and good design practices (although it'll reduce the expressiveness of the designs users can create).

With this exploration I tried to follow a pattern I've seen here for other design tools and features: offer functionalities that give as much control as possible but make it difficult to produce "bad" design.

MaggieCabrera commented 2 years ago

With this exploration I tried to follow a pattern I've seen here for other design tools and features: offer functionalities that give as much control as possible but make it difficult to produce "bad" design.

I see what you mean... I wonder though if we could leave more options to theme developers to control if we decide we don't want to surface all possibilities. Text decoration is a good example of a case where it's not common for all blocks to want to surface that control but it's very obvious that theme will want to set a default for. It's a case I've actually had to write CSS for in the last... maybe 5 block themes I've worked on. Maybe the UI is more restrictive but theme.json will let you cover more cases?

getdave commented 2 years ago

Ah so the UI would only offer a subset but you could control a lot more via Theme JSON? At that point what are the benefits over standard CSS? I guess so the information can be parsed and consumed by non-web clients?

This is going to be tricky. If we open up the idea of controlling interactivity states via the UI, it's inevitable folks will ask for more control via the UI for other things (even things that might be "bad" for design).

javierarce commented 2 years ago

An alternative way to reveal the state selection interface:

https://user-images.githubusercontent.com/4933/169264058-d296d65d-bc72-4585-b1d6-318c0610bd29.mov

mtias commented 2 years ago

I like this last way of revealing the different states, I think it has promise. One addition to consider is surfacing modified values better in the default collapsed state. We had this stacking presentation in the global styles mockups that can be repurposed.

image

In this case, "Links" has both a default color and a hover color, and both are expressed as a stack.

javierarce commented 2 years ago

One addition to consider is surfacing modified values better in the default collapsed state. We had this stacking presentation in the global styles mockups that can be repurposed.

Oh, good idea, I'll incorporate it into the design.

getdave commented 2 years ago

@javierarce Both myself and @draganescu are actively exploring this route in code. It's early days but just so you know we're intending to advance this in a generic way in order that it is applicable to all blocks.

Ironically, it's likely that the Nav block will be the last block to gain the enhancement, as it - necessarily - uses a custom implementation of the color controls so it won't automatically gain the new interaction support if/when it lands unless we refactor that aspect.

javierarce commented 2 years ago

I've added a new prototype to the Figma file to showcase how this solution to display the properties could work inside Global Styles:

https://user-images.githubusercontent.com/4933/176466008-a38e139e-abfe-4449-a119-a18547c835d7.mov

Using descriptions to explain each property could be nice if we found a succinct way to describe each of them. Otherwise, we could maintain the original order:

image

getdave commented 2 years ago

Update

We've iterated on this in https://github.com/WordPress/gutenberg/pull/41786 and I'm currently working on https://github.com/WordPress/gutenberg/pull/41976.

I have a video overview of this if folks want a quick review.

After merged of https://github.com/WordPress/gutenberg/pull/41976, the next steps are:

scruffian commented 2 years ago

@javierarce what do you think about reusing the three dots interface to show/hide the hover state controls? This is how it looks for typography:

Screenshot 2022-07-01 at 10 20 25
javierarce commented 2 years ago

@scruffian I think it's a good idea (I suggested it here but I forgot to add the other existing options inside the menu). I can imagine two possibilities: as a toggle for the feature, or as a list of properties that users can turn on and off.

image

The second option has the nice benefit that users can see which properties are enabled… but I wonder if the list will be too long in some cases.

Were you thinking of one of those solutions in particular?

The only thing I don't like is when we then go to Global Styles: we end up having three ellipses in this weird configuration (although maybe it's a good opportunity to remove the one in the middle and find a better location for the item inside).

image

carolinan commented 1 year ago

Is there anything preventing adding button hover/focus/active to theme.json without the UI?

getdave commented 1 year ago

No. I believe @MaggieCabrera is working on that right now.

eric-michel commented 1 year ago

I think this comment is within the scope of this issue, but if not please let me know and I can make a new post.

For keyboard accessibility, we're using focus-within to add an outline to links and buttons, like so: image

The trouble I'm running into is providing an appropriate color to buttons based on the background color. For links and outlined buttons it's easy - just use outline-color: currentColor; and call it a day.

For regular buttons, there isn't really a great way to access the background color. The best way I've been able to come up with that continues to leverage the style engine and avoid redefining my full color palette in my theme's CSS is the following:

Iterate through the color palette and define a CSS custom property for each background color selector, then output that CSS at the same time as global-styles:

/**
 * Iterate through color palette defined in theme.json and output additional styles for theme
 */
function global_styles_supplemental_colors() {
    $global_styles = wp_get_global_settings();
    $color_palette = $global_styles['color']['palette']['theme'];

    $supplemental_css = "";
    foreach( $color_palette as $color ) {
        $slug = $color['slug'];
        $supplemental_css .= ".has-$slug-background-color{--bg-color:var(--wp--preset--color--$slug) !important}";
    }

    wp_add_inline_style( 'global-styles', $supplemental_css );
}
add_action( 'wp_enqueue_scripts', 'global_styles_supplemental_colors', 100 );

Then in my theme's CSS, add:

:where( :not( .is-style-outline ) ) > .wp-block-button__link {
    outline-color: var( --bg-color );
}

This doesn't really feel great though, especially the fact that I'm having to re-output the .has-$slug-background-color selector.

Perhaps there is a better way to hook into the style engine to add this directly to the .has-$slug-background-color selector and add what I want there, but I have searched around quite a bit and not found any documentation that points me in the right direction.

cbirdsong commented 1 year ago

@eric-michel I do something similar with custom properties on my non-theme.json themes, which also easily allows for default text/link colors to be associated with each background color. This anecdote might be worth dropping into https://github.com/WordPress/gutenberg/issues/39372.

eric-michel commented 1 year ago

@cbirdsong

I do something similar with custom properties on my non-theme.json themes, which also easily allows for default text/link colors to be associated with each background color.

Funny you mention that, because I just finished doing adding same thing to our theme 😁. I'm glad someone else is using similar methods. I'm always worried I'm missing an obviously better way of handling these things.

paaljoachim commented 1 year ago

Hello everyone.

It would be great to get some movement in this issue. Links states came up in two comments. Linking to the second comment. https://github.com/WordPress/gutenberg/issues/4543#issuecomment-1493752657

jameskoster commented 1 year ago

One thing I'm curious about is how to represent the cascade as you manage different states.

If we just duplicate the default state then it becomes quite tricky for the user to understand which controls / values are inherited, and which are specific to the state they're editing.

For example, in the mockup below it takes a lot of scanning to work out the differences, and this is with both panels visible at the same time. Obviously it'll be much more tedious when you have to click back and forth.

Screenshot 2023-04-03 at 17 15 16

Having per-panel state management helps with this, but convolutes the Inspector quite a bit when more than one panel entertains different states.

paaljoachim commented 1 year ago

I just want to add in here that there is a parallell discussion going on here: Add Button Hover Color options on Button Block https://github.com/WordPress/gutenberg/issues/4543#issuecomment-1494554414

shaunandrews commented 1 year ago

I've been looking at an interface for interaction states. I think it's important that we design an interface that allows for multiple states, like both hover and active states. I also think it's important we design an interface that supports not only interaction states, but also content (or data) states, like loading, error, or empty.

https://user-images.githubusercontent.com/191598/230945034-e30379bd-fb29-418b-a5ca-ebc9c468dc70.mp4

CleanShot 2023-04-10 at 12 23 57@2x
paaljoachim commented 1 year ago

That looks really good Shaun @shaunandrews I do wonder if Link States should be in it's own panel component.

nathanrodrigues2111 commented 1 year ago

This has to be a must have option for blocks especially navigation block. As even if we add hover using code its not easy for users to manage / change it using editor which is a really downside. Please if this could be taken as a priority would be really great, Thanks 🙂

paaljoachim commented 1 year ago

Hi @nathanrodrigues2111 Nathan. I believe this issue has not moved forward as there are still some design considerations that needs to be done. Perhaps it is time to relook at this issue in relation to design. To see what kind of user interface would be natural to focus more on for this unique feature as well as using something similar for other more complex features. After the beta for WordPress 6.3 has been released there will be more time to be able to focus on this issue.

nathanrodrigues2111 commented 1 year ago

@paaljoachim Thanks for the prompt reply looking forward for the for this feature in the future 🙂

masteradhoc commented 8 months ago

@paaljoachim any update on this one? Would love to see this getting pushed further.

paaljoachim commented 8 months ago

If I remember correctly I believe @getdave and @MaggieCabrera have been looking into this feature and that there is something that needs to be done first before focus can get to this.

getdave commented 8 months ago

From what I recall, the foundation of this feature is available in Theme JSON. What's needed now is someone to continue to implement a UI to expose this for all blocks that need it.

I won't be working on this during the 6.5 cycle as I am unavoidably focused elsewhere.

deryckoe commented 8 months ago

@getdave is there documentation or clue on how to add a new tab (for hover) to the color picker? I tried to find it with no success. I may be able to help with that.