From ea77512ae0d776feea5ed46b7444f6e51e21eee8 Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 16:46:54 -0700 Subject: [PATCH 01/11] Rename Icon path property to svgPath to fix type collision Rename the property inside the object from path to svgPath in IconApi schema. This breaks the structural match with DataBindingType and preserves the type in the union, avoiding the need for as any casts in renderers. TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- renderers/angular/src/v0_9/catalog/basic/icon.component.ts | 4 ++-- .../angular/src/v0_9/catalog/basic/simple-components.spec.ts | 2 +- renderers/react/package-lock.json | 2 +- renderers/react/src/v0_9/catalog/basic/components/Icon.tsx | 2 +- .../src/v0_9/basic_catalog/components/basic_components.ts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/renderers/angular/src/v0_9/catalog/basic/icon.component.ts b/renderers/angular/src/v0_9/catalog/basic/icon.component.ts index 18b508396..1a62f5f12 100644 --- a/renderers/angular/src/v0_9/catalog/basic/icon.component.ts +++ b/renderers/angular/src/v0_9/catalog/basic/icon.component.ts @@ -90,12 +90,12 @@ export class IconComponent extends BasicCatalogComponent { readonly isPath = computed(() => { const name = this.iconNameRaw(); - return typeof name === 'object' && name !== null && 'path' in name; + return typeof name === 'object' && name !== null && 'svgPath' in name; }); readonly path = computed(() => { const name = this.iconNameRaw(); - return (name as any)?.path || ''; + return (name as any)?.svgPath || ''; }); readonly iconName = computed(() => { diff --git a/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts b/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts index a37bf3f14..1b2676d7f 100644 --- a/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts +++ b/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts @@ -275,7 +275,7 @@ describe('Simple Components', () => { it('should render path icon', () => { fixture.componentRef.setInput('props', { - name: createBoundProperty({path: 'M10 10...'}), + name: createBoundProperty({svgPath: 'M10 10...'}), }); fixture.detectChanges(); const svg = fixture.nativeElement.querySelector('svg'); diff --git a/renderers/react/package-lock.json b/renderers/react/package-lock.json index 7880f4da8..22a8cf8a0 100644 --- a/renderers/react/package-lock.json +++ b/renderers/react/package-lock.json @@ -75,7 +75,7 @@ "version": "0.0.4", "license": "Apache-2.0", "dependencies": { - "dompurify": "^3.3.1", + "dompurify": "3.3.1", "markdown-it": "^14.1.0" }, "devDependencies": { diff --git a/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx b/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx index 4dafef380..2eaaec56d 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx @@ -39,7 +39,7 @@ export const Icon = createComponentImplementation(IconApi, ({props}) => { const iconName = typeof props.name === 'string' ? toMaterialSymbol(props.name) - : (props.name as {path?: string})?.path; + : (props.name as {svgPath?: string})?.svgPath; const style: React.CSSProperties = { ...getBaseLeafStyle(), diff --git a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts index ce1c4a385..26268c340 100644 --- a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts +++ b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts @@ -152,7 +152,7 @@ export const IconApi = { z.enum(ICON_NAMES), z .object({ - path: z.string(), + svgPath: z.string(), }) .strict(), ]) From f9942742677e48bda13e318a5ee47a0973480fe1 Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 16:53:58 -0700 Subject: [PATCH 02/11] Address review comments: update React Icon to render SVG, revert lockfile change, and add schema description - Update React Icon component to render SVG when svgPath is provided. - Revert unintentional pinning of dompurify in React package-lock.json. - Add description to svgPath in IconApi schema. TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- renderers/react/package-lock.json | 2 +- .../v0_9/catalog/basic/components/Icon.tsx | 38 +++++++++++++++---- .../components/basic_components.ts | 2 +- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/renderers/react/package-lock.json b/renderers/react/package-lock.json index 22a8cf8a0..7880f4da8 100644 --- a/renderers/react/package-lock.json +++ b/renderers/react/package-lock.json @@ -75,7 +75,7 @@ "version": "0.0.4", "license": "Apache-2.0", "dependencies": { - "dompurify": "3.3.1", + "dompurify": "^3.3.1", "markdown-it": "^14.1.0" }, "devDependencies": { diff --git a/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx b/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx index 2eaaec56d..a2d485d58 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx @@ -36,29 +36,51 @@ function toMaterialSymbol(str: string): string { export const Icon = createComponentImplementation(IconApi, ({props}) => { useBasicCatalogStyles(); - const iconName = - typeof props.name === 'string' - ? toMaterialSymbol(props.name) - : (props.name as {svgPath?: string})?.svgPath; + + const isPath = typeof props.name === 'object' && props.name !== null && 'svgPath' in props.name; - const style: React.CSSProperties = { + const baseStyle: React.CSSProperties = { ...getBaseLeafStyle(), display: 'inline-flex', alignItems: 'center', justifyContent: 'center', - fontFamily: 'var(--a2ui-icon-font-family, "Material Symbols Outlined", sans-serif)', fontSize: 'var(--a2ui-icon-size, var(--a2ui-font-size-xl, 24px))', color: 'var(--a2ui-icon-color, inherit)', + lineHeight: 1, + }; + + if (isPath) { + const path = (props.name as {svgPath: string}).svgPath; + return ( + + + + ); + } + + const iconName = typeof props.name === 'string' ? toMaterialSymbol(props.name) : ''; + + const fontStyle: React.CSSProperties = { + ...baseStyle, + fontFamily: 'var(--a2ui-icon-font-family, "Material Symbols Outlined", sans-serif)', fontVariationSettings: 'var(--a2ui-icon-font-variation-settings, "FILL" 1)', fontWeight: 'normal', fontStyle: 'normal', - lineHeight: 1, letterSpacing: 'normal', textTransform: 'none', }; return ( - + {iconName} ); diff --git a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts index 26268c340..69168fae5 100644 --- a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts +++ b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts @@ -152,7 +152,7 @@ export const IconApi = { z.enum(ICON_NAMES), z .object({ - svgPath: z.string(), + svgPath: z.string().describe('Custom SVG path data'), }) .strict(), ]) From d46fb22f082c1d4c67b168f96606dbfb2a6207bd Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 16:59:52 -0700 Subject: [PATCH 03/11] don't use any in icon component --- .../src/v0_9/catalog/basic/icon.component.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/renderers/angular/src/v0_9/catalog/basic/icon.component.ts b/renderers/angular/src/v0_9/catalog/basic/icon.component.ts index 1a62f5f12..0cbf8bc24 100644 --- a/renderers/angular/src/v0_9/catalog/basic/icon.component.ts +++ b/renderers/angular/src/v0_9/catalog/basic/icon.component.ts @@ -42,9 +42,9 @@ const ICON_NAME_OVERRIDES: Record = { standalone: true, imports: [], template: ` - @if (isPath()) { + @if (isSvgPath()) { - + } @else { @@ -88,14 +88,17 @@ export class IconComponent extends BasicCatalogComponent { readonly color = computed(() => (this.props() as AnyDuringSchemaAlignment)['color']?.value()); readonly iconNameRaw = computed(() => this.props()['name']?.value()); - readonly isPath = computed(() => { + readonly isSvgPath = computed(() => { const name = this.iconNameRaw(); return typeof name === 'object' && name !== null && 'svgPath' in name; }); - readonly path = computed(() => { + readonly svgPath = computed(() => { const name = this.iconNameRaw(); - return (name as any)?.svgPath || ''; + if (typeof name === 'object' && name !== null && 'svgPath' in name) { + return name.svgPath; + } + return ''; }); readonly iconName = computed(() => { From d1c8bc8fe99d652a4e479b1b5cce6aadc4ebce38 Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 17:02:54 -0700 Subject: [PATCH 04/11] Update Lit Icon component to support svgPath - Update Lit Icon component to render SVG when svgPath is provided. - Update usages from path to svgPath. TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- .../src/v0_9/catalogs/basic/components/Icon.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/renderers/lit/src/v0_9/catalogs/basic/components/Icon.ts b/renderers/lit/src/v0_9/catalogs/basic/components/Icon.ts index a4f40b008..29ecddddc 100644 --- a/renderers/lit/src/v0_9/catalogs/basic/components/Icon.ts +++ b/renderers/lit/src/v0_9/catalogs/basic/components/Icon.ts @@ -64,6 +64,11 @@ export class A2uiIconElement extends BasicCatalogA2uiLitElement color: var(--a2ui-icon-color, inherit); font-variation-settings: var(--a2ui-icon-font-variation-settings, 'FILL' 1); } + .svg { + fill: currentColor; + width: var(--_icon-size); + height: var(--_icon-size); + } `; protected createController() { @@ -74,8 +79,15 @@ export class A2uiIconElement extends BasicCatalogA2uiLitElement const props = this.controller.props; if (!props) return nothing; - const iconName = - typeof props.name === 'string' ? toMaterialSymbol(props.name) : (props.name as any)?.path; + const name = props.name; + const isPath = typeof name === 'object' && name !== null && 'svgPath' in name; + + if (isPath) { + const path = (name as {svgPath: string}).svgPath; + return html``; + } + + const iconName = typeof name === 'string' ? toMaterialSymbol(name) : ''; return html`${iconName}`; } } From f8cf81cfbcff21f3e35d89db35869b4beff7c08b Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 17:05:51 -0700 Subject: [PATCH 05/11] Apply formatting fixes TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- renderers/react/src/v0_9/catalog/basic/components/Icon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx b/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx index a2d485d58..0e2831024 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/Icon.tsx @@ -36,7 +36,7 @@ function toMaterialSymbol(str: string): string { export const Icon = createComponentImplementation(IconApi, ({props}) => { useBasicCatalogStyles(); - + const isPath = typeof props.name === 'object' && props.name !== null && 'svgPath' in props.name; const baseStyle: React.CSSProperties = { From 843cf7b229cf46c98ba473fda3b33f1dc8e5ed0f Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 17:14:20 -0700 Subject: [PATCH 06/11] Update changelogs for Icon path rename TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- renderers/angular/CHANGELOG.md | 1 + renderers/lit/CHANGELOG.md | 1 + renderers/react/CHANGELOG.md | 1 + renderers/web_core/CHANGELOG.md | 4 ++++ 4 files changed, 7 insertions(+) diff --git a/renderers/angular/CHANGELOG.md b/renderers/angular/CHANGELOG.md index e9e8eb4f2..d5628ac14 100644 --- a/renderers/angular/CHANGELOG.md +++ b/renderers/angular/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- (v0_9) Rename Icon `path` property to `svgPath` to fix type collision and avoid forced casts. - (v0_9) Re-style the v0_9 catalog components using the default theme from `web_core`. [#1166](https://github.com/google/A2UI/pull/1166) - (v0_9) Improve type safety of `props()` in Catalog components. Custom catalog diff --git a/renderers/lit/CHANGELOG.md b/renderers/lit/CHANGELOG.md index 36dd1e837..7599a77ce 100644 --- a/renderers/lit/CHANGELOG.md +++ b/renderers/lit/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. - (v0_9) Re-style the v0_9 catalog components using the default theme from `web_core`. [#1079](https://github.com/google/A2UI/pull/1079) - (v0_9) Add missing features to ChoicePicker and CheckBox. [#1145](https://github.com/google/A2UI/pull/1145) diff --git a/renderers/react/CHANGELOG.md b/renderers/react/CHANGELOG.md index 3762394b6..c5822a1a3 100644 --- a/renderers/react/CHANGELOG.md +++ b/renderers/react/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. - **BREAKING CHANGE**: Renamed `createReactComponent` to `createComponentImplementation`. - **BREAKING CHANGE**: Renamed `createBinderlessComponent` to `createBinderlessComponentImplementation`. - **BREAKING CHANGE**: Removed `minimalCatalog`. diff --git a/renderers/web_core/CHANGELOG.md b/renderers/web_core/CHANGELOG.md index df1034aa2..a7818f6bb 100644 --- a/renderers/web_core/CHANGELOG.md +++ b/renderers/web_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2 + +- Rename Icon `path` property to `svgPath` to fix type collision with `DataBindingType`. + ## 0.9.1 - Add new `FrameworkSignal` concept, which represents a generic signal from a From 5a405f252d67ee257fddc31faedb7e37ce428a59 Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Wed, 6 May 2026 17:15:32 -0700 Subject: [PATCH 07/11] Use Unreleased section in web_core changelog TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- renderers/web_core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderers/web_core/CHANGELOG.md b/renderers/web_core/CHANGELOG.md index a7818f6bb..cc1f5e822 100644 --- a/renderers/web_core/CHANGELOG.md +++ b/renderers/web_core/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.9.2 +## Unreleased - Rename Icon `path` property to `svgPath` to fix type collision with `DataBindingType`. From 15037e37d4879f451b090341271e8364172f3906 Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Fri, 8 May 2026 11:21:09 -0700 Subject: [PATCH 08/11] Mark Icon path rename as breaking change in changelogs TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- renderers/angular/CHANGELOG.md | 2 +- renderers/lit/CHANGELOG.md | 2 +- renderers/react/CHANGELOG.md | 2 +- renderers/web_core/CHANGELOG.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/renderers/angular/CHANGELOG.md b/renderers/angular/CHANGELOG.md index 06a803df6..80d4a3eb3 100644 --- a/renderers/angular/CHANGELOG.md +++ b/renderers/angular/CHANGELOG.md @@ -1,6 +1,6 @@ ## Unreleased -- (v0_9) Rename Icon `path` property to `svgPath` to fix type collision and avoid forced casts. +- **BREAKING CHANGE**: (v0_9) Rename Icon `path` property to `svgPath` to fix type collision and avoid forced casts. - (v0_9) Re-style the v0_9 catalog components using the default theme from `web_core`. [#1166](https://github.com/google/A2UI/pull/1166) - (v0_9) Improve type safety of `props()` in Catalog components. Custom catalog diff --git a/renderers/lit/CHANGELOG.md b/renderers/lit/CHANGELOG.md index 7599a77ce..484b75be3 100644 --- a/renderers/lit/CHANGELOG.md +++ b/renderers/lit/CHANGELOG.md @@ -1,6 +1,6 @@ ## Unreleased -- (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. +- **BREAKING CHANGE**: (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. - (v0_9) Re-style the v0_9 catalog components using the default theme from `web_core`. [#1079](https://github.com/google/A2UI/pull/1079) - (v0_9) Add missing features to ChoicePicker and CheckBox. [#1145](https://github.com/google/A2UI/pull/1145) diff --git a/renderers/react/CHANGELOG.md b/renderers/react/CHANGELOG.md index c5822a1a3..f1fd94587 100644 --- a/renderers/react/CHANGELOG.md +++ b/renderers/react/CHANGELOG.md @@ -1,6 +1,6 @@ ## Unreleased -- (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. +- **BREAKING CHANGE**: (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. - **BREAKING CHANGE**: Renamed `createReactComponent` to `createComponentImplementation`. - **BREAKING CHANGE**: Renamed `createBinderlessComponent` to `createBinderlessComponentImplementation`. - **BREAKING CHANGE**: Removed `minimalCatalog`. diff --git a/renderers/web_core/CHANGELOG.md b/renderers/web_core/CHANGELOG.md index cc1f5e822..33b48c1a1 100644 --- a/renderers/web_core/CHANGELOG.md +++ b/renderers/web_core/CHANGELOG.md @@ -1,6 +1,6 @@ ## Unreleased -- Rename Icon `path` property to `svgPath` to fix type collision with `DataBindingType`. +- **BREAKING CHANGE**: Rename Icon `path` property to `svgPath` to fix type collision with `DataBindingType`. ## 0.9.1 From e7569f6f8812e321c4e9791ceb6588ea9be9297f Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Fri, 8 May 2026 11:52:05 -0700 Subject: [PATCH 09/11] Update specification to use svgPath for Icon TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- specification/v0_9/json/basic_catalog.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/v0_9/json/basic_catalog.json b/specification/v0_9/json/basic_catalog.json index 858a189ad..25542c8dd 100644 --- a/specification/v0_9/json/basic_catalog.json +++ b/specification/v0_9/json/basic_catalog.json @@ -162,11 +162,11 @@ { "type": "object", "properties": { - "path": { + "svgPath": { "type": "string" } }, - "required": ["path"], + "required": ["svgPath"], "additionalProperties": false } ] From 481da88d12464c7691782e68ddcb9a49c0c6d60d Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Fri, 8 May 2026 11:58:38 -0700 Subject: [PATCH 10/11] Fix test case after merge conflict resolution TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- .../angular/src/v0_9/catalog/basic/simple-components.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts b/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts index 38737f645..bf7cba65a 100644 --- a/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts +++ b/renderers/angular/src/v0_9/catalog/basic/simple-components.spec.ts @@ -280,6 +280,7 @@ describe('Simple Components', () => { expect(icon.textContent.trim()).toBe('star_border'); }); + it('should render path icon', () => { setComponentProps(fixture, { ...defaultProps, name: createBoundProperty({ From 5cbf75244fec7ce285ba10dbcade1b1760899fc9 Mon Sep 17 00:00:00 2001 From: Jose Montes Date: Fri, 8 May 2026 12:03:25 -0700 Subject: [PATCH 11/11] Allow DataBinding for Icon name in specification and schema TAG=agy CONV=2bdb6c04-2ba5-495e-8b59-e9981dd0ce1c --- .../src/v0_9/basic_catalog/components/basic_components.ts | 5 +++++ specification/v0_9/json/basic_catalog.json | 3 +++ 2 files changed, 8 insertions(+) diff --git a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts index 69168fae5..b704b00f9 100644 --- a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts +++ b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts @@ -155,6 +155,11 @@ export const IconApi = { svgPath: z.string().describe('Custom SVG path data'), }) .strict(), + z + .object({ + path: z.string(), + }) + .strict(), ]) .describe('The name of the icon to display.'), }) diff --git a/specification/v0_9/json/basic_catalog.json b/specification/v0_9/json/basic_catalog.json index 25542c8dd..bbb7d83a3 100644 --- a/specification/v0_9/json/basic_catalog.json +++ b/specification/v0_9/json/basic_catalog.json @@ -168,6 +168,9 @@ }, "required": ["svgPath"], "additionalProperties": false + }, + { + "$ref": "common_types.json#/$defs/DataBinding" } ] }