Skip to content

[WIP] Block Supports: Relocate text and bg color controls to Typography and Background panels#77279

Draft
aaronrobertshaw wants to merge 34 commits into
trunkfrom
update/text-and-background-color-control-locations
Draft

[WIP] Block Supports: Relocate text and bg color controls to Typography and Background panels#77279
aaronrobertshaw wants to merge 34 commits into
trunkfrom
update/text-and-background-color-control-locations

Conversation

@aaronrobertshaw

Copy link
Copy Markdown
Contributor

What?

See:

This PR is a proof of concept that explores improving the information architecture of the block inspector and global styles sidebars by relocating the root-level text and background color controls to the panels they most naturally belong with:

  • Text color moves into the Typography panel.
  • Background color and Background gradient move into the Background panel (alongside background image).
  • The Color panel retains the element-level controls (Links, Headings, Buttons, Captions, etc.).

Why?

Today, every color-related control lives under a single Color panel, regardless of whether the user is thinking about typography, background styling, or element-specific treatments. Grouping controls by the style aspect they affect (typography, background, etc.) should make the sidebars easier to reason about and bring related controls closer to where users are already working.

This PR is deliberately an interim step. The element-level color controls (Links, Headings, Buttons, Captions, etc.) remain under the Color panel because moving those properly is a larger IA question: ideally each element would be presented as a drill-down into its full set of styles (typography, color, spacing, etc.) as a cohesive unit, rather than splitting a single element's controls across multiple top-level panels. That exploration is out of scope here and is best tackled as a follow-up once we have feedback on this simpler change.

The goal of landing this smaller step first is to validate the directional change on the two simplest cases (root text and root background) before committing to a larger restructuring.

How?

  • Added a text color control to the global styles Typography panel and to the block-level Typography panel in the inspector.
  • Added background color and background gradient controls to the Background panel in both global styles and the block inspector.
  • Removed the root text and background items from the Color panel. Element-level controls (Links, Headings, etc.) are unchanged.
  • Introduced a shared block-editor-color-gradient-item class so the border/layout styles for color dropdown items are defined once and reused across the
    Color, Background, and Typography panels. The existing panel-specific classes (block-editor-tools-panel-color-gradient-settings__item,
    block-editor-background-panel__item, block-editor-typography-panel__color-item) remain on the DOM for backward compatibility.
  • Removed an obsolete :nth-child(1 of &) margin-top rule that predated __experimentalFirstVisibleItemClass and was causing excess top margin on the first
    visible item in the Color panel when element-level controls were toggled on.
  • Updated affected unit and e2e tests to handle the new "Color" label inside the Typography panel and to scope selectors to the correct panel when multiple
    "Color" buttons now exist in the sidebar.

Testing Instructions

  1. Open the site editor and navigate to Styles.
  2. Open the Typography panel and confirm a Color control is present. Set a text color and confirm it applies to the editor canvas.
  3. Go back and open the Background panel. Confirm Color and Gradient controls are present alongside the background image control. Set a value for each and confirm it applies.
  4. Go back and open the Colors panel. Confirm that only element-level controls (Links, Headings, Buttons, Captions) remain and that the root text/background controls are no longer present.
  5. In the Colors panel, toggle element controls on and off via the panel menu. Confirm no excess top margin appears on the first visible item.
  6. Open a post or page in the editor, select a block that supports color (e.g. Group, Paragraph, Heading), and confirm the same relocation is reflected in the block inspector.
  7. Save and reload, confirming persisted values are applied on the frontend.

Screenshots or screencast

Screen.Recording.2026-04-14.at.11.46.01.am.mp4

@aaronrobertshaw aaronrobertshaw self-assigned this Apr 14, 2026
@aaronrobertshaw aaronrobertshaw added [Type] Enhancement A suggestion for improvement. [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi labels Apr 14, 2026
@github-actions github-actions Bot added the [Package] Block editor /packages/block-editor label Apr 14, 2026
@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

@jameskoster I took a quick run at what an interim step might look like in terms of relocating the text color control under the Typography panel, and the background color control under the Background panel.

Note that the "element" colors like for Link, Heading, Buttons etc. are all still under optional controls on the Color panel at the moment until we work out a drill down approach or similar.

An additional step in this exploration could be to add a new Elements panel that behaves as the Color panel does now for the Group block. That is, all the elements are optional controls that can be toggled on and each has a popover containing text, background etc tabs. Not ideal but a reasonable step until we have the ability to drill down and style more than just colors.

We'd keep the current Colors panel so that if blocks add ad hoc color controls into that panel they still show as expected. If there's nothing in the Colors panel it wouldn't render at all.

Let me know if you think there might be something here we can pursue in the short term.

@github-actions

github-actions Bot commented Apr 14, 2026

Copy link
Copy Markdown

Size Change: +1.26 kB (+0.01%)

Total Size: 8.46 MB

📦 View Changed
Filename Size Change
build/scripts/block-editor/index.min.js 381 kB +1.69 kB (+0.44%)
build/scripts/editor/index.min.js 467 kB +1 B (0%)
build/styles/block-editor/style-rtl.css 18.6 kB -173 B (-0.92%)
build/styles/block-editor/style-rtl.min.css 16 kB -41 B (-0.26%)
build/styles/block-editor/style.css 18.6 kB -173 B (-0.92%)
build/styles/block-editor/style.min.css 16 kB -41 B (-0.26%)

compressed-size-action

@ramonjd

ramonjd commented Apr 14, 2026

Copy link
Copy Markdown
Member

Thanks for getting this PR up for consideration, and allowing folks to play around with it. It's working for me as described.

Global Block
Screenshot 2026-04-14 at 3 09 19 pm Screenshot 2026-04-14 at 3 10 26 pm

I can't shake the feeling our labels are working against us, and it's for this reason we're having to make some awkward shuffling around of properties.

Typography, at least for me, is about how text is shaped and arranged, so we have font family, size, weight, spacing, line height, text transform etc, while color has always been a surface treatment.

BUT the user's mental model isn't CSS properties so my thinking here is inappropriate. I don't know how many folks outside this repo say "Oh, I need to set my color and font size" but instead "this text needs to be bigger and bolder and should stand out more" 😄 Is being prescriptive based on CSS taxonomy instead of user tasks working against us here?

So in the context of this PR, I see some reason in dropping technical terms and mirroring CSS. "Text" or "Text Style" makes more sense to me when I test out the controls here.

Anyway, these are just my initial thoughts. I don't know if there's a perfect solution here at all (is there ever?), but I appreciate the compromises and ideas folks have arrived at to help us decide.

@jameskoster

Copy link
Copy Markdown
Contributor

An additional step in this exploration could be to add a new Elements panel that behaves as the Color panel does now for the Group block. That is, all the elements are optional controls that can be toggled on and each has a popover containing text, background etc tabs. Not ideal but a reasonable step until we have the ability to drill down and style more than just colors.

This would effectively mean the existing Color panel is hidden most of the time, right? If so I think that might be good to include in this PR. Relatedly I'd consider giving the new Elements panel less prominence in the UI, maybe by positioning it at the bottom of the inspector.

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Thanks for the direction @jameskoster 👍

I was already working towards both including the elements panel as well as pushing it further down the sidebar.

As soon as I have something more functional. I'll demo again.

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

This is early days and still buggy but here's a quick glimpse of the elements panel approach discussed. The first pass at this was pushed in 9853127

Screen.Recording.2026-04-16.at.5.54.32.pm.mp4

@jameskoster

jameskoster commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Neat, that looks pretty good to me. Time to rope in @WordPress/gutenberg-design for some wider feedback.

The only quirk I noticed is the placement of the contrast warning. If that appears due to changing the Text color the placement is a bit unexpected. I wonder if we should move that warning to the color popover. That way it'll appear contextually whether you're currently modifying the background or the text color. Additionally it won't clutter the Inspector in situations where users legitimately want low contrast styling.

@aaronrobertshaw

aaronrobertshaw commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for taking another look at this one 🙇

I wonder if we should move that warning to the color popover

Good idea. I like it 👍

I'll find some time and make it happen on this PR.

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Here's a demo of a quick hack at getting the contrast checker warning within the color popovers. I think we might need to put a little thought into how we could present this better to avoid scrollbar within the popover, the popover extending beyond the bottom of the page, or even just the significant layout jump that it causes.

Happy to try out any ideas you might have:

Screen.Recording.2026-04-18.at.8.00.06.pm.mp4

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Here's a quick mockup of potentially adding a warning icon and tooltip/popover to the color popover when the contrast is too low. We could also display it in color control in the panel as well if we can find a way that it doesn't look too bad beside existing color swatches and the reset button within the control.

For now though maybe this will spark further ideas:

Screen.Recording.2026-04-19.at.11.46.28.am.mp4

@jameskoster

Copy link
Copy Markdown
Contributor

Yeah that works a bit better. I wonder if we could use a Badge with a 'Low contrast' or similar label. I suppose with the smaller footprint we could display the badge in the panel, something like:

Screenshot 2026-04-20 at 13 34 09

@jasmussen

Copy link
Copy Markdown
Contributor

Nice! Taking this one for a spin, I think it works well.

On the badges for low contrast, it's not a poor idea, but given we have color Items that have very long titles, like "Submenu & overlay background" (which already gets elided), I don't think there's room for a badge there. Could we do an unread dot instead? And regardless, because that may be a rabbit hole and a new feature, might be worth keeping separate from this one?

That is, can we just keep the yellow notice that exists in trunk already?

I see this is already present, I'm thinking the same but with a blue dot instead of a yellow icon:
image

Also, now that we've changed the Color panel, should we move Typography above it?

image

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Appreciate all the great feedback here 🙇

I'll try and resolve all the new conflicts over the next few days then explore the options in front of us.

That is, can we just keep the yellow notice that exists in trunk already?

I'm not sure how I feel on this one given the two related colors being compared are split across panels. I'll see how it plays if the contrast warning is displayed in both panels, if that's even possible etc. then update again.

@aaronrobertshaw aaronrobertshaw force-pushed the update/text-and-background-color-control-locations branch from 2c7bfcc to 8be2003 Compare June 5, 2026 07:41
@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

I've finished resolving all the conflicts with the recent state based and responsive styling changes. I believe this is back to a functional state.

The suggested tweaks have been made and are present in current state of this PR. These include:

  • Using blue dot instead of yellow warning dot/icon.
  • Displaying the contrast warning in both the Typography and Background panels
  • Relocating the Typography panel above the Color and Background panels

It turns out if a block contains a link element and the link element has styles for the block that also has its contrast checked.

Having multiple contrast warnings really creates some dramatic layout shift and/or scroll in the block inspector. It'll be even worse if we add another warning to the elements panel when it is considered low contrast and applicable. (Side note, the element color popovers don't have the low contrast dot and tooltip rendered yet but that can be a follow-up if we keep with that approach)

Another issue with the current contrast warning being rendered multiple times is that the warning by default is announced by speak() for accessibility purposes.

If we were to display a single warning only, at the block level, within the inspector, would that detach the warning too much from the relevant controls? Could the combination of styles and the resulting lack of contrast be a block level concept?

The last issue I noticed, which is also present on trunk is that with state-based styles e.g. hover state, the link element there still has a :hover state in the link element's color popover. I'm not sure if we want that but for now, I guess the block has it's hover styles and the link element within the block can have separate hover styles still.

Here's a quick demo of the latest exploring low contrast selections and warning display:

Screen.Recording.2026-06-08.at.1.52.24.pm.mp4

/cc @jasmussen and @jameskoster any thoughts on the latest changes? It still feels like we need to polish the contrast warning behaviour and UX.

@ramonjd ramonjd left a comment

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.

In the UI, this is working how I'd expect. I don't see any gotchas (aside from the double custom color comment) from a UX perspective. It's satisfying to be able to play with transparent images and gradients and try different things.

Image

My other comments are non-blocking and mostly questions.

);

// Announce to screen readers whenever the warning becomes active.
speak( message );

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.

This would fire on every render that happens while isPoor is true, right? Is there anything else that could trigger a render besides the contrast check?

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.

Honestly, not sure off the top of my head but the fact that we're rendering 2 contrast warnings (3 if we add one for elements), means we're going to be announcing redundant warnings. Navigating our editor is hard enough I'd say for those relying on screenreaders etc. without introducing this.

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.

Actually, I was forgetting that I added the speak call here to meet other accessibility warnings I was getting. There might be a different balance or solution here.

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.

After adding the warning back to the panels. This speak call could be omitted entirely. If it turns out we go back to just the warning in the color popover, I'll gate this in an effect so it only fires on the change from false to true or when color values change.

Comment on lines +227 to +235
const setTextColor = ( newColor ) => {
onChange(
setImmutably(
value,
[ 'color', 'text' ],
encodeColorValue( newColor )
)
);
};

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.

Not sure if this is right but I see a regression and I think it might be related to the way trunk passed newSlug.

If I have two custom colors with the same hex value, e.g.,

    "color": {
      "palette": [
        { "slug": "brand-a", "name": "Brand A", "color": "#e10000" },
        { "slug": "brand-b", "name": "Brand B", "color": "#e10000" }
      ]
    }

They're selected, and only brand-a is assignable.

Image

here's how trunk is working

Kapture.2026-06-09.at.14.24.31.mp4

I think it's important coz if the custom color brand-b is ever updated in the theme, it wouldn't have any effect on stored posts with that var.

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 for the quick testing and flagging this.

I'm sure I've messed up the rebase. I'll get a test in place to cover the regression and implement a fix.

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.

FWIW I've seen two colors showing as "active" before, when the values are the same. Not ideal, but probably also not the fault of this PR.

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.

I've seen two colors showing as "active" before, when the values are the same. Not ideal, but probably also not the fault of this PR.

I just retested and still see the two colors selected, but the slug does persist after 71ab383 I think. Nice work!

So here I tested by selected the second B and saved, then updated the value in theme.json to check that the change came through.

Screenshot 2026-06-12 at 1 12 02 pm

observer.observe( blockEl, {
attributes: true,
attributeFilter: [ 'class', 'style' ],
subtree: true,

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.

I guess this is unavoidable. In big containers with lots of deeply-nested blocks I'm wondering what the performance trade off would be of calling a lot of getComputedStyle().

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.

This is mirroring the existing contrast checker that displays the warning in the different panels. So if it has been accepted there I think that is the baseline.

Now, given this means it might be done multiple times with the warning to be displayed in the color popover, it might need optimising if possible or a different approach to ensure performance is maintained or improved.

I'll look into it.

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.

No biggie if it was there before. Thanks!

@jasmussen

Copy link
Copy Markdown
Contributor

Nice work, this is trucking along well.

Thanks for changing the dot to blue. I will say it's not entirely clear that it's useful after all. It's fine to keep, but it seems like that dot is serving the same purpose that is covered by the contrast notice itself. It may be best to simply remove it after all.

Speaking of, the double warnings is the problem to solve to ship this:

image

Not a solution near term, but I want to connect this to #76996 and #78880 as having potential to be more generic homes for lint, which I consider contrast issues to be.

But near term, can we show the contrast warning only inside the panel that has colors set? E.g. the above image is confusing because it is flagging incompatible colors in a panel that does not have colors set. However the following is probably fine, true, and honest:

image

Not necessarily for this PR, but we could also potentially improve those contrast warnings with clarity, brevity, and specificity. E.g. instead of:

This color combination may be hard for people to read. Try using a brighter background color and/or a darker text color.

For the typography panel we could do:

This color has poor contrast against the background. Consider increasing contrast.

For the background panel we could do:

This color combination has poor contrast. Consider increasing contrast between background and foreground.


Relatedly, and possibly not the fault of this PR, but I managed to get myself into this state by clicking first one color, then the other:

image

The duplicate controls called "Color" will take a little getting used to, insofar as one is typography color and the other is background color, with the panel context revealing which is which. I think this is worth shipping as is, feeling out. If that fails, we can always call change the BG color term to "Fill", or "Solid":

image

@jameskoster

Copy link
Copy Markdown
Contributor

Didn't we add the dot so that we could remove the notice in the Inspector?

I think the yellow dot/icon worked a bit better as it conveys meaning. From that perspective I still think it could be displayed as an Info tip in the ItemGroup:

Screenshot 2026-06-09 at 16 23 16

@jasmussen

Copy link
Copy Markdown
Contributor

I would agree that it's either the notice, or the dot.

Do we have to decide between them in this PR? I'm softly leaning towards the notice, in part out of inertia/cheese-moving, but also because until we have something like #76996, flagging very visibly contrast issues is something that is unique to the block editor compared to other players in the space.

@jameskoster

Copy link
Copy Markdown
Contributor

Yes I think it would be fine to tackle separately, especially without a design we're 100% happy with. Ideally it's something we can prioritise though because obviously the double-notice is taking up a lot of valuable space in the Inspector, arguably a regression. Not essential, but an interim solution could be to make the notice(s) dismissible.

@jasmussen

Copy link
Copy Markdown
Contributor

The double notice can hopefully be substantially mitigated by worth-doing-anyway changes to when they fire as suggested here, i.e. only show the notice if a color from the panel has actually been set, and rephrase the notice dependant on which panel it shows up on. WDYT?

@jameskoster

Copy link
Copy Markdown
Contributor

It can work, but will still produce double-notices in some cases, no?

@jasmussen

Copy link
Copy Markdown
Contributor

If there's a color set in both typography and background panels, both of which are poor, there could be two notices, yes. But each would have a bespoke contextual message, and each would still need separate fixing, yes? I.e. if you fix it in one place and that improves the contrast enough for both checks to pass, the notice would disappear in both places, but you'd get to choose where to fix it.

I agree, not necessarily perfect, but it's honest, it's truthful, right?

@jasmussen

Copy link
Copy Markdown
Contributor

Not a strong opinion. If you feel strongly about the dot-based indicator, we can pursue that also. It's a tight space, but there should just be room:

image

@aaronrobertshaw

aaronrobertshaw commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Appreciate all the continued discussion here 🙇

The commits I pushed yesterday implemented all the feedback from #77279 (comment) but it all needed a little further testing before I was going to record a demo.

It'll be even worse if we add another warning to the elements panel when it is considered low contrast and applicable

I flagged earlier the fact that contrast warnings can be triggered by elements too.

That means there might be three locations where a color selection could cause low contrast:

  • Typography + text color
  • Background + background color
  • Elements + link color etc (when this is a link in the block's content)
Screen.Recording.2026-06-09.at.5.15.57.pm.mp4

This PR now has some conflicts with trunk, so I'll sort those out again, then iterate further.

I'll link to two separate commits that will demo both the latest notice in panel behaviour and the alternative dot only approach. Hopefully, that will help guide what feels best before we have the linting error solution mentioned earlier.

Pull the ColorPanelDropdown component and its supporting
LabeledColorIndicators/ColorPanelTab/popoverProps helpers out of
color-panel.js into a standalone module so Background, Typography, and
Color panels can all render color/gradient ToolsPanelItems consistently
without duplicating the dropdown/tabs/reset boilerplate.

Pure refactor. No UI change.
Addresses design feedback on the relocated text and background color
controls:

- Remove the small contrast-warning dot from the color picker popover,
  along with its portal wiring in the shared dropdown item and its CSS.
  The panel notice remains the single contrast warning surface.
- Only show a panel's contrast warning when that panel actually has a
  color set: the Typography panel requires a text color, and the
  Background panel requires a background color. This avoids warning in a
  panel that has no color selection of its own.
- Add a messageOverride prop to the shared ContrastChecker so each panel
  can provide clearer, panel-specific copy (text-vs-background guidance
  in Typography, combination guidance in Background).
@aaronrobertshaw aaronrobertshaw force-pushed the update/text-and-background-color-control-locations branch from 39661d4 to 75ed850 Compare June 11, 2026 01:39
@aaronrobertshaw

aaronrobertshaw commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

With the current approach, displaying contrast warnings within the typography or background panels only if those panels contain a color selection, if an element color selection is low contrast against theme inherited values, no warning shows.

This probably means that we still need the contrast warning in the third panel, Elements.

Screenshot 2026-06-10 at 6 39 10 pm

I believe there is another issue possibly stemming from the fact the contrast checker previously worked based on the whole set of color selections. If there was any low contrast by the whole set a single contrast warning was shown.

Screenshot 2026-06-10 at 6 48 19 pm

Note that the text vs background colors here are fine, it is the link triggering a contrast warning but each panel with a color selection shows the warning

Now if we are showing different warning messages based on the panel, I'll need to tweak the contrast checker in each panel to only check against that color e.g text vs background in the typography panel and not allow elements to impact that check and vice versa

- Elements panel now surfaces a contrast warning for link color
  selections, fixing the gap where a low contrast link color went
  unreported when Typography/Background had no selections.
- Typography panel now only warns when the text color pair fails;
  link-only failures are reported by the Elements panel instead.
- Background panel behavior is unchanged: it warns on any failure
  since both text and link contrast depend on the background.
The Elements panel notice previously had no styles, so it spanned a
single grid column with no spacing above it. Consolidate the per-panel
rules from background, color, and typography styles into a single
shared stylesheet that covers all four panels.
Replaces the in-panel contrast warning notices with an indicator on
the color control toggle row, per design feedback. When a color
selection results in insufficient contrast, the reset button's slot
hosts a small actions dropdown modeled on the Global Styles
inheritance dropdown:

- Trigger: caution icon (exclamation in circle), always visible
  (no hover-reveal), labeled '{control label} options', with proper
  aria-haspopup/aria-expanded menu semantics and the popover
  anchored to the trigger button itself.
- Menu: offers 'Adjust color' (opens the color picker popover, with
  the full warning message as its tooltip) and 'Reset'.

When there is no warning, the plain reset button renders exactly as
before, keeping the surface that the upcoming reset-to-dropdown PR
rewrites untouched. That PR's menu can later absorb the warning
state (icon swap on the trigger, extra items in the menu) alongside
inherited-value indicators and push-to-global-styles actions.

Supporting changes:

- Extract getContrastWarning() from the ContrastChecker component so
  the warning can be consumed as data; the public component behavior
  is unchanged.
- Convert the block-level checker into a useBlockColorContrastWarning
  hook that reads computed colors from the block element and returns
  the warning message, still announcing it via a11y speak().
- Per-panel attribution is preserved: Background checks both pairs,
  Typography checks text only, Elements checks link only.
- Remove the now-unused shared panel notice styles.
@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

I have explored the approach to low contrast warnings proposed in #77279 (comment).

The initial issue with that is what we do with the "reset" button that is revealed on hover when there is a color selection. For accessibility, we can't nest the button within the color control's button to toggle the color popover. So the current approach is to absolutely position the reset button. This makes it less straightforward to place another warning/icon or interactive element beside that reset button.

Below is what it might look like to have the reset button replaced with a dropdown using the warning icon as its toggle button. The dropdown contains an "adjust" item that has the warning icon and tooltip to flag the low contrast issue as well as the "reset" option.

This dropdown is inline with the approach being explored for displaying inheritance of global styles values in #77894. In #77894, the blue dot indicating inheritance is a toggle for a dropdown that allows the user to reset to inherited value or push to global styles.

This is just an exploration and to provoke further ideas and discussion. Happy for any feedback.

Screen.Recording.2026-06-10.at.11.43.43.pm.mov

To compare the notice-in-panel approach vs the current approach shown above, checkout bf042da

@jasmussen

Copy link
Copy Markdown
Contributor

Thanks for all the explorations. This is trucking along. The shifting notices in your demo video do look jumpy, so not ideal. But to be honest, if I'm comparing to trunk, they feel better and more contextual and actionable. I think we've worked up almost a banner-blindness to what exists in trunk because they are just not quite as useful.

Specifically what works well:

  • The errors are contextual to the panel which has offending colors.
  • The error messages are clearer and more contextual.

These principles are worth maintaining regardless of whether we go with notices or warning icons.

Your latest video from just a moment ago is actually quite compelling. What do you prefer yourself at this point: notices or warning icons?

If we do go with warning icons, we should consider using the error icon.

The only concern I have with the warning icon is that it feels like a one-off pattern as just an icon inside the ItemGroup. I wish we could use an icon-only badge, then at least it'd be a recognisable element, similar to how we use badges for state-bsased indicators:

image

But I don't think we can. @jameskoster what are your system instincts here?

@jasmussen

Copy link
Copy Markdown
Contributor

Note that the text vs background colors here are fine, it is the link triggering a contrast warning but each panel with a color selection shows the warning

In that example, can we rephrase the contrast text to clarify this? Or is that adding needless complexity?

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Thanks for the quick feedback here @jasmussen 🙇

What do you prefer yourself at this point: notices or warning icons?

Personally, I think I lean toward the icons but feel like the UI and dropdown needs some furtherpolishing. That approach seems forward compatible with the dropdown that is proposed in #77894.

With the notices approach, there are cases where you could have one notice get rendered but be outside of the viewport and go unseen unless the user scrolls. The icons approach isn't perfect either but does limit some of that UI jumping.

In that example, can we rephrase the contrast text to clarify this? Or is that adding needless complexity?

I'm sure we can refine the text as needed. The real estate available and the required brevity will be determined by the approach we settle on I think.

@jasmussen

Copy link
Copy Markdown
Contributor

If we can't refine the text as needed, it makes me also softly lean towards the icons.

Ultimately I'll defer to Jay if he has opinions on how we might systematise the icon. That's the main open question for me still.

@fcoveram

Copy link
Copy Markdown
Contributor

Coming to say this is great work and the change feels definitely a better experience. Just sharing a thought regarding the latest topic.

Regarding informing about the color contrast, I'm drawn to use icon instead of notice component. An icon badge would be ideal, and that sounds like a follow up improvement of the component. For the icon type, I would not use error as there is no action required by the user. The message is a caution to be aware of the outcome, but it does not impede user to go with it.

But take the above lightly as Jay and Joen have been actively working here.

Replaces the contrast warning actions dropdown with a 'Low contrast'
badge on the color control toggle row, per design feedback:

- A non-interactive Badge (warning intent, caution icon) renders
  beside the reset button when a color selection has insufficient
  contrast; clicks pass through to the control toggle. The badge
  matches the block card's state badge styling.
- The reset button stays visible without hover while the badge is
  shown, so its action remains discoverable.
- The full warning message renders inside the color picker popover,
  between the custom color picker and the palette swatches, so the
  explanation is visible at the moment the user acts on the warning
  and disappears live once a passing color is chosen.

Supporting changes:

- ColorPalette (components) accepts an optional children slot
  rendered between the custom color picker and the palette.
- ColorGradientControl forwards children into the color tab.
- Remove the ContrastWarningDropdown and its styles; the warning UI
  is now purely status (badge) plus contextual advice (popover).
The badge inside the color control toggle inherited the toggle
button's 13px font size on its outer span, rendering larger than the
same badge in the block card (12px). Pin the badge subtree to
$font-size-small so it matches the block card's state badge.
…pover

- Blocks with non-standard color attributes (e.g. Social Icons,
  Navigation) render the public ContrastChecker component directly
  within the color panel. The rules giving that notice full panel
  width and top spacing were lost during the contrast warning
  refactoring; restore them in hooks/color.scss.
- Replace the ad hoc icon-and-text contrast warning inside the color
  picker popover with the Notice component, matching the warning
  notices shown in the inspector panels (same background, border,
  and typography) and dropping the icon which wasted horizontal
  space in the narrow popover.

@ramonjd ramonjd left a comment

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.

Great work @aaronrobertshaw and kudos for sticking with this.

From a code perspective this is working well. I tested the following:

  • block instance styles (image, gradient, color)
  • global styles
  • block variations

All are working as expected.

Question - now that root background color moved out of ColorPanel do we need to update useBlockHasGlobalStyles with useHasBackgroundPanel or something?

This LGTM in my testing. If the design direction has the 👍🏻 I think we're in a good place.


Non-blocking observations:

The only things I noticed are related to block instance responsive overrides, and I think this is already a known quantity.

They seem to work fine in the editor, but don't output as expected.

Editor Frontend
Screenshot 2026-06-12 at 12 54 42 pm Screenshot 2026-06-12 at 12 56 06 pm

As far as I can tell, global responsive overrides are working okay.

Also the background image control is set up to display the global styles fallback if a block instance isn't set. That's fine until we set a block instance background image to A, then switch to editing "Mobile/Tablet". The control will still show the global styles value instead of the block instance A.

// control in the Typography panel and under all controls in the
// Background panel, visible without opening the popovers.
const typographyWarning = typographyPanel.locator(
'.block-editor-contrast-checker'

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.

Is this still right? I noticed .block-editor-contrast-checker is deleted above in packages/block-editor/src/hooks/color.scss

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.

This branch is in a bit of a transitional state at the moment. I'm trying several different approaches in the UI. So there's a lot of clean up, polishing, and even sanity checking to be done once we're more settled on a final direction.

Thanks for flagging this, I've added it to a list to circle back to and clean up.

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.

Ah no worries, I was a bit trigger happy. I'll wait until you're through with the changes.

Comment on lines +227 to +235
const setTextColor = ( newColor ) => {
onChange(
setImmutably(
value,
[ 'color', 'text' ],
encodeColorValue( newColor )
)
);
};

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.

I've seen two colors showing as "active" before, when the values are the same. Not ideal, but probably also not the fault of this PR.

I just retested and still see the two colors selected, but the slug does persist after 71ab383 I think. Nice work!

So here I tested by selected the second B and saved, then updated the value in theme.json to check that the change came through.

Screenshot 2026-06-12 at 1 12 02 pm

@aaronrobertshaw

aaronrobertshaw commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for circling back to this PR @ramonjd 🙇

I'm working on another alternate approach in the UI that might blend a few of the options we've been considering. So there's a good chance the code might shift again before I can consolidate, polish, and look toward final reviews here.

This isn't the UI I'm working towards with the contrast checking, just the current state, so take it with a grain of salt as it is changing rapidly. It might provide food for thought for people though, so I'll share early.

Screenshot 2026-06-11 at 6 45 44 pm

The above:

  • leans into the badge preference previously shared
  • moves the weighty text explanation into the popover where the user can actually do something about the warning
  • does not add interactivity or tooltip for the badge
  • will possibly allow the warning to replace the overlayed reset button when there's a contrast warning in effect
    • there's already two other places to reset the color selection; toolspanel menu + color popover clear button
  • still allows some further creativity around how we display the warning notice in the popover
  • doesn't yet solve announcing contrast warnings to screen readers before a popover would be opened etc

I'll push the latest as soon as it is demoable or can be played with.

aaronrobertshaw and others added 3 commits June 11, 2026 23:08
The Background panel resolved the selected preset slug only from
`inheritedValue`, while the displayed color used `value` first
(`userBackgroundColor ?? backgroundColor`). For a block instance the
selection lives in `value` and `inheritedValue` only holds the global
styles fallback, so the slug was missing and ColorPalette fell back to
hex matching, marking two same-hex presets as selected at once.

Resolve the slug with the same value-first precedence as the indicator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the [Package] Components /packages/components label Jun 12, 2026
@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Instead of both the badge and the reset button, here's what omitting the reset button looks like when there is a contrast warning in effect. Even without this reset button, there's two other places to reset the button; ToolsPanel menu + clear button in popover.

Screenshot 2026-06-11 at 11 10 17 pm

Let me know what people think is our best bet from the options floated to date 🙏

@jasmussen

Copy link
Copy Markdown
Contributor

I like that badge, and the notice inside the flyout seems like a good solution. The only problem is that it's an extremely tight space. As mentioned previously, some ItemGroup situations have very long labels. Options: does the badge support tooltip label only, and being icon only? If not, can it just say "Warning"? I'd love it even shorter, but that's hard to do.

@fcoveram

Copy link
Copy Markdown
Contributor

Showing the warning title might not scaling well when this is longer and the available space is even smaller. I would keep the indicator just to only show the notice type (warning), and rely purely on the icon. Ideally, using badge in medium

@jasmussen

Copy link
Copy Markdown
Contributor

I was thinking the same thing, the only thing is I don't think the badge supports icon-only.

@jameskoster

Copy link
Copy Markdown
Contributor

I'm not sure we can do icon only because there's no easy way (that I can see) to make the message accessible to screen readers. To reveal a tooltip the element needs to be focusable, which leads us back to the nested-interactive-elements violation. Maybe we could do something with aria-describedby on the button then just display an inline icon, but it sounds a bit complex and potentially fragile.

As mentioned previously, some ItemGroup situations have very long labels

When does this occur? I couldn't find an example. Or is it an i18n thing?

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Thanks for the continued discussion, I appreciate having so many eyes on this one.

My understanding of the feedback so far is that we essentially want an icon-only option, with tooltip, and the notice displayed in the popover. Is that correct?

If so, this almost takes us back to an earlier iteration where there was a dropdown menu attached to the icon-only warning.

I'll tweak the current version to go back to the icon-only interactive element that is absolutely positioned, similar to the reset button that appears on hover on trunk. That way our icon-only warning can have a tooltip. I'll also play around and see if we can have the reset button beside this icon-only warning too.

@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Here's one more permutation that we might consider:

  • Contrast warning is initially indicated by icon-only button
  • Icon-only warning button has Low contrast tooltip
  • Icon-only warning button toggles the color control's popover
  • Icon-only warning button shows in the far right and regardless of hovering the control
  • Reset button that appears on hover is still there but shows to the left of the icon-only warning button
  • Contrast warning notice is still rendered in the color control's popover
Screenshot 2026-06-12 at 3 45 32 pm Screenshot 2026-06-12 at 3 45 51 pm

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

Labels

[Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Package] Block editor /packages/block-editor [Package] Components /packages/components [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants