Skip to content

Commit

Permalink
feat(nuxt-img): add placeholderClass prop (#1111)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanchase committed Apr 22, 2024
1 parent 36ba10b commit 55c2717
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
21 changes: 21 additions & 0 deletions docs/content/2.usage/1.nuxt-img.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,27 @@ const img = useImage()
</template>
```

### `placeholder-class`

When using a placeholder, you can use `placeholder-class` to apply a class to the original underlying `<img>` element (while the placeholder is being rendered).

```html
<!-- Apply a static class to the original image -->
<nuxt-img src="/nuxt.png" placeholder placeholder-class="custom" />

<!-- Apply a dynamic class to the original image -->
<nuxt-img src="/nuxt.png" placeholder :placeholder-class="custom" />
```

::callout
If you need to apply some CSS to only the _loaded_ image you can do so with something like:
```css
img:not(.my-placeholder-class) {
/* styles here */
}
```
::

### `provider`

Use other provider instead of default [provider option](/get-started/configuration#provider) specified in `nuxt.config`
Expand Down
5 changes: 3 additions & 2 deletions src/runtime/components/nuxt-img.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useHead, useNuxtApp } from '#imports'
export const imgProps = {
...baseImageProps,
placeholder: { type: [Boolean, String, Number, Array], default: undefined },
placeholderClass: { type: String, default: undefined },
}

export default defineComponent({
Expand All @@ -20,6 +21,7 @@ export default defineComponent({
const _base = useBaseImage(props)

const placeholderLoaded = ref(false)
const imgEl = ref<HTMLImageElement>()

type AttrsT = typeof _base.attrs.value & {
'sizes'?: string
Expand Down Expand Up @@ -103,8 +105,6 @@ export default defineComponent({
prerenderStaticImages(src.value, sizes.value.srcset)
}

const imgEl = ref<HTMLImageElement>()

const nuxtApp = useNuxtApp()
const initialLoad = nuxtApp.isHydrating
onMounted(() => {
Expand Down Expand Up @@ -151,6 +151,7 @@ export default defineComponent({
...import.meta.server ? { onerror: 'this.setAttribute(\'data-error\', 1)' } : {},
...attrs.value,
...ctx.attrs,
class: props.placeholder && !placeholderLoaded.value ? [props.placeholderClass] : undefined,
})
},
})
32 changes: 32 additions & 0 deletions test/unit/image.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,38 @@ describe('Renders placeholder image', () => {
expect(sizes).toMatchInlineSnapshot('"(max-width: 500px) 200px, (max-width: 900px) 500px, 900px"')
expect(wrapper.emitted().load[0]).toStrictEqual([loadEvent])
})

it('placeholder class can be set', async () => {
const { resolve: resolveImage } = getImageLoad(() => {
wrapper = mount(NuxtImg, {
propsData: {
src,
placeholder: true,
placeholderClass: 'placeholder',
},
attrs: {
class: [{ test: true }, 'other'],
},
})
})
expect([...wrapper.element.classList]).toMatchInlineSnapshot(`
[
"placeholder",
"test",
"other",
]
`)
expect(wrapper.element.getAttribute('src')).toMatchInlineSnapshot('"/_ipx/q_50&blur_3&s_10x10/image.png"')
resolveImage()
await nextTick()
expect([...wrapper.element.classList]).toMatchInlineSnapshot(`
[
"test",
"other",
]
`)
expect(wrapper.element.getAttribute('src')).toMatchInlineSnapshot(`"/_ipx/_/image.png"`)
})
})

describe('Renders image, applies module config', () => {
Expand Down

0 comments on commit 55c2717

Please sign in to comment.