Skip to content

Skeleton

A placeholder to show while content is loading.

Demo

This requires the following theme to be installed:

Component

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

const skeleton = tv(theme)

export interface SkeletonProps {
  as?: any
  class?: any
}
</script>

<script setup lang="ts">
const props = defineProps<SkeletonProps>()

const ui = computed(() => skeleton({ class: props.class }))
</script>

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

const skeleton = tv(theme)

export interface SkeletonProps {
  as?: any
  class?: any
}
</script>

<script setup lang="ts">
const props = defineProps<SkeletonProps>()

const ui = computed(() => skeleton({ class: props.class }))
</script>

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

Theme

skeleton.ts
ts
export default {
  base: '',
}
View Nuxt UI theme
skeleton.ts
ts
export default {
  base: 'animate-pulse rounded-md bg-elevated',
}

Test

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

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

describe('skeleton', () => {
  it.each<[string, RenderOptions<typeof Skeleton>]>([
    // Props
    ['with as', { props: { as: 'span' } }],
    ['with class', { props: { class: 'rounded-full size-12' } }],
  ])('renders %s correctly', (name, options) => {
    render(Skeleton, {
      attrs: {
        'data-testid': 'skeleton',
      },
      ...options,
    })

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

describe('skeleton', () => {
  it.each<[string, RenderOptions<typeof Skeleton>]>([
    // Props
    ['with as', { props: { as: 'span' } }],
    ['with class', { props: { class: 'rounded-full size-12' } }],
  ])('renders %s correctly', (name, options) => {
    render(Skeleton, {
      attrs: {
        'data-testid': 'skeleton',
      },
      ...options,
    })

    expect(screen.getByTestId('skeleton')).toMatchSnapshot()
  })
})

Contributors

barbapapazes

Changelog

c615c - feat: add custom eslint rule to disallow relative imports (#81) on 1/7/2025
aed6f - feat: add skeleton component (#9) on 12/14/2024