Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/runtime/components/Icon.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<script lang="ts">
import type { RuntimeOptions } from '@nuxt/icon'
export interface IconProps {
name: string | object
mode?: 'svg' | 'css'
size?: string | number
customize?: (
content: string,
name?: string,
prefix?: string,
provider?: string
) => string
customize?: RuntimeOptions['customize']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
customize?: RuntimeOptions['customize']
customize?: RuntimeOptions['customize'] | boolean | null

The customize prop type doesn't include boolean or null values, but the Vue Icon component expects to handle these values to control whether the global customize function should be used.

View Details

Analysis

IconProps.customize type is too restrictive, prevents boolean/null values

What fails: IconProps interface in src/runtime/components/Icon.vue only accepts RuntimeOptions['customize'] (function type) but the Vue component implementation explicitly supports boolean | null | undefined values

How to reproduce:

import type { IconProps } from './src/runtime/components/Icon.vue'
const props: IconProps = { name: "test", customize: true } // TypeScript error

Result: TypeScript compilation fails with "Type 'boolean' is not assignable to type 'IconifyIconCustomizeCallback'"

Expected: Should accept boolean and null values as the Vue component's resolveCustomizeFn function handles these cases (lines 13-20 in src/runtime/vue/components/Icon.vue)

The @nuxt/icon component already defines customize as IconifyIconCustomizeCallback | boolean | null, so NuxtUI should match this type definition.

}
</script>

Expand Down
41 changes: 31 additions & 10 deletions src/runtime/vue/components/Icon.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
<script lang="ts">
import type { IconProps as NuxtIconProps } from '../../types'

export interface IconProps {
name: NuxtIconProps['name']
}
</script>

<script setup lang="ts">
import type { IconProps } from '../../types'
import type { IconifyRenderMode } from '@iconify/vue'
import { computed } from 'vue'
import { Icon as IconifyIcon } from '@iconify/vue'
import { useAppConfig } from '#imports'
import type { RuntimeOptions } from '@nuxt/icon'

const props = defineProps<IconProps>()

const appConfig = useAppConfig()

function resolveCustomizeFn(
customize: RuntimeOptions['customize'] | boolean | null | undefined,
globalCustomize: RuntimeOptions['customize'] | undefined
): RuntimeOptions['customize'] | undefined {
if (customize === false) return undefined
if (customize === true || customize === null) return globalCustomize
return customize
}

defineProps<IconProps>()
const resolvedMode = computed(() => {
const mode = props.mode || appConfig.icon?.mode
if (mode === 'css') return 'style'
return mode as IconifyRenderMode
})
</script>

<template>
<IconifyIcon v-if="typeof name === 'string'" :icon="name.replace(/^i-/, '')" />
<IconifyIcon
v-if="typeof name === 'string'"
:icon="name.replace(/^i-/, '')"
:mode="resolvedMode"
:width="size || appConfig.icon?.size"
:height="size || appConfig.icon?.size"
:customise="resolveCustomizeFn(props.customize, appConfig.icon?.customize)"
/>
<component :is="name" v-else />
</template>
7 changes: 6 additions & 1 deletion src/unplugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { Options as ComponentsOptions } from 'unplugin-vue-components/types
import { defu } from 'defu'
import tailwind from '@tailwindcss/vite'
import type colors from 'tailwindcss/colors'
import type { RuntimeOptions } from '@nuxt/icon'

import type * as ui from '#build/ui'

Expand Down Expand Up @@ -37,6 +38,10 @@ export interface NuxtUIOptions extends Omit<ModuleOptions, 'fonts' | 'colorMode'
/** Whether to generate declaration files for auto-imported components. */
dts?: boolean
ui?: AppConfigUI
/**
* Default props for the `Icon` component
*/
icon?: Pick<RuntimeOptions, 'customize' | 'size' | 'mode'>
/**
* Enable or disable `@vueuse/core` color-mode integration
* @defaultValue `true`
Expand Down Expand Up @@ -64,7 +69,7 @@ export const NuxtUIPlugin = createUnplugin<NuxtUIOptions | undefined>((_options
options.theme = options.theme || {}
options.theme.colors = resolveColors(options.theme.colors)

const appConfig = defu({ ui: options.ui, colorMode: options.colorMode }, { ui: getDefaultUiConfig(options.theme.colors) })
const appConfig = defu({ ui: options.ui, colorMode: options.colorMode, icon: options.icon }, { ui: getDefaultUiConfig(options.theme.colors) })

return [
NuxtEnvironmentPlugin(options),
Expand Down
Loading