Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Truncate: improve handling of non-string children #57261

Merged
merged 9 commits into from
Dec 21, 2023

Conversation

ciampo
Copy link
Contributor

@ciampo ciampo commented Dec 20, 2023

What?

This PR introduces a few changes to the Truncate component to make it more resilient to different types of children received:

  • it makes the component able to truncate children of type number
  • when children have types other than string or number, the component renders the children without any attempted truncation (instead of not rendering the children at all)

Why?

While working on #55625, I discovered that Truncate only handles children of type string, and otherwise renders an empty <span /> tag.

The component falsely advertises that its children are of type ReactNode, while in reality the component only knows how to deal with string.

This behaviour is not great, and can cause confusion and disruption in the consumers of Truncate

How?

Tweaked the logic of the truncate hook:

  • numbers are converted to string so that they can be truncated
  • when detecting children that are not string of number type, the component simply no-ops and renders children as-is
  • added unit tests for this new behaviour

@ciampo ciampo force-pushed the feat/truncate-convert-input-to-string branch from 61b3259 to 2871be5 Compare December 20, 2023 13:11
@ciampo ciampo self-assigned this Dec 20, 2023
@ciampo ciampo requested review from ntsekouras and a team December 20, 2023 13:13
@ciampo ciampo added [Type] Bug An existing feature does not function as intended [Package] Components /packages/components labels Dec 20, 2023
@ciampo ciampo marked this pull request as ready for review December 20, 2023 13:13
Copy link
Contributor

@ntsekouras ntsekouras left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

Interesting, yes it looks like the Truncate/Text primitives are designed to be quite permissive with the type of their children!

I think the approach here is good (and of course the added tests!), although I'd like to suggest a few more things to mitigate consumer confusion:

  • We should mention in the children prop description that truncation won't happen unless it's string/number.
  • I noticed that Text actually throws when you try to use the highlight feature with a non-string. Obviously for back-compat reasons we can't start throwing here now, but maybe it merits a warn()? (No strong opinion on this one)

@ciampo
Copy link
Contributor Author

ciampo commented Dec 20, 2023

Thank you for the review, @ntsekouras and @mirka !

I'd like to suggest a few more things to mitigate consumer confusion:

Sounds good, I went ahead and implemented the suggested changes.

@ciampo ciampo enabled auto-merge (squash) December 20, 2023 17:05
childrenAsText = children.toString();
} else {
// eslint-disable-next-line no-console
console.warn(
Copy link
Member

Choose a reason for hiding this comment

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

I think it's preferable to use @wordpress/warning?

} else {
// eslint-disable-next-line no-console
console.warn(
`Truncate: text truncation has been disabled, since it is only available when passing 'children' of type 'string' or 'number'`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
`Truncate: text truncation has been disabled, since it is only available when passing 'children' of type 'string' or 'number'`
`wp.components.Truncate: text truncation has been disabled, since it is only available when passing 'children' of type 'string' or 'number'`

Probably better for clarity, since Truncate is used under the hood for a handful of more common components and the consumer may not be aware of what "Truncate" is specifically.

@ciampo
Copy link
Contributor Author

ciampo commented Dec 21, 2023

Looking more into unit tests failures, it emerges that a lot of components use Truncate indirectly via the Text and Heading components.

The problem with that is that the Text component adds some extra logic to its hook which in some cases completely ignores the result of calling useTruncate:

let finalEllipsizeMode: undefined | 'auto' | 'none';
if ( truncate === true ) {
finalEllipsizeMode = 'auto';
}
if ( truncate === false ) {
finalEllipsizeMode = 'none';
}
const finalComponentProps = {
...otherProps,
className: classes,
children,
ellipsizeMode: ellipsizeMode || finalEllipsizeMode,
};
const truncateProps = useTruncate( finalComponentProps );
/**
* Enhance child `<Link />` components to inherit font size.
*/
if ( ! truncate && Array.isArray( children ) ) {
content = Children.map( children, ( child ) => {
if (
typeof child !== 'object' ||
child === null ||
! ( 'props' in child )
) {
return child;
}
const isLink = hasConnectNamespace( child, [ 'Link' ] );
if ( isLink ) {
return cloneElement( child, {
size: child.props.size || 'inherit',
} );
}
return child;
} );
}

Therefore, I don't think that showing a warning makes a lot of sense because it would just pollute the console for a lot of Text` consumers.

@ciampo ciampo force-pushed the feat/truncate-convert-input-to-string branch from ff93065 to 23818de Compare December 21, 2023 10:27
Copy link

Flaky tests detected in 23818de.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/7286939991
📝 Reported issues:

@ciampo ciampo merged commit 2b5cfdf into trunk Dec 21, 2023
56 checks passed
@ciampo ciampo deleted the feat/truncate-convert-input-to-string branch December 21, 2023 10:53
@github-actions github-actions bot added this to the Gutenberg 17.4 milestone Dec 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Bug An existing feature does not function as intended
Projects
Status: Done 🎉
Development

Successfully merging this pull request may close these issues.

3 participants