Stretchy Text: Accept very small font sizes, and show a warning#73730
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: +465 B (+0.02%) Total Size: 2.58 MB
ℹ️ View Unchanged
|
| // Note: The `Notice` component can speak messages via its `spokenMessage` | ||
| // prop, but similar to the contrast checker, we use granular control over | ||
| // when the announcements are made. | ||
| speak( message ); |
There was a problem hiding this comment.
I haven't tested this but, wouldn't this give information to screen readers in every render? I wonder if it'd be best to use this only when mounting the component. 🤔
There was a problem hiding this comment.
I added logic to only speak when mounting the component.
| isSelected && | ||
| fontSize < MIN_FONT_SIZE_FOR_WARNING && ( | ||
| <InspectorControls group="styles"> | ||
| <FitTextSizeWarning fontSize={ fontSize } /> |
There was a problem hiding this comment.
Did you mean to use the fontSize in the FitTextSizeWarning component? It's not used right now.
There was a problem hiding this comment.
Yah the font size prop is not needed, I removed it from the code.
| const alreadyHasScrollableHeight = | ||
| textElement.scrollHeight > textElement.clientHeight; | ||
| let minSize = 5; | ||
| let minSize = 0; |
There was a problem hiding this comment.
The JSDoc above still says 5-600px
There was a problem hiding this comment.
Good catch the comment was updated!
| /** | ||
| * Higher-order component that when fit text is enabled, | ||
| * adds the FitTextEdit component to the block's edit interface. | ||
| * We could not use the expored edit component because, we need | ||
| * this to added even when the block is not selected to ensure | ||
| * the fit text calculations are done. | ||
| */ |
There was a problem hiding this comment.
I tried the following: remove this HOC and make edit: ()=> null just edit: FixTextEdit. It didn't work. My understanding is that it doesn't because the useFitText clean up function removes the style when is unmounted.
With the edit approach, the edit export renders in the inspector panel, which is separate from the block:
<Editor>
├── <BlockList>
│ └── <Block clientId="abc">
│ └── <BlockEdit />
│
└── <InspectorPanel> ← Only shows controls for selected block
└── <BlockInspector>
└── <FitTextEdit /> ← Mounted ONLY when block is selected
└── useFitText() runsbut when the block is unselected:
<Editor>
├── <BlockList>
│ └── <Block clientId="abc">
│ └── <BlockEdit />
│
└── <InspectorPanel>
└── (empty or different block's controls)
← FitTextEdit UNMOUNTED
← useEffect cleanup runs
← Style element removedHowever, the HOC approach works because FixTextEdit is always part of the block render tree:
<Editor>
└── <BlockList>
└── <Block clientId="abc"> ← Always mounted while block exists
└── <withFitTextEdit> ← HOC wrapper
├── <BlockEdit /> ← The actual block UI
└── <FitTextEdit /> ← Always mounted when fitText=true
└── useFitText() runs
└── returns warning UI only if isSelectedI reckon I'm a bit rusty after a few years not working with block supports, so wanted to document my understanding in case I've missed something.
There was a problem hiding this comment.
Hi @oandregal, edit: FixTextEdit, does not work because it only renders when the block is selected, and for fit text even if the block is not selected we may need to recompute the font size, because for example the container width may have changed.
oandregal
left a comment
There was a problem hiding this comment.
This works as expected. Left a few minor comments and a question, but I think it's good.
c2b4c56 to
c436b31
Compare
|
Flaky tests detected in 74bc80e. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/20302369523
|
| { fitText && ( | ||
| <FitTextEdit | ||
| clientId={ clientId } | ||
| fitText={ fitText } | ||
| setAttributes={ props.setAttributes } | ||
| name={ name } | ||
| attributes={ attributes } | ||
| isSelected={ isSelected } | ||
| /> | ||
| ) } | ||
| { ! fitText && isSelected && ( | ||
| <FitTextControl | ||
| clientId={ clientId } | ||
| fitText={ fitText } | ||
| setAttributes={ setAttributes } | ||
| name={ name } | ||
| fontSize={ attributes.fontSize } | ||
| style={ attributes.style } | ||
| /> | ||
| ) } |
There was a problem hiding this comment.
I found this arrangement a bit confusing, even though I understand that the motivation is to ensure useFitText is only called when needed. Thinking about clearer ways to express this, how about:
Encapsulate the hook calling in a HoC:
function WithFitTextFontSize( { fitText, name, clientId, children } ) {
const { fontSize } = useFitText( { fitText, name, clientId } );
return children( fontSize );
}Render FitTextControl in both branches, but with the HoC mediating the font-size computation:
return (
<>
<BlockEdit { ...props } />
{ fitText && (
<WithFitTextFontSize
fitText={ fitText }
name={ name }
clientId={ clientId }
>
{ ( fontSize ) =>
isSelected && (
<FitTextControl
clientId={ clientId }
fitText={ fitText }
setAttributes={ setAttributes }
name={ name }
fontSize={ attributes.fontSize }
style={ attributes.style }
warning={
fontSize <
MIN_FONT_SIZE_FOR_WARNING && (
<FitTextSizeWarning />
)
}
/>
)
}
</WithFitTextFontSize>
) }
{ ! fitText && isSelected && (
<FitTextControl
clientId={ clientId }
fitText={ fitText }
setAttributes={ setAttributes }
name={ name }
fontSize={ attributes.fontSize }
style={ attributes.style }
/>
) }
</>
);This way, the reader immediately sees what gets rendered and no longer needs to keep in mind the difference between FitTextControl and FitTextEdit.
If this sounds like an improvement, I can push to a new branch — @jorgefilipecosta @oandregal
There was a problem hiding this comment.
Hi @mcsf this sounds like a code clarity improvement 👍, feel free to push the changes or let me know and I can also do it.
| import { createHigherOrderComponent } from '@wordpress/compose'; | ||
|
|
||
| const EMPTY_OBJECT = {}; | ||
| const MIN_FONT_SIZE_FOR_WARNING = 6; |
There was a problem hiding this comment.
In my testing, this felt way too low. Why 6? It feels to me like anything below 12px should raise a warning. Definitely below 10px, but most likely below 12px. No? @jorgefilipecosta
There was a problem hiding this comment.
Good questions, 6px is being used because the previous minimum possible size was 6px, so this PR removed the minimum but added a warning for values that previously were not possible. Off-course we can reconsider a better value, 12px sounds good to me.
Fixes: #73720
Makes the min size for fit text, equal to 0, ensuring text will always fit the container no matter how long the text is.
Adds a warning notice in the block inspector's when the fit text feature computes a font size below 6px, similar to the existing color contrast warning. This helps users understand when their text may be too small to read and suggests using a larger container or less text.
Ideally the warning would appear between the stretchy text, and styles section at the top, but we don't have an API too do that.
I also considered the Typography section, but it is a tools panel and we can not simply add a warning there that appears all the time.
Screenshots
Testing Instructions for Keyboard
Write a very very long text string inside a Stretchy Text block.
Verify when the font size gets smaller than 6px a warning appears.