Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Integrations] NuxtImg component and nuxt/image #137

Open
boumanb opened this issue May 16, 2023 · 7 comments
Open

[Integrations] NuxtImg component and nuxt/image #137

boumanb opened this issue May 16, 2023 · 7 comments

Comments

@boumanb
Copy link

boumanb commented May 16, 2023

I've spend quite some time to get nuxt/image to work using their documentation on https://v1.image.nuxtjs.org/get-started (for responsive images and webp) only to find out that the NuxtImg component provided by nuxt/image is not working but the NuxtPicture component provided by nuxt/image is.

Could it be so that the NuxtImg provided by nuxt/image gets overruled by the NuxtImg provided in @nuxt-themes/elements?

Copy link
Contributor

Tahul commented May 17, 2023

Hello @boumanb ; could you share us your implementation in your project so maybe we can send a PR to Elements implementing it?

@Tahul Tahul changed the title [question] NuxtImg component and nuxt/image [Integrations] NuxtImg component and nuxt/image May 17, 2023
@boumanb
Copy link
Author

boumanb commented May 17, 2023

Thanks for responding. I haven't made a different implementation. I simply replaced all the references to the NuxtImg element by referencing the NuxtPicture component from https://github.com/nuxt/image.

For example, I've overridden the AppHeader.vue from alpine by copying it over to the project's components folder and changing it to:

<script lang="ts" setup>
const alpine = useAppConfig().alpine

const show = ref(false)
</script>

<template>
  <header :class="alpine.header.position || 'left'">
    <div class="menu">
      <button @click="(show = !show)" aria-label="Navigation Menu">
        <svg width="24" height="24" viewBox="0 0 68 68" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
          <path d="M8 34C8 32.1362 8 31.2044 8.30448 30.4693C8.71046 29.4892 9.48915 28.7105 10.4693 28.3045C11.2044 28 12.1362 28 14 28C15.8638 28 16.7956 28 17.5307 28.3045C18.5108 28.7105 19.2895 29.4892 19.6955 30.4693C20 31.2044 20 32.1362 20 34C20 35.8638 20 36.7956 19.6955 37.5307C19.2895 38.5108 18.5108 39.2895 17.5307 39.6955C16.7956 40 15.8638 40 14 40C12.1362 40 11.2044 40 10.4693 39.6955C9.48915 39.2895 8.71046 38.5108 8.30448 37.5307C8 36.7956 8 35.8638 8 34Z" />
          <path d="M28 34C28 32.1362 28 31.2044 28.3045 30.4693C28.7105 29.4892 29.4892 28.7105 30.4693 28.3045C31.2044 28 32.1362 28 34 28C35.8638 28 36.7956 28 37.5307 28.3045C38.5108 28.7105 39.2895 29.4892 39.6955 30.4693C40 31.2044 40 32.1362 40 34C40 35.8638 40 36.7956 39.6955 37.5307C39.2895 38.5108 38.5108 39.2895 37.5307 39.6955C36.7956 40 35.8638 40 34 40C32.1362 40 31.2044 40 30.4693 39.6955C29.4892 39.2895 28.7105 38.5108 28.3045 37.5307C28 36.7956 28 35.8638 28 34Z" />
          <path d="M48 34C48 32.1362 48 31.2044 48.3045 30.4693C48.7105 29.4892 49.4892 28.7105 50.4693 28.3045C51.2044 28 52.1362 28 54 28C55.8638 28 56.7956 28 57.5307 28.3045C58.5108 28.7105 59.2895 29.4892 59.6955 30.4693C60 31.2044 60 32.1362 60 34C60 35.8638 60 36.7956 59.6955 37.5307C59.2895 38.5108 58.5108 39.2895 57.5307 39.6955C56.7956 40 55.8638 40 54 40C52.1362 40 51.2044 40 50.4693 39.6955C49.4892 39.2895 48.7105 38.5108 48.3045 37.5307C48 36.7956 48 35.8638 48 34Z" />
        </svg>
      </button>
    </div>

    <div class="overlay" :class="[show && 'show']">
      <MainNav @link-click="show = !show" />
    </div>

    <div class="logo">
      <NuxtLink v-if="alpine.header.logo" to="/">
        <!-- TODO: width/height doesn't make much sense here, but Lighthouse requires it. 
        Used current Alpine logo ratio, will break on enduser logo -->
        <NuxtPicture class="dark-img" :src="alpine.header.logo.pathDark" :alt="alpine.header.logo.alt" width="89" height="31" />
        <NuxtPicture class="light-img" :src="alpine.header.logo.path" :alt="alpine.header.logo.alt" width="89" height="31" />
      </NuxtLink>
      <NuxtLink v-else to="/" class="fallback">
        {{ alpine.title }}
      </NuxtLink>
    </div>

    <div class="main-nav">
      <MainNav />
    </div>
  </header>
</template>

<style scoped lang="ts">
css({
  header: {
    '--header-padding': '{space.16}',
    '--logo-height': '{space.8}',
    position: 'relative',
    display: 'grid',
    gridTemplateColumns: 'repeat(12, minmax(0, 1fr))',
    alignItems: 'center',
    gap: '{space.4}',
    py: 'var(--header-padding)',
    '.menu': {
      position: 'absolute',
      display: 'flex',
      ':hover': {
        color: '{color.primary.500}',
      },
      '.left &&': {
        right: 0
      },
      '@sm': {
        display: 'none'
      }
    },
    '.overlay': {
      position: 'absolute',
      top: 'calc(var(--header-padding) + var(--logo-height) + {space.2})',
      backgroundColor: '{alpine.backdrop.backgroundColor}',
      border: '1px solid {color.gray.200}',
      borderRadius: '{radii.md}',
      padding: '{space.6}',
      paddingRight: '{space.24}',
      fontSize: '{text.lg.fontSize}',
      lineHeight: '{text.lg.lineHeight}',
      fontWeight: '{fontWeight.medium}',
      transition: 'all 250ms',
      perspective: '2000px',
      transformOrigin: 'top',
      backdropFilter: 'blur(20px)',
      willChange: 'opacity, transform',
      '&:not(.show)': {
        opacity: 0,
        transform: 'translateY(-10px) rotateY(-8deg) rotateX(-20deg)',
        '.left &&': {
          transform: 'translateY(-10px) rotateY(8deg) rotateX(-20deg)',
        },
        pointerEvents: 'none'
      },
      '.left &&': {
        right: 0,
        padding: '{space.6}',
        paddingLeft: '{space.16}',
        textAlign: 'right'
      },
      '@sm': {
        display: 'none'
      },
      '@dark': {
        borderColor: '{color.gray.800}',
      }
    },
    '.logo': {
      display: 'flex',
      gridColumn: 'span 12 / span 12',
      height: 'var(--logo-height)',
      a: {
        display: 'flex',
      },
      '.center &&': {
        gridColumn: 'span 12 / span 12',
        justifyContent: 'center',
      },
      '.right &&': {
        justifyContent: 'flex-end',
      },
      '@sm': {
        gridColumn: 'span 4 / span 4',
        gridColumnStart: 'auto',
        '.right &&': {
          order: 2,
        },
      },
      '.fallback': {
        fontSize: '{text.2xl.fontSize}',
        lineHeight: '{text.2xl.lineHeight}',
        fontWeight: '{fontWeight.semibold}'
      }
    },
    '.main-nav': {
      display: 'none',
      '@sm': {
        display: 'flex',
        gridColumn: 'span 8 / span 8',
        fontSize: '{text.xl.fontSize}',
        lineHeight: '{text.xl.lineHeight}',
        fontWeight: '{fontWeight.medium}',
        '.center &&': {
          gridColumn: 'span 12 / span 12',
          justifyContent: 'center',
        },
        '.right &&': {
          justifyContent: 'flex-start',
        },
        '.left &&': {
          justifyContent: 'flex-end',
        },
      }
    },
  }
})
</style>

The important lines:

<NuxtPicture class="dark-img" :src="alpine.header.logo.pathDark" :alt="alpine.header.logo.alt" width="89" height="31" />
<NuxtPicture class="light-img" :src="alpine.header.logo.path" :alt="alpine.header.logo.alt" width="89" height="31" />

I've done this at various places so that all images are converted to webp by default and are delivered in various responsive formats. By doing so I'm not longer leveraging the NuxtImg provided by @nuxt-themes/elements which is probably bad.

I'd recommend to let the NuxtImg provided in @nuxt-themes/elements leverage the NuxtPicture component from nuxt/image so that all themes use modern standards for serving images by default. Good for user experience and SEO. One should not bother with generating webp images (manually) and add them to source (https://github.com/nuxt-themes/alpine/tree/main/.starters/default/public).

Copy link
Contributor

Tahul commented May 22, 2023

@Atinux ; really nice news as @boumanb proved @nuxt/img to be ready for our themes!

WDYT of updating all <img> to use <NuxtPicture /> across all themes?

Copy link
Contributor

Atinux commented May 22, 2023

Happy to see a PR using Nuxt Image 💯

BillyBouman-2B-IT added a commit to BillyBouman-2B-IT/alpine that referenced this issue May 22, 2023
…age formats and responsive sizes by default, improves performance (mobile).
@BillyBouman-2B-IT
Copy link

@Tahul @Atinux I've just proposed a PR using Nuxt Image for the Alpine theme. There is however a critical issue that needs to be resolved. Styling the <NuxtPicture /> only works upon removing scoped from <style scoped lang="ts">. Could it have something to do with https://github.com/Tahul/pinceau?

BillyBouman-2B-IT added a commit to BillyBouman-2B-IT/alpine that referenced this issue May 22, 2023
@BillyBouman-2B-IT
Copy link

Also, everything is working fine locally (and on Netlify too) using IPX but images seem broken on the PR deployment https://alpine-d503wurue-nuxtlabs.vercel.app on Vercel. Maybe it has something to do with the Vercel (provider).

Reference:
https://vercel.com/docs/concepts/image-optimization/examples#using-nuxt/image-on-vercel
https://v1.image.nuxtjs.org/providers/introduction#environment-detection
unjs/nitro#1073

BillyBouman-2B-IT added a commit to BillyBouman-2B-IT/alpine that referenced this issue Jun 24, 2023
…age formats and responsive sizes by default, improves performance (mobile).
BillyBouman-2B-IT added a commit to BillyBouman-2B-IT/alpine that referenced this issue Jun 24, 2023
@BillyBouman-2B-IT
Copy link

Please see #146 (comment) for latest status.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants