feat: use nuxt-icon

This commit is contained in:
Benjamin Canac
2023-02-16 16:16:37 +01:00
parent 6018f009a8
commit f5d068be9d
19 changed files with 562 additions and 559 deletions

View File

@@ -6,14 +6,14 @@
:aria-label="ariaLabel"
v-bind="buttonProps"
>
<Icon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="leadingIconClass" aria-hidden="true" />
<IconCSS v-if="isLeading && leadingIconName" :name="leadingIconName" :class="leadingIconClass" aria-hidden="true" />
<slot>
<span :class="[truncate ? 'text-left break-all line-clamp-1' : '', compact ? 'hidden sm:block' : '']">
<span :class="[labelCompact && 'hidden sm:block']">{{ label }}</span>
<span v-if="labelCompact" class="sm:hidden">{{ labelCompact }}</span>
</span>
</slot>
<Icon v-if="isTrailing && trailingIconName" :name="trailingIconName" :class="trailingIconClass" aria-hidden="true" />
<IconCSS v-if="isTrailing && trailingIconName" :name="trailingIconName" :class="trailingIconClass" aria-hidden="true" />
</component>
</template>
@@ -22,7 +22,6 @@ import { ref, computed, useSlots } from 'vue'
import type { PropType } from 'vue'
import type { RouteLocationNormalized, RouteLocationRaw } from 'vue-router'
import NuxtLink from '#app/components/nuxt-link'
import Icon from '../elements/Icon.vue'
import { classNames } from '../../utils'
import $ui from '#build/ui'

View File

@@ -27,7 +27,7 @@
@click="item.click"
>
<slot :name="item.slot" :item="item">
<Icon v-if="item.icon" :name="item.icon" :class="[itemIconClass, item.iconClass]" />
<IconCSS v-if="item.icon" :name="item.icon" :class="[itemIconClass, item.iconClass]" />
<Avatar v-if="item.avatar" v-bind="{ size: 'xxs', ...item.avatar }" :class="itemAvatarClass" />
<span class="truncate">{{ item.label }}</span>
@@ -57,7 +57,6 @@ import type { RouteLocationNormalized } from 'vue-router'
import { ref, computed, onMounted } from 'vue'
import { defu } from 'defu'
import NuxtLink from '#app/components/nuxt-link'
import Icon from '../elements/Icon.vue'
import Avatar from '../elements/Avatar.vue'
import { classNames, omit } from '../../utils'
import { usePopper } from '../../composables/usePopper'

View File

@@ -1,56 +0,0 @@
<template>
<span v-if="isFetching" />
<Iconify v-else-if="icon" :icon="icon" />
<Component :is="component" v-else-if="component" />
<span v-else>{{ name }}</span>
</template>
<script setup lang="ts">
import type { IconifyIcon } from '@iconify/vue'
import { Icon as Iconify } from '@iconify/vue/dist/offline'
import { loadIcon } from '@iconify/vue'
import { useNuxtApp, useState, computed, watch, onMounted } from '#imports'
const props = defineProps({
name: {
type: String,
required: true
}
})
const nuxtApp = useNuxtApp()
const state = useState<Record<string, Required<IconifyIcon> | Promise<void> | null>>('u-icons', () => ({}))
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
const isFetching = computed(() => state.value?.[props.name] && ('then' in state.value?.[props.name]!))
const icon = computed<Required<IconifyIcon> | null>(() =>
!state.value?.[props.name] || 'then' in state.value[props.name]!
? null
: state.value[props.name] as Required<IconifyIcon>
)
const component = computed(() => nuxtApp.vueApp.component(props.name))
const loadIconComponent = (name: string) => {
state.value = state.value || {}
if (nuxtApp.vueApp.component(props.name) || state.value[name] || state.value[name] === null) { return state.value[name] }
state.value[name] = loadIcon(name)
.then((res) => { state.value[name] = res })
// We won't try to load this icon again if it fails
.catch(() => { state.value[name] = null })
// return an awaitable promise
return state.value[name]
}
onMounted(() => {
watch(() => props.name, loadIconComponent, { immediate: true })
})
if (process.server) {
await loadIconComponent(props.name)
}
</script>
<script lang="ts">
export default { name: 'UIcon' }
</script>