From 441efecc943652a27b592e6805ec56474afc14b7 Mon Sep 17 00:00:00 2001 From: at-susie Date: Sun, 31 May 2026 21:37:10 +0200 Subject: [PATCH 01/11] chore: Add null guard and fix SCSS max() function interpolation --- src/icon/internal.tsx | 5 +++++ src/icon/mixins.scss | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 0f81249908..5e8e086a45 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -79,6 +79,11 @@ function computeSizeOverrides({ }): SizeOverrideResult { const result: SizeOverrideResult = {}; + // Guard against stale context consumers that don't provide these maps yet. + if (!sizeOverrides || !strokeWidthOverrides) { + return result; + } + const targetSizePx = sizeOverrides[iconSize]; if (targetSizePx !== undefined) { result.size = targetSizePx; diff --git a/src/icon/mixins.scss b/src/icon/mixins.scss index d4d1b122df..76d00d5e99 100644 --- a/src/icon/mixins.scss +++ b/src/icon/mixins.scss @@ -4,6 +4,7 @@ */ @use 'sass:map'; +@use 'sass:string'; @use '../internal/styles' as styles; @use '../internal/styles/tokens' as awsui; @use '../internal/generated/custom-css-properties' as custom-props; @@ -75,10 +76,10 @@ $_icon-sizes: ( &.size-#{$name} { inline-size: var(#{custom-props.$iconSizeOverride}, #{$size}); - block-size: max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size})); + block-size: string.unquote('max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size}))'); box-sizing: border-box; &-mapped-height { - block-size: max($supportedLineHeight, var(#{custom-props.$iconSizeOverride}, $size)); + block-size: string.unquote('max(#{$supportedLineHeight}, var(#{custom-props.$iconSizeOverride}, #{$size}))'); padding-block: $padding; padding-inline: 0; } @@ -86,7 +87,7 @@ $_icon-sizes: ( > svg, > img { inline-size: var(#{custom-props.$iconSizeOverride}, #{$size}); - block-size: max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size})); + block-size: string.unquote('max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size}))'); vertical-align: top; } From 36c724403c375163a69541b6036b2db50cbbfb50 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 10:39:08 +0200 Subject: [PATCH 02/11] chore: Revert the change in the scss mixin --- src/icon/mixins.scss | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/icon/mixins.scss b/src/icon/mixins.scss index 76d00d5e99..d4d1b122df 100644 --- a/src/icon/mixins.scss +++ b/src/icon/mixins.scss @@ -4,7 +4,6 @@ */ @use 'sass:map'; -@use 'sass:string'; @use '../internal/styles' as styles; @use '../internal/styles/tokens' as awsui; @use '../internal/generated/custom-css-properties' as custom-props; @@ -76,10 +75,10 @@ $_icon-sizes: ( &.size-#{$name} { inline-size: var(#{custom-props.$iconSizeOverride}, #{$size}); - block-size: string.unquote('max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size}))'); + block-size: max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size})); box-sizing: border-box; &-mapped-height { - block-size: string.unquote('max(#{$supportedLineHeight}, var(#{custom-props.$iconSizeOverride}, #{$size}))'); + block-size: max($supportedLineHeight, var(#{custom-props.$iconSizeOverride}, $size)); padding-block: $padding; padding-inline: 0; } @@ -87,7 +86,7 @@ $_icon-sizes: ( > svg, > img { inline-size: var(#{custom-props.$iconSizeOverride}, #{$size}); - block-size: string.unquote('max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size}))'); + block-size: max(#{$size}, var(#{custom-props.$iconSizeOverride}, #{$size})); vertical-align: top; } From 2d965486811f2c2f2ecd764404977189a91b082f Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 10:39:48 +0200 Subject: [PATCH 03/11] chore: Remove comment --- src/icon/internal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 5e8e086a45..0afc92a0c0 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -79,7 +79,6 @@ function computeSizeOverrides({ }): SizeOverrideResult { const result: SizeOverrideResult = {}; - // Guard against stale context consumers that don't provide these maps yet. if (!sizeOverrides || !strokeWidthOverrides) { return result; } From 6e7bd4ab05f4ecbe2129c17030d956310d552f5f Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 10:47:23 +0200 Subject: [PATCH 04/11] chore: Simplify size override computation with nullish coalescing --- src/icon/internal.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 0afc92a0c0..5df0b251e2 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -79,11 +79,10 @@ function computeSizeOverrides({ }): SizeOverrideResult { const result: SizeOverrideResult = {}; - if (!sizeOverrides || !strokeWidthOverrides) { - return result; - } + const sizes = sizeOverrides ?? {}; + const strokes = strokeWidthOverrides ?? {}; - const targetSizePx = sizeOverrides[iconSize]; + const targetSizePx = sizes[iconSize]; if (targetSizePx !== undefined) { result.size = targetSizePx; const basePx = BASE_SIZE_PX[iconSize]; @@ -92,7 +91,7 @@ function computeSizeOverrides({ } } - const rawStroke = strokeWidthOverrides[iconSize]; + const rawStroke = strokes[iconSize]; if (rawStroke !== undefined) { const scaleFactor = SCALE_FACTOR[iconSize] ?? 1; const basePx = BASE_SIZE_PX[iconSize]; From 7ea181dc222354864c63f55b2e07a77eb40f8a15 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 10:49:26 +0200 Subject: [PATCH 05/11] chore: Replace nullish coalescing with explicit null guards in computeSizeOverrides --- src/icon/internal.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 5df0b251e2..3892efd0b7 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -79,10 +79,15 @@ function computeSizeOverrides({ }): SizeOverrideResult { const result: SizeOverrideResult = {}; - const sizes = sizeOverrides ?? {}; - const strokes = strokeWidthOverrides ?? {}; + // Fall back to empty maps if either is undefined (e.g. older context versions). + if (!sizeOverrides) { + sizeOverrides = {}; + } + if (!strokeWidthOverrides) { + strokeWidthOverrides = {}; + } - const targetSizePx = sizes[iconSize]; + const targetSizePx = sizeOverrides[iconSize]; if (targetSizePx !== undefined) { result.size = targetSizePx; const basePx = BASE_SIZE_PX[iconSize]; @@ -91,7 +96,7 @@ function computeSizeOverrides({ } } - const rawStroke = strokes[iconSize]; + const rawStroke = strokeWidthOverrides[iconSize]; if (rawStroke !== undefined) { const scaleFactor = SCALE_FACTOR[iconSize] ?? 1; const basePx = BASE_SIZE_PX[iconSize]; From b7aec3e066cf142612e817b6561b4144789ecbff Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 12:32:25 +0200 Subject: [PATCH 06/11] chore: Add null guard tests for missing context fields --- .../__tests__/icon-provider.test.tsx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/icon-provider/__tests__/icon-provider.test.tsx b/src/icon-provider/__tests__/icon-provider.test.tsx index a48a63d575..41c12d08ea 100644 --- a/src/icon-provider/__tests__/icon-provider.test.tsx +++ b/src/icon-provider/__tests__/icon-provider.test.tsx @@ -417,4 +417,31 @@ describe('Icon Provider', () => { expect(secondIcon).toStrictEqual(expectedSvg); }); }); + + describe('missing context fields (null guard)', () => { + it('renders without crashing when no IconProvider is present', () => { + const { container } = render(); + expect(container.querySelector('[class*="icon"]')).not.toBeNull(); + }); + + it('still applies strokeWidths when sizeOverrides is an empty map', () => { + const { container } = render( + + + + ); + const iconEl = container.querySelector('[class*="icon"]') as HTMLElement; + expect(iconEl.style.getPropertyValue(customCSSPropertiesMap.iconStrokeWidthOverride)).toBe('2px'); + }); + + it('still applies sizes when strokeWidthOverrides is an empty map', () => { + const { container } = render( + + + + ); + const iconEl = container.querySelector('[class*="icon"]') as HTMLElement; + expect(iconEl.style.getPropertyValue(customCSSPropertiesMap.iconSizeOverride)).toBe('12px'); + }); + }); }); From 5803e4e0ca432264089ac02687b31a53d300c415 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 12:36:16 +0200 Subject: [PATCH 07/11] chore: Remove comment --- src/icon/internal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 3892efd0b7..933c7e27eb 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -79,7 +79,6 @@ function computeSizeOverrides({ }): SizeOverrideResult { const result: SizeOverrideResult = {}; - // Fall back to empty maps if either is undefined (e.g. older context versions). if (!sizeOverrides) { sizeOverrides = {}; } From ae29623d05ae7b9a7883d05488706e71a4609d78 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 12:50:10 +0200 Subject: [PATCH 08/11] chore: Use wrapper(container).findIcon() and .getElement() --- src/icon-provider/__tests__/icon-provider.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/icon-provider/__tests__/icon-provider.test.tsx b/src/icon-provider/__tests__/icon-provider.test.tsx index 41c12d08ea..d822fd3170 100644 --- a/src/icon-provider/__tests__/icon-provider.test.tsx +++ b/src/icon-provider/__tests__/icon-provider.test.tsx @@ -421,7 +421,7 @@ describe('Icon Provider', () => { describe('missing context fields (null guard)', () => { it('renders without crashing when no IconProvider is present', () => { const { container } = render(); - expect(container.querySelector('[class*="icon"]')).not.toBeNull(); + expect(wrapper(container).findIcon()).not.toBeNull(); }); it('still applies strokeWidths when sizeOverrides is an empty map', () => { @@ -430,7 +430,7 @@ describe('Icon Provider', () => { ); - const iconEl = container.querySelector('[class*="icon"]') as HTMLElement; + const iconEl = wrapper(container).findIcon()!.getElement(); expect(iconEl.style.getPropertyValue(customCSSPropertiesMap.iconStrokeWidthOverride)).toBe('2px'); }); @@ -440,7 +440,7 @@ describe('Icon Provider', () => { ); - const iconEl = container.querySelector('[class*="icon"]') as HTMLElement; + const iconEl = wrapper(container).findIcon()!.getElement(); expect(iconEl.style.getPropertyValue(customCSSPropertiesMap.iconSizeOverride)).toBe('12px'); }); }); From 03e7658e678914f66d0d45a1fb0d1fe4b4800628 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 12:56:34 +0200 Subject: [PATCH 09/11] chore: Add undefined type to size override parameters --- src/icon/internal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 933c7e27eb..e4fc3a93ae 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -73,8 +73,8 @@ function computeSizeOverrides({ strokeWidthOverrides, iconSize, }: { - sizeOverrides: Partial>; - strokeWidthOverrides: Partial>; + sizeOverrides: Partial> | undefined; + strokeWidthOverrides: Partial> | undefined; iconSize: string; }): SizeOverrideResult { const result: SizeOverrideResult = {}; From 8adf0616c3b40ef3a9aa5d35eb67e6f106d2d042 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 13:36:19 +0200 Subject: [PATCH 10/11] chore: Add tests for missing context fields in IconProvider --- .../__tests__/icon-provider.test.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/icon-provider/__tests__/icon-provider.test.tsx b/src/icon-provider/__tests__/icon-provider.test.tsx index d822fd3170..3debdfb83a 100644 --- a/src/icon-provider/__tests__/icon-provider.test.tsx +++ b/src/icon-provider/__tests__/icon-provider.test.tsx @@ -8,6 +8,7 @@ import Icon, { IconProps } from '../../../lib/components/icon'; import IconProvider, { IconProviderProps } from '../../../lib/components/icon-provider'; import wrapper from '../../../lib/components/test-utils/dom'; import generatedIcons from '../../icon/generated/icons'; +import { InternalIconContext, InternalIconContextValue } from '../../icon-provider/context'; import customCSSPropertiesMap from '../../internal/generated/custom-css-properties'; const CUSTOM_SVG = ( @@ -424,6 +425,26 @@ describe('Icon Provider', () => { expect(wrapper(container).findIcon()).not.toBeNull(); }); + it('renders without crashing when sizeOverrides is undefined in context', () => { + const staleContext = { icons: generatedIcons, strokeWidthOverrides: {} } as InternalIconContextValue; + const { container } = render( + + + + ); + expect(wrapper(container).findIcon()).not.toBeNull(); + }); + + it('renders without crashing when strokeWidthOverrides is undefined in context', () => { + const staleContext = { icons: generatedIcons, sizeOverrides: {} } as InternalIconContextValue; + const { container } = render( + + + + ); + expect(wrapper(container).findIcon()).not.toBeNull(); + }); + it('still applies strokeWidths when sizeOverrides is an empty map', () => { const { container } = render( From bfacc3f034a6df7bf92dc79e65cab4c83df029bb Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 1 Jun 2026 15:13:24 +0200 Subject: [PATCH 11/11] chore: Add test for undefined sizeOverrides and strokeWidthOverrides --- src/icon-provider/__tests__/icon-provider.test.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/icon-provider/__tests__/icon-provider.test.tsx b/src/icon-provider/__tests__/icon-provider.test.tsx index 3debdfb83a..75532e1cf7 100644 --- a/src/icon-provider/__tests__/icon-provider.test.tsx +++ b/src/icon-provider/__tests__/icon-provider.test.tsx @@ -445,6 +445,16 @@ describe('Icon Provider', () => { expect(wrapper(container).findIcon()).not.toBeNull(); }); + it('renders without crashing when both sizeOverrides and strokeWidthOverrides are undefined in context', () => { + const staleContext = { icons: generatedIcons } as InternalIconContextValue; + const { container } = render( + + + + ); + expect(wrapper(container).findIcon()).not.toBeNull(); + }); + it('still applies strokeWidths when sizeOverrides is an empty map', () => { const { container } = render(