Skip to content

Commit 6a8ca98

Browse files
Merge pull request #1958 from NYPL/ISW-5431/icon-styles-bug
ISW-5431: double style bug for custom svgs
2 parents 5072acb + c739e1b commit 6a8ca98

File tree

6 files changed

+36
-21
lines changed

6 files changed

+36
-21
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Currently, this repo is in Prerelease. When it is released, this project will ad
88

99
## Prerelease
1010

11+
### Fixes
12+
13+
- Fixed the double application of styles when a custom svg is passed into the `Icon` component.
14+
1115
## 4.1.4 (February 26, 2026)
1216

1317
### Updates

src/components/Icons/Icon.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { changelogData } from "./iconChangelogData";
1919
componentName="Icon"
2020
summary="Renders commonly used icons in SVG format"
2121
versionAdded="0.0.4"
22-
versionLatest="4.1.1"
22+
versionLatest="Prerelease"
2323
/>
2424

2525
<Canvas of={IconStories.WithControls} />

src/components/Icons/Icon.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ describe("Icon", () => {
5050
const warn = jest.spyOn(console, "warn");
5151
render(<Icon>Not an SVG</Icon>);
5252
expect(warn).toHaveBeenCalledWith(
53-
"NYPL Reservoir Icon: An `svg` element must be passed to the `Icon` " +
53+
"NYPL Reservoir Icon: Only an `svg` element can be passed to the `Icon` " +
5454
"component as its child."
5555
);
5656
});

src/components/Icons/Icon.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ export const Icon: ChakraComponent<
7676
variant = "default",
7777
...rest
7878
} = props;
79+
const hasChildSVG = children && (children as JSX.Element).type === "svg";
7980
const styles = useStyleConfig("ReservoirIcon", {
8081
align,
8182
color,
83+
hasChildSVG,
8284
iconRotation,
8385
size,
8486
variant,
@@ -90,16 +92,21 @@ export const Icon: ChakraComponent<
9092
title,
9193
...rest,
9294
};
93-
let childSVG: any = null;
9495

9596
// Component prop validation
96-
if (name && children) {
97+
if (name && hasChildSVG) {
9798
console.warn(
9899
"NYPL Reservoir Icon: Pass in either a `name` prop or an `svg` element " +
99100
"child. Do not pass both."
100101
);
101102
return null;
102-
} else if (!name && !children) {
103+
} else if (children && !hasChildSVG) {
104+
console.warn(
105+
"NYPL Reservoir Icon: Only an `svg` element can be passed to the `Icon` " +
106+
"component as its child."
107+
);
108+
return null;
109+
} else if (!name && !hasChildSVG) {
103110
console.warn(
104111
"NYPL Reservoir Icon: Pass an icon `name` prop or an SVG child to " +
105112
"ensure an icon appears."
@@ -117,22 +124,13 @@ export const Icon: ChakraComponent<
117124
);
118125
}
119126

120-
// If no `name` prop was passed, we expect a child SVG element to be passed.
127+
// If all prop validation passed and no `name` prop was passed, we expect a
128+
// child SVG element was passed and render it accordingly.
121129
// Apply icon props to the SVG child.
122-
if (
123-
(children as JSX.Element).type === "svg" ||
124-
(children as JSX.Element).props?.type === "svg"
125-
) {
126-
childSVG = React.cloneElement(children as JSX.Element, {
127-
...iconProps,
128-
ref,
129-
});
130-
} else {
131-
console.warn(
132-
"NYPL Reservoir Icon: An `svg` element must be passed to the `Icon` " +
133-
"component as its child."
134-
);
135-
}
130+
const childSVG = React.cloneElement(children as JSX.Element, {
131+
...iconProps,
132+
ref,
133+
});
136134

137135
return (
138136
<Box ref={ref} __css={styles}>

src/components/Icons/iconChangelogData.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
import { ChangelogData } from "../../utils/ComponentChangelogTable";
1010

1111
export const changelogData: ChangelogData[] = [
12+
{
13+
date: "Prerelease",
14+
version: "Prerelease",
15+
type: "Bug Fix",
16+
affects: ["Functionality", "Styles"],
17+
notes: [
18+
"Fixed the double application of styles when a custom svg is passed.",
19+
],
20+
},
1221
{
1322
date: "2025-12-11",
1423
version: "4.1.1",

src/theme/components/icon.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const iconRotation: Record<string, { transform: string }> = {
3838
interface IconBaseStyle extends StyleFunctionProps {
3939
align: keyof typeof align;
4040
color: string;
41+
hasChildSVG: boolean;
4142
iconRotation: keyof typeof iconRotation;
4243
size: keyof typeof iconSizeStyles;
4344
}
@@ -53,7 +54,10 @@ const Icon = defineStyleConfig({
5354
};
5455

5556
return {
56-
...allStyles,
57+
// Apply styles to the root element if a custom svg is not passed
58+
...(!props.hasChildSVG ? allStyles : {}),
59+
60+
// Apply styles to a child svg element
5761
svg: {
5862
...allStyles,
5963
},

0 commit comments

Comments
 (0)