Skip to content

Conversation

rijenkii
Copy link

@rijenkii rijenkii commented Aug 15, 2025

πŸ”— Linked issue

Resolves #4728

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

Previously, all icon props in components only accepted string values representing icon names (e.g. "i-lucide-rocket"). Icons defined this way would be loaded from a CDN, which results in absence of icons altogether when CDN is unavailable for one reason or another.

Current solution for this is to statically bundle all of the used icons into the application, which is unacceptable when bundle size is of importance and when knowing all of the used icons in the project is impossible.

This PR allows user to pass a Vue component instead of an icon name in every component that has an icon prop. UIcon by itself will just render the passed component unchanged, so scaling has to be done either by applying styles to UIcon or to the Vue component.

I was unable to allow setting component icons inside the global config, because it is passed through JSON.stringify to expose config as a virtual module, and components obviously do not survive that process.

I can backport this to v3 if you want.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Copy link

pkg-pr-new bot commented Aug 15, 2025

npm i https://pkg.pr.new/@nuxt/ui@4766

commit: 7d3dc3d

@rijenkii
Copy link
Author

Right now I am unable to access Vercel so I do not know what the deployment error is.

@rijenkii
Copy link
Author

rijenkii commented Aug 16, 2025

Maybe it's also worth adding the ability to pass icons in template slots, but that will be a bigger change. Maybe that's a better way then passing a component in props though:

<script setup lang="ts">
import IconLightbulb from '~icons/lucide/lightbulb'
</script>

<template>
  <UButton :trailing-icon="IconLigthbulb">Button</UButton>
  <!-- VS -->
  <UButton>
    <template #trailing-icon><IconLightbulb /></template>
    Button
  </UButton>
</template>

@benjamincanac benjamincanac changed the title feat(icon): allow passing a component instead of a name feat(Icon): allow passing a component instead of a name Aug 16, 2025
@rijenkii
Copy link
Author

rijenkii commented Aug 21, 2025

The fact that you cannot pass an icon component into appConfig bugs me, but I am not sure if I can do anything about it without it looking like a horrible hack.

Ideas I came up with, all have their downsides:

  1. allow setting icons to objects like { html: `<svg xmlns="...">...</svg>` }
    • icon will be inserted into a component with v-html
    • cannot pass a component, only static html
    • would make sense to also accept that in the UIcon component
  2. allow setting icons to functional components like () => h("svg", { xmlns: "..." }, [...])
    • requires converting vdom tree back into component definition
    • not sure if useful at all as you cannot import components at all inside vite.config.ts
  3. allow changing/defining appConfig from inside the app, e.g. in main.ts
    • probably the hardest, but most convenient, as now any component from the app can be set as a default icon

EDIT: I forgot that IconifyIcon exists, possible alternative to option 1.


Also I feel like UIcon.name is no longer an appropriate parameter name, UIcon.icon would be better suited, but that would require marking UIcon.name as deprecated and switching over to UIcon.icon in the entire project.

@benjamincanac benjamincanac added the v4 #4488 label Aug 25, 2025
@benjamincanac benjamincanac force-pushed the v4 branch 2 times, most recently from 7f055cf to 3e38fac Compare August 25, 2025 15:58
@rijenkii
Copy link
Author

rijenkii commented Aug 27, 2025

So:

  • Regarding the deprecation of UIcon.name and gradual switching over to UIcon.icon -- I was unable to type that: component with { name: ...; icon?: ... } | { name?: ...; icon: ... } as props allows passing no props at all.

  • Regarding svg icons in appConfig -- this is a large change; for now I have defined a local iconify collection, replaced all icons in appConfig with icons from that collection, and am populating it in main.ts. Not ideal, but works.

  • I have been using package from this PR for at least a week now, and have found no problems.

@benjamincanac
Copy link
Member

I don't think it is necessary to rename name prop to icon, this would introduce an enormous breaking change to users without any benefit, too big in my opinion even for v4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v4 #4488
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants