Skip to content

fix(react): fix icon rendering in v0.9 basic catalog#1031

Merged
jacobsimionato merged 2 commits intogoogle:mainfrom
ppazosp:fix/946-react-icon-rendering
Apr 11, 2026
Merged

fix(react): fix icon rendering in v0.9 basic catalog#1031
jacobsimionato merged 2 commits intogoogle:mainfrom
ppazosp:fix/946-react-icon-rendering

Conversation

@ppazosp
Copy link
Copy Markdown
Contributor

@ppazosp ppazosp commented Mar 29, 2026

Description

Adds camelCase-to-snake_case conversion for icon names in the React v0.9 Icon component.

The A2UI spec defines icon names in camelCase (e.g., shoppingCart) but Material Symbols Outlined font requires snake_case ligatures (shopping_cart). Without this conversion, multi-word icon names rendered as empty/broken boxes. The fix matches the existing pattern used in Angular v0.9 and React v0.8 renderers.

Fixes #946

Pre-launch Checklist

Add camelCase to snake_case conversion for Material Symbols icon names.
The A2UI spec uses camelCase names (e.g., skipPrevious, shoppingCart)
but Material Symbols Outlined requires snake_case (skip_previous,
shopping_cart). This matches the approach used in the Angular renderer
and React v0_8 renderer.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds a toSnakeCase helper function to the Icon component to ensure icon names are correctly formatted for Material Symbols. Feedback was provided to improve the regex implementation to avoid generating leading underscores for capitalized input strings.

* e.g., "shoppingCart" -> "shopping_cart", "skipPrevious" -> "skip_previous"
*/
function toSnakeCase(str: string): string {
return str.replace(/([A-Z])/g, '_$1').toLowerCase();
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.

medium

The current implementation of toSnakeCase will produce a leading underscore for strings that start with an uppercase letter (e.g., 'ShoppingCart' becomes '_shopping_cart'). This is likely not the intended behavior for Material Symbols font ligatures.

A more robust implementation would handle this case correctly. Using a negative lookbehind (?<!^) can prevent matching an uppercase letter at the beginning of the string.

Suggested change
return str.replace(/([A-Z])/g, '_$1').toLowerCase();
return str.replace(/(?<!^)([A-Z])/g, '_$1').toLowerCase();

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.

The A2UI schema enforces camelCase icon names via a Zod enum (ICON_NAMES in basic_components.ts), so PascalCase input is never valid. This regex is also identical to Angular v0.9 (icon.component.ts:98) and React v0.8 (Icon.tsx:29). Changing it here would break consistency across renderers.

@jacobsimionato
Copy link
Copy Markdown
Collaborator

This LGTM, but I saw some icons are still broken - e.g. play?
Screenshot 2026-04-10 at 1 51 16 PM

I think the icons in our specification don't exactly match material, so it's necessary to have a lookup table to translate the names. Would you be willing to figure that out?

Thank you so much again!!

@ppazosp
Copy link
Copy Markdown
Contributor Author

ppazosp commented Apr 10, 2026

Thanks for the review and the screenshot! You're right, the camelCase-to-snake_case conversion only fixes multi-word icons. Single-word mismatches like play (which should be play_arrow in Material Symbols) need a separate lookup table.

I checked all 59 spec icon names against Material Symbols Outlined ligatures. Only 4 need explicit mapping:

Spec name Material Symbols
play play_arrow
rewind fast_rewind
favoriteOff favorite_border
starOff star_border

The other 55 all resolve correctly with the camelCase-to-snake_case conversion alone.

I'll add the lookup table to this PR.

@ppazosp
Copy link
Copy Markdown
Contributor Author

ppazosp commented Apr 10, 2026

I checked all v0.9 renderers and the issue goes beyond React:

Renderer snake_case conversion Override mapping
React v0.9 Yes (this PR) Not yet
Angular v0.9 Yes No
Lit v0.9 No No

Lit v0.9 doesn't even do camelCase-to-snake_case, so multi-word icons like shoppingCart are also broken there.

Happy to fix all three v0.9 renderers in this PR if you'd prefer, or I can keep this one scoped to React and open separate issues for the others.

@jacobsimionato
Copy link
Copy Markdown
Collaborator

Thank you so much for the analysis!!

I'll merge this change now seeing as it's a strict improvement and brings renderers to consistency. If you could write another change to fix all three renderers for v0.9 so that all the icons work, that would be amazing!

@jacobsimionato jacobsimionato merged commit 0262a2d into google:main Apr 11, 2026
9 of 10 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in A2UI Apr 11, 2026
@ppazosp
Copy link
Copy Markdown
Contributor Author

ppazosp commented Apr 11, 2026

Of course I can mate!! omw!

@ppazosp
Copy link
Copy Markdown
Contributor Author

ppazosp commented Apr 11, 2026

Opened #1146 with the override map for all three v0.9 renderers and tests. Hope its good!!

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

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[React] Fix icon rendering

2 participants