Skip to content

Conversation

@luminuu
Copy link
Member

@luminuu luminuu commented Sep 16, 2025

What?

Closes #42683
Closes #64760
Closes #71510
Closes #52191
Closes #69939

Why?

This PR solves multiple issues regarding the selection of font size preset, if those presets have the same size. Right now selecting a font size preset in the editor will result in always falling back to the first item in the list that has the exact same size set.

Even if a user sets custom fluid values, the original size value is stored and used as a selection reference. This causes issues in the user experience of the custom fluid values not working correctly as they just can not be selected, if the size value (which will be disabled) is not changed before entering custom fluid values.

How?

This PR introduces a selectedSlug variable that is used in every relevant spot to hold the actual selection, instead of falling back on a specific size that can be added multiple times through the font size presets interface.

The code fixes this issue in both selection variations: the horizontal S - M - L - XL - XXL selection like in Twenty Twenty-Five, as well as in the dropdown, if more font size presets exist than the horizontal selection can show.

I also went ahead on updating the display of the font size preset name and actual value in the dropdown, despite the issue is waiting for more Design feedback. The reason for this is I found that when not adjusting this, if the preset name was short (like Small) and it had a fixed value, it would all be in one line. Together with items that break into two lines, this would have looked confusing, as information for different items have showed differently. I went ahead and added feedback by @karmatosed already, but this can be discussed here too.

Testing Instructions

Depending on the theme it's tested and optionally additional font size presets added, both variations can be tested:

Horizontal view

CleanShot 2025-09-16 at 17 57 07
  1. This can be tested with Twenty Twenty-Five without any additional font size presets added.
  2. Go to Styles -> Typography -> Font size presets.
  3. You can pick any existing font size. Small has a fixed value, so you can edit for example Medium, by deactivating both toggles and adding 0.875rem as font size.
  4. Save settings.
  5. Go to any paragraph or heading and select the font size preset. Without this PR, you should not be able to select it, with this PR, both original and updated selections are possible.

Dropdown view

CleanShot 2025-09-16 at 18 04 40
  1. In order to test this view, you need to add at least one additional font size preset, two to make it easier testing.
  2. Go to Styles -> Typography -> Font size presets.
  3. Add a new custom font size with a fixed value of 1rem for example.
  4. Add a second custom font size with adding 1rem in the size input as well, before activating both of the fluid toggles and adding 1rem and 3rem as respective values.
  5. Save settings.
  6. Go to any paragraph or heading and select the second font size with the fluid values added. It should stay selected and not fall back on the first custom font size with the fixed value.

Screenshots or screencast

The screencasts only show the dropdown version.

Before

CleanShot.2025-09-16.at.18.15.52.mp4

After

CleanShot.2025-09-16.at.18.10.29.mp4

… M - L - XL - XXL, where having the same size wasn't possible to select either
@github-actions
Copy link

github-actions bot commented Sep 16, 2025

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: luminuu <[email protected]>
Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: ramonjd <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: mirka <[email protected]>
Co-authored-by: hanneslsm <[email protected]>
Co-authored-by: karmatosed <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: priethor <[email protected]>
Co-authored-by: pagelab <[email protected]>
Co-authored-by: SH4LIN <[email protected]>
Co-authored-by: andersnoren <[email protected]>
Co-authored-by: matiasbenedetto <[email protected]>
Co-authored-by: susurruses <[email protected]>
Co-authored-by: uniquesolution <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@luminuu luminuu requested a review from Mamaduka September 16, 2025 16:18
@Mamaduka Mamaduka added [Type] Bug An existing feature does not function as intended Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json [Feature] Typography Font and typography-related issues and PRs labels Sep 16, 2025
@hanneslsm

This comment was marked as outdated.

@t-hamano t-hamano added the [Package] Components /packages/components label Sep 17, 2025
@t-hamano t-hamano requested a review from a team September 17, 2025 01:56
Copy link
Contributor

@t-hamano t-hamano left a comment

Choose a reason for hiding this comment

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

Thanks for the PR!

Like many other components, I think that which items are selected or not should be determined by a single source.

Even if a user sets custom fluid values, the original size value is stored and used as a selection reference.

This is the fundamental problem we need to address. This may be difficult, but can we generate a unique size value from fluid.min and fluid.max? Or, when passing a prop to the FontSizePicker component, can we pass the actual clamp value as the size value instead of 16px?

Together with items that break into two lines, this would have looked confusing, as information for different items have showed differently.

If this is a real problem, it should be fixed in the CustomSelectControl component itself, rather than overriding the CustomSelectControl behavior. Perhaps we can discuss the design in a separate issue or PR.

@luminuu
Copy link
Member Author

luminuu commented Sep 17, 2025

Thank you for your feedback @t-hamano!

This is the fundamental problem we need to address. This may be difficult, but can we generate a unique size value from fluid.min and fluid.max? Or, when passing a prop to the FontSizePicker component, can we pass the actual clamp value as the size value instead of 16px?

I don't think generating a unique size will solve the problem. It would make most sense to me to have the entire clamp() statement in there, just as it is generated on the frontend.

Together with items that break into two lines, this would have looked confusing, as information for different items have showed differently.

If this is a real problem, it should be fixed in the CustomSelectControl component itself, rather than overriding the CustomSelectControl behavior. Perhaps we can discuss the design in a separate issue or PR.

Would this be a blocker now for this PR?

@t-hamano
Copy link
Contributor

Together with items that break into two lines, this would have looked confusing, as information for different items have showed differently.

If this is a real problem, it should be fixed in the CustomSelectControl component itself, rather than overriding the CustomSelectControl behavior. Perhaps we can discuss the design in a separate issue or PR.

Would this be a blocker now for this PR?

I don't think this is a blocker, but I don't understand why a special layout is needed just for the font size picker 🤔

@luminuu
Copy link
Member Author

luminuu commented Sep 17, 2025

I don't think this is a blocker, but I don't understand why a special layout is needed just for the font size picker 🤔

Let's call it "path of least resistance" 😅 Let me try to figure out a better way in the CustomSelectControl component.

@mirka
Copy link
Member

mirka commented Sep 17, 2025

If this is a real problem, it should be fixed in the CustomSelectControl component itself, rather than overriding the CustomSelectControl behavior. Perhaps we can discuss the design in a separate issue or PR.

Agreed. Also, there are plans for a new and improved CustomSelectControl which will allow for easier layout customization like this at the instance-level, so there's also an option to wait until that's ready.

@luminuu
Copy link
Member Author

luminuu commented Sep 17, 2025

If this is a real problem, it should be fixed in the CustomSelectControl component itself, rather than overriding the CustomSelectControl behavior. Perhaps we can discuss the design in a separate issue or PR.

Agreed. Also, there are plans for a new and improved CustomSelectControl which will allow for easier layout customization like this at the instance-level, so there's also an option to wait until that's ready.

Is there already an issue for improving the CustomSelectControl?

@mirka
Copy link
Member

mirka commented Sep 17, 2025

Is there already an issue for improving the CustomSelectControl?

Sorry, hard to find 😅 #55023

@karmatosed
Copy link
Member

@mirka is there a timeline on that being implemented? I know that is a hard ask but I am wondering if that is going to be a blocker to getting this in or if this could be something worked around within this PR to not require changes to a global component. That might be asking a lot and the other option is to get some timing on this with the other issue if that is possible.

What I see in review is an issue started in 2023, with quite a bit of work going on lately (which is great), does this mean it is going to land in the next few versions or hope to?

@mirka
Copy link
Member

mirka commented Sep 30, 2025

I'm not in a position to say about the timeline, but I don't think it necessarily has to be a blocker for this PR.

If we only need to wrap the hint to the next line, could we just do the minimum possible style override, for example set width: 100% on .components-custom-select-control__item-hint? I think we can stomach a temporary style override if it's only a line or two.

@luminuu
Copy link
Member Author

luminuu commented Oct 13, 2025

I'm not in a position to say about the timeline, but I don't think it necessarily has to be a blocker for this PR.

If we only need to wrap the hint to the next line, could we just do the minimum possible style override, for example set width: 100% on .components-custom-select-control__item-hint? I think we can stomach a temporary style override if it's only a line or two.

I have now reduced the CSS to that one line changing the width to 100% and it just works fine.

I've tried to get the remaining checks passing but for some reason it always gets stuck on this:

You are trying to create a styled element with an undefined component.
    You may have forgotten to import it.

But the component is imported as an external dependency a few lines above. Or am I doing something else wrong here? @mirka @t-hamano @Mamaduka

Copy link
Member

@ramonjd ramonjd left a comment

Choose a reason for hiding this comment

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

Thanks a lot for tackling this tricky problem!! 🙏🏻

Sorry if a lot of my comments are premature - I know you're working on the internals.

I think things are on the right track with the valueMode as folks have suggested, I was just having trouble testing the functionality in both block and global styles.

From what I can gather we're going to refer to selectedSlug and then set valueMode to "slug" if there is one?

In my opinion, unit tests would greatly help reason about the logic here (and catch bugs!). Also updating the storybook examples to cover these cases. If this is to get into 6.9 then I think both are required, even as follow ups to this PR.

But I understand things are still in motion so take what I've said with as much salt as you need right now 😄

Here' an example of some presets I was testing:

theme.json typography settings
		"typography": {
			"defaultFontSizes": false,
			"fluid": true,
			"fontSizes": [
				{
					"name": "Tiny Test",
					"slug": "tiny",
					"size": "12px"
				},
				{
					"name": "Small Test",
					"slug": "small", 
					"size": "12px"
				},
				{
					"name": "Base Test",
					"slug": "base",
					"size": "16px"
				},
				{
					"name": "Medium Test",
					"slug": "medium",
					"size": "18px"
				},
				{
					"name": "Large Test",
					"slug": "large",
					"size": "20px"
				},
				{
					"name": "Extra Large Test",
					"slug": "extra-large",
					"size": "24px"
				},
				{
					"name": "Huge Test",
					"slug": "huge",
					"size": "32px",
					"fluid": {
						"min": "16px",
						"max": "32px"
					}
				},
				{
					"name": "Giant Test",
					"slug": "giant",
					"size": "48px"
				},
				{
					"name": "Display Small Test",
					"slug": "display-small",
					"size": "32px"
				},
				{
					"name": "Display Large Test",
					"slug": "display-large",
					"size": "48px"
				}
			]
		}
	},

size = 'default',
units: unitsProp = DEFAULT_UNITS,
value,
valueMode = 'literal',
Copy link
Member

Choose a reason for hiding this comment

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

Is there a condition for which this should be 'slug'?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's literal when you use a custom font size that is not a preset, but it's slug when you use a preset. Previously the font size was only working with size, so you were not able to select a different font size if the size property held the same value, even if it was a fixed vs. a fluid value. Now it differentiates on the slugs of you use a preset, so when using for example TT5 it can hold small, medium, large and so on, and custom sizes well you can add via the typography interface.

@luminuu
Copy link
Member Author

luminuu commented Oct 17, 2025

Thanks a lot for tackling this tricky problem!! 🙏🏻

Sorry if a lot of my comments are premature - I know you're working on the internals.

I think things are on the right track with the valueMode as folks have suggested, I was just having trouble testing the functionality in both block and global styles.

From what I can gather we're going to refer to selectedSlug and then set valueMode to "slug" if there is one?

In my opinion, unit tests would greatly help reason about the logic here (and catch bugs!). Also updating the storybook examples to cover these cases. If this is to get into 6.9 then I think both are required, even as follow ups to this PR.

But I understand things are still in motion so take what I've said with as much salt as you need right now 😄

Here' an example of some presets I was testing:
theme.json typography settings


</details>

Thank you for your feedback @ramonjd! I think the code was a bit confusing, I just removed the remaining selectedSlug values, which were in the code of my first iteration. As @t-hamano and @mirka pointed out, it makes no sense to have the value stored in two variables, as there's no single source of truth. So I went ahead and changed the code yesterday to work with the valueMode prop. I just removed the remaining instances of selectedSlug, so maybe the code is now a bit clearer to understand.

Copy link
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

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

Thanks for all the hard work on this @luminuu 🙇

I'm not fully up-to-date on the history and context of this PR but I've taken the latest changes for a spin in both the site editor with global styles and the block editor.

It is testing as per the test instructions for me.

✅ Could replicate issue with toggle group control on trunk
✅ Could replicate issue with font size picker dropdown on trunk
✅ This PR fixes selection of preset font sizes for the toggle group control
✅ This PR fixes selection when picker is using the dropdown
✅ When using this PR I could not replicate reported custom value issue

This is very close I think. Just a few remaining pieces of earlier feedback to address and it should be good to go.

The unit tests don't need to be a blocker and could be added via a follow-up.

@ramonjd
Copy link
Member

ramonjd commented Oct 20, 2025

I just removed the remaining selectedSlug values, which were in the code of my first iteration.

Ah got it, thanks for that. I retested and things are working well.

Just curious if other folks can see the selected preset disappearing after save (this is for toggle + select, block + global styles)

Kapture.2025-10-20.at.11.13.41.mp4

Here's the JSON I'm using to test:

		"typography": {
			"defaultFontSizes": false,
			"fluid": true,
			"fontSizes": [
				{
					"name": "Extra Large Test",
					"slug": "extra-large",
					"size": "24px"
				},
				{
					"name": "Huge Test",
					"slug": "huge",
					"size": "32px",
					"fluid": {
						"min": "16px",
						"max": "32px"
					}
				},
				{
					"name": "Giant Test",
					"slug": "giant",
					"size": "48px"
				},
				{
					"name": "Display Small Test",
					"slug": "display-small",
					"size": "32px"
				},
				{
					"name": "Display Large Test",
					"slug": "display-large",
					"size": "48px"
				}
			]
		}
	},

@aaronrobertshaw
Copy link
Contributor

@ramonjd Thanks for the extra debugging and testing here. I can replicate the issue you reported.

I used empty theme and simply added two font size presets with matching font size values.

From my debugging so far the issue is related to the different preset data formats between global styles and block supports. I believe block supports will encode to a var:preset:* string whereas global styles uses var(--wp--preset--*).

Quickly updating the currentFontSizeSlug logic to handle this appears on the surface to fix the selection however the persisting of the font size still isn't correct so the selection is lost on refreshing the page.

@aaronrobertshaw
Copy link
Contributor

@luminuu I hope you don't mind but I took the liberty of pushing a quick commit that I believe fixes the issue @ramonjd highlighted.

This quick fix has the selection of font size presets working again for me in the Global Styles typography panel.

Screen.Recording.2025-10-20.at.5.49.43.pm.mp4

It appears our CI is down due to an AWS outage. @ramonjd if you can re-test and confirm this fix, could you also then kick off the e2es as well?

@luminuu
Copy link
Member Author

luminuu commented Oct 20, 2025

Thank you for the quick fix @aaronrobertshaw! I'll work on the other feedback @ramonjd has provided today, if there's anything no longer relevant just mark it as resolved.

@luminuu
Copy link
Member Author

luminuu commented Oct 20, 2025

I've now figured out why the one Playwright test is failing: in trunk, when selecting a font size preset from the dropdown, the size prop is added to the input field when you switch from presets to "Set custom size" (the toggle on the right next to the "Size" heading). With this PR, this is no longer happening and therefore the test is failing. I haven't looked into the other tests in detail but I assume there might be similar issues.

I assume this needs to be fixed and we're not changing the Playwright tests, is that correct? @ramonjd

@luminuu
Copy link
Member Author

luminuu commented Oct 20, 2025

Figured out the issue with the failing checks myself and did another commit. I think I have addressed all feedback, let me know if there's still something unclear / I should take a look at.

@ramonjd
Copy link
Member

ramonjd commented Oct 20, 2025

Thanks @luminuu and @aaronrobertshaw

This is testing well for me!

  • selected presets persist in the controls where there are duplicates
  • global styes/block styles are applied as expected
  • no regressions on fluid typography values as far as I can see

I appreciate all the hard work 🙇🏻

@t-hamano do you think we can still get this PR into 6.9 in the next package update?

Copy link
Member

@ramonjd ramonjd left a comment

Choose a reason for hiding this comment

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

Thanks for sticking with this one @luminuu

And for the tests!

I think this is going to be a high-impact bug fix.

@ramonjd ramonjd added the Backport to WP 6.9 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Oct 20, 2025
@t-hamano
Copy link
Contributor

do you think we can still get this PR into 6.9 in the next package update?

This PR adds a new prop to a component, so it's strictly an enhancement. Gutenberg 21.9 RC1 and RC2 have already been released, but if RC3 is planned before 6.9 Beta1, this PR could be cherry-picked. cc @ellatrix @priethor

However, since this PR fixes many bugs at the same time, I think it would be fine to backport it to Beta1 or later.

@Mamaduka
Copy link
Member

I think it's okay to include this in beta cycles.

@priethor
Copy link
Contributor

Confirming we are having a GB RC3 with the latest cherry-picked PRs, but I agree it's fine to ship this post-Beta1.

Copy link
Contributor

@t-hamano t-hamano left a comment

Choose a reason for hiding this comment

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

Is there anything else we should do? If not, let's backport it to 6.9 Beta2.

Added documentation for the 'valueMode' prop in font size picker.
@ramonjd ramonjd merged commit 9b22cc3 into WordPress:trunk Oct 24, 2025
34 checks passed
@github-actions github-actions bot added this to the Gutenberg 22.0 milestone Oct 24, 2025
@github-actions github-actions bot removed the Backport to WP 6.9 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Oct 24, 2025
gutenbergplugin pushed a commit that referenced this pull request Oct 24, 2025
…lue (#71703)

Co-authored-by: luminuu <[email protected]>
Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: ramonjd <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: mirka <[email protected]>
Co-authored-by: hanneslsm <[email protected]>
Co-authored-by: karmatosed <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: priethor <[email protected]>
Co-authored-by: pagelab <[email protected]>
Co-authored-by: SH4LIN <[email protected]>
Co-authored-by: andersnoren <[email protected]>
Co-authored-by: matiasbenedetto <[email protected]>
Co-authored-by: susurruses <[email protected]>
Co-authored-by: uniquesolution <[email protected]>
@github-actions github-actions bot added the Backported to WP Core Pull request that has been successfully merged into WP Core label Oct 24, 2025
@github-actions
Copy link

I just cherry-picked this PR to the wp/6.9 branch to get it included in the next release: d14bfe4

sidharthpandita1 pushed a commit to sidharthpandita1/gutenberg that referenced this pull request Oct 24, 2025
…lue (WordPress#71703)

Co-authored-by: luminuu <[email protected]>
Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: ramonjd <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: mirka <[email protected]>
Co-authored-by: hanneslsm <[email protected]>
Co-authored-by: karmatosed <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: priethor <[email protected]>
Co-authored-by: pagelab <[email protected]>
Co-authored-by: SH4LIN <[email protected]>
Co-authored-by: andersnoren <[email protected]>
Co-authored-by: matiasbenedetto <[email protected]>
Co-authored-by: susurruses <[email protected]>
Co-authored-by: uniquesolution <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backported to WP Core Pull request that has been successfully merged into WP Core [Feature] Typography Font and typography-related issues and PRs Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json [Package] Components /packages/components [Type] Bug An existing feature does not function as intended

Projects

None yet

9 participants