fix(vue): support kebab-case icon-node prop on Icon component (#4512)

* fix(vue): support kebab-case icon-node prop on Icon component

The Icon component destructured `iconNode` camelCase-only while
`stroke-width`/`absolute-stroke-width` accept both cases, so the
idiomatic Vue usage `<Icon :icon-node="..." />` left iconNode undefined
and crashed with 'Cannot read properties of undefined (reading map)'
(#3485). Accept the kebab-case alias and guard the render path.

Closes #3485

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore(vue): apply prettier formatting to Icon.ts

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
This commit is contained in:
Sagar Gupta
2026-07-09 14:11:20 +02:00
committed by GitHub
co-authored by Copilot Autofix powered by AI Eric Fennis
parent 63369b1ac0
commit 4c663b9a32
2 changed files with 21 additions and 5 deletions
+9 -5
View File
@@ -4,15 +4,16 @@ import defaultAttributes from './defaultAttributes';
import { IconNode, LucideProps } from './types';
import { useLucideProps } from './context';
interface IconProps {
iconNode: IconNode;
name: string;
}
type IconProps = { name: string } & (
| { iconNode: IconNode; 'icon-node'?: never }
| { 'icon-node': IconNode; iconNode?: never }
);
const Icon: FunctionalComponent<LucideProps & IconProps> = (
{
name,
iconNode,
'icon-node': iconNodeKebabCase,
absoluteStrokeWidth,
'absolute-stroke-width': absoluteStrokeWidthKebabCase,
strokeWidth,
@@ -71,7 +72,10 @@ const Icon: FunctionalComponent<LucideProps & IconProps> = (
: ['lucide-icon']),
),
},
[...iconNode.map((child) => h(...child)), ...(slots.default ? [slots.default()] : [])],
[
...(iconNode ?? iconNodeKebabCase ?? []).map((child) => h(...child)),
...(slots.default ? [slots.default()] : []),
],
);
};
+12
View File
@@ -19,6 +19,18 @@ describe('Using Icon Component', () => {
expect(container.firstChild).toBeDefined();
});
it('should render when iconNode is passed as the kebab-case icon-node prop', async () => {
const { container } = render(Icon, {
props: {
'icon-node': airVent,
name: 'AirVent',
},
});
expect(container.firstChild).toBeDefined();
expect(container.querySelector('svg')).toBeTruthy();
});
it('should render icon and match snapshot', async () => {
const { container } = render(Icon, {
props: {