diff --git a/renderers/angular/CHANGELOG.md b/renderers/angular/CHANGELOG.md index 8ab7a333a..80d4a3eb3 100644 --- a/renderers/angular/CHANGELOG.md +++ b/renderers/angular/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- **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/angular/src/v0_9/catalog/basic/icon.component.ts b/renderers/angular/src/v0_9/catalog/basic/icon.component.ts index 18b508396..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 && 'path' in name; + return typeof name === 'object' && name !== null && 'svgPath' in name; }); - readonly path = computed(() => { + readonly svgPath = computed(() => { const name = this.iconNameRaw(); - return (name as any)?.path || ''; + if (typeof name === 'object' && name !== null && 'svgPath' in name) { + return name.svgPath; + } + return ''; }); 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 7e0a7b155..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 @@ -284,7 +284,7 @@ describe('Simple Components', () => { setComponentProps(fixture, { ...defaultProps, name: createBoundProperty({ - path: 'M10 10...', + svgPath: 'M10 10...', }) as unknown as ComponentToProps['name'], }); fixture.detectChanges(); diff --git a/renderers/lit/CHANGELOG.md b/renderers/lit/CHANGELOG.md index 2cbef13b9..906c96048 100644 --- a/renderers/lit/CHANGELOG.md +++ b/renderers/lit/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- **BREAKING CHANGE**: (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. - (v0_9) Wire up agent-provided primary color to basic catalog components. - (v0_9) Re-style the v0_9 catalog components using the default theme from `web_core`. [#1079](https://github.com/google/A2UI/pull/1079) 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}`; } } diff --git a/renderers/react/CHANGELOG.md b/renderers/react/CHANGELOG.md index 3e4072dbc..63c4484ba 100644 --- a/renderers/react/CHANGELOG.md +++ b/renderers/react/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- **BREAKING CHANGE**: (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements. - Added license. - (v0_8) Exclude SVG elements and descendants from CSS reset to restore SVG rendering. [#1252](https://github.com/google/A2UI/pull/1252) - **BREAKING CHANGE**: Renamed `createReactComponent` to `createComponentImplementation`. 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..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,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 {path?: string})?.path; - const style: React.CSSProperties = { + const isPath = typeof props.name === 'object' && props.name !== null && 'svgPath' in props.name; + + 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/CHANGELOG.md b/renderers/web_core/CHANGELOG.md index 78946ddd6..1e7e213fd 100644 --- a/renderers/web_core/CHANGELOG.md +++ b/renderers/web_core/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +- **BREAKING CHANGE**: Rename Icon `path` property to `svgPath` to fix type collision with `DataBindingType`. - (v0_9) Add `computeColorVariant` helper function for basic catalog components to generate CSS formulas for color variants (light, dark, hover), allowing reuse across renderers. ## 0.9.1 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..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 @@ -150,6 +150,11 @@ export const IconApi = { name: z .union([ z.enum(ICON_NAMES), + z + .object({ + svgPath: z.string().describe('Custom SVG path data'), + }) + .strict(), z .object({ path: z.string(), diff --git a/specification/v0_9/json/basic_catalog.json b/specification/v0_9/json/basic_catalog.json index 858a189ad..bbb7d83a3 100644 --- a/specification/v0_9/json/basic_catalog.json +++ b/specification/v0_9/json/basic_catalog.json @@ -162,12 +162,15 @@ { "type": "object", "properties": { - "path": { + "svgPath": { "type": "string" } }, - "required": ["path"], + "required": ["svgPath"], "additionalProperties": false + }, + { + "$ref": "common_types.json#/$defs/DataBinding" } ] }