Skip to content

Icon

A component to display any icon from Iconify.

Demo

This requires the following theme to be installed:

Component

Icon.vue
vue
<script lang="ts">
import theme from '@/ui/theme/icon'
import { Primitive } from 'reka-ui'
import { tv } from 'tailwind-variants'
import { computed } from 'vue'

const icon = tv(theme)

export interface IconProps {
  as?: any
  name?: string
  class?: any
}

export interface IconEmits {}
export interface IconSlots {}
</script>

<script lang="ts" setup>
const props = withDefaults(defineProps<IconProps>(), {
  as: 'span',
})
defineEmits<IconEmits>()
defineSlots<IconSlots>()

const ui = computed(() => icon({
  class: [props.name, props.class],
}))
</script>

<template>
  <Primitive :as="as" :class="ui" />
</template>
Icon.vue
vue
<script lang="ts">
import theme from '@/UI/Theme/icon'
import { Primitive } from 'reka-ui'
import { tv } from 'tailwind-variants'
import { computed } from 'vue'

const icon = tv(theme)

export interface IconProps {
  as?: any
  name?: string
  class?: any
}

export interface IconEmits {}
export interface IconSlots {}
</script>

<script lang="ts" setup>
const props = withDefaults(defineProps<IconProps>(), {
  as: 'span',
})
defineEmits<IconEmits>()
defineSlots<IconSlots>()

const ui = computed(() => icon({
  class: [props.name, props.class],
}))
</script>

<template>
  <Primitive :as="as" :class="ui" />
</template>

Theme

icon.ts
ts
export default {
  base: '',
}
View Nuxt UI theme
icon.ts
ts
export default {
  base: 'inline-block',
}

Test

To test this component, you can use the following test file:

Icon.test.ts
ts
import type { RenderOptions } from '@testing-library/vue'
import Icon from '@/ui/components/Icon.vue'
import { render, screen } from '@testing-library/vue'
import { describe, expect, it } from 'vitest'

describe('icon', () => {
  const props = { name: 'i-lucide-alarm-clock' }

  it.each<[string, RenderOptions<typeof Icon>]>([
    // Props
    ['with icon', { props }],
    ['with as', { props: { ...props, as: 'div' } }],
    ['with class', { props: { ...props, class: 'custom-class' } }],
  ])('renders %s correctly', (name, options) => {
    render(Icon, {
      attrs: {
        'data-testid': 'icon',
      },
      ...options,
    })

    expect(screen.getByTestId('icon')).matchSnapshot()
  })
})
Icon.test.ts
ts
import type { RenderOptions } from '@testing-library/vue'
import Icon from '@/UI/Components/Icon.vue'
import { render, screen } from '@testing-library/vue'
import { describe, expect, it } from 'vitest'

describe('icon', () => {
  const props = { name: 'i-lucide-alarm-clock' }

  it.each<[string, RenderOptions<typeof Icon>]>([
    // Props
    ['with icon', { props }],
    ['with as', { props: { ...props, as: 'div' } }],
    ['with class', { props: { ...props, class: 'custom-class' } }],
  ])('renders %s correctly', (name, options) => {
    render(Icon, {
      attrs: {
        'data-testid': 'icon',
      },
      ...options,
    })

    expect(screen.getByTestId('icon')).matchSnapshot()
  })
})

Contributors

barbapapazes

Changelog