0.8.1 • Published 5 months ago

@react-visual/react v0.8.1

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

@react-visual/react react-visual

Renders images and videos into a container. Features:

  • Supports a next.js style image loader for making srcsets
  • Creates <source> tags for different MIME types and media queries
  • Easily render assets using aspect ratios
  • Videos are lazyloaded (unless priority flag is set)

Install

yarn add @react-visual/react

Usage

Play a video with a poster image.

import Visual from '@react-visual/react'

export default function VideoExample() {
  return (
    <Visual
      image='https://placehold.co/300x150'
      video='https://placehold.co/300x150.mp4'
      aspect={300/150}
      sizes='100vw'
      alt='Example using placeholder images' />
  )
}

Generate multiple landscape and portrait sources using an image CDN to create a srcset.

import Visual from '@react-visual/react'

export default function ResponsiveExample() {
  return (
    <Visual
      image='https://placehold.co/200x200'
      sourceTypes={['image/webp']}
      sourceMedia={['(orientation:landscape)', '(orientation:portrait)']}
      imageLoader={({ src, type, media, width }) => {
        const height = media?.includes('landscape') ? width * 0.5 : width
        const ext = type?.includes('webp') ? '.webp' : ''
        return `https://placehold.co/${width}x${height}${ext}`
      }}
      width='100%'
      alt='Example of responsive images'/>
  )
}

The above would produce:

<div style="position: relative; width: 100%; max-width: 100%;">
  <picture>
    <source
      type='image/webp'
      media='(orientation:landscape)'
      srcset='https://placehold.co/640x320.webp 640w, https://placehold.co/750x375.webp 750w, https://placehold.co/828x414.webp 828w, https://placehold.co/1080x540.webp 1080w, https://placehold.co/1200x600.webp 1200w, https://placehold.co/1920x960.webp 1920w, https://placehold.co/2048x1024.webp 2048w, https://placehold.co/3840x1920.webp 3840w'>
    <source
      type='image/webp'
      media='(orientation:portrait)'
      srcset='https://placehold.co/640x640.webp 640w, https://placehold.co/750x750.webp 750w, https://placehold.co/828x828.webp 828w, https://placehold.co/1080x1080.webp 1080w, https://placehold.co/1200x1200.webp 1200w, https://placehold.co/1920x1920.webp 1920w, https://placehold.co/2048x2048.webp 2048w, https://placehold.co/3840x3840.webp 3840w'>
    <source
      type='image/webp'
      media='(orientation:landscape)'
      srcset='https://placehold.co/640x320 640w, https://placehold.co/750x375 750w, https://placehold.co/828x414 828w, https://placehold.co/1080x540 1080w, https://placehold.co/1200x600 1200w, https://placehold.co/1920x960 1920w, https://placehold.co/2048x1024 2048w, https://placehold.co/3840x1920 3840w'>
    <source
      media='(orientation:portrait)'
      srcset='https://placehold.co/640x640 640w, https://placehold.co/750x750 750w, https://placehold.co/828x828 828w, https://placehold.co/1080x1080 1080w, https://placehold.co/1200x1200 1200w, https://placehold.co/1920x1920 1920w, https://placehold.co/2048x2048 2048w, https://placehold.co/3840x3840 3840w'>
    <img
      src='https://placehold.co/200x200'
      loading='lazy'
      alt='Example of responsive images'
      style='object-fit: cover; width: 100%;'>
  </picture>
</div>

Accept objects from a CMS to produce responsive assets at different aspect ratios.

import Visual from '@react-visual/react'

export default function ResponsiveExample() {
  return (
    <Visual
      image={{
        landscape: {
          url: 'https://placehold.co/500x250',
          aspect: 2,
        },
        portrait: {
          url: 'https://placehold.co/500x500',
          aspect: 1,
        }
      }}
      sourceMedia={['(orientation: landscape)', '(orientation: portrait)']}
      imageLoader={({ src, type, media, width }) => {

        // Choose the right source
        const asset = media?.includes('landscape') ?
          src.landscape : src.portrait

        // Make the dimensions
        const dimensions = `${width}x${width / asset.aspect}`

        // Choose the right format
        const ext = type?.includes('webp') ? '.webp' : '.jpg'

        // Make the url
        return `https://placehold.co/${dimensions}${ext}`

      }}
      aspect={({ image, media }) => {
        return media?.includes('landscape') ?
          image.landscape.aspect :
          image.portrait.aspect
      }}
      alt='Example of responsive images'/>
  )
}

This produces:

<div
  class="rv-orientation-landscape-2 rv-orientation-portrait-1"
  style="position: relative; max-width: 100%;">
  <picture>
    <source
      media="(orientation: landscape)"
      srcset="https://placehold.co/640x320.jpg 640w, https://placehold.co/750x375.jpg 750w, https://placehold.co/828x414.jpg 828w, https://placehold.co/1080x540.jpg 1080w, https://placehold.co/1200x600.jpg 1200w, https://placehold.co/1920x960.jpg 1920w, https://placehold.co/2048x1024.jpg 2048w, https://placehold.co/3840x1920.jpg 3840w">
    <source
      media="(orientation: portrait)"
      srcset="https://placehold.co/640x640.jpg 640w, https://placehold.co/750x750.jpg 750w, https://placehold.co/828x828.jpg 828w, https://placehold.co/1080x1080.jpg 1080w, https://placehold.co/1200x1200.jpg 1200w, https://placehold.co/1920x1920.jpg 1920w, https://placehold.co/2048x2048.jpg 2048w, https://placehold.co/3840x3840.jpg 3840w">
    <img
      src="https://placehold.co/1920x1920.jpg"
      loading="lazy"
      alt="Example of responsive images"
      style="object-fit: cover; position: absolute; inset: 0px;">
  </picture>
  <style>
    @media (orientation: landscape) {
      .rv-orientation-landscape-2 {
        aspect-ratio: 2;
      }
    }
    @media (orientation: portrait) {
      .rv-orientation-portrait-1 {
        aspect-ratio: 1;
      }
    }
  </style>
</div>

For more examples, read the Cypress component tests.

Props

Sources

PropTypeDescription
imagestring, objectURL to an image asset.
videostring, objectURL to a video asset asset.

Layout

PropTypeDescription
expandbooleanMake the Visual fill it's container via CSS using absolute positioning.
aspectnumber, functionForce the Visual to a specific aspect ratio.
widthnumber, stringA CSS dimension value or a px number.
heightnumber, stringA CSS dimension value or a px number.
fitstringAn object-fit value that is applied to the assets. Defaults to cover.
positionstringAn object-position value.

Loading

PropTypeDescription
prioritybooleanDisables <img loading="lazy>" and prevents videos from lazy loading based on IntersectionObserver.
sizesstringSets the <img sizes> attribute.
sourceTypesstring[]Specify image MIME types that will be passed to the imageLoader and used to create additional <source> tags. Use this to create webp or avif sources with a CDN like Contentful.
sourceMediastring[]Specify media queries that will be passed to the imageLoader and used to create additional <source> tags.
imageLoaderFunctionUses syntax that is similar to next/image's loader prop. A srcset is built with a hardcoded list of widths.
videoLoaderFunctionLike imageLoader but is only passed the src and media properties.

Video

PropTypeDescription
pausedbooleanDisables autoplay of videos. This prop is reactive, unlike the paused property of the html <video> tag. You can set it to true to pause a playing video or set it to false to play a paused video.

Accessibility

PropTypeDescription
altstringSets the alt attribute or aria-label value, depending on asset type.

Theming

PropTypeDescription
classNamestringAdd a custom CSS class.
styleCSSPropertiesAdd additional styles.
0.8.1

5 months ago

0.8.0

5 months ago

0.7.1

5 months ago

0.7.0

5 months ago

0.6.0

6 months ago

0.5.1

8 months ago

0.5.0

8 months ago

0.4.1

8 months ago

0.4.0

8 months ago

0.3.2

9 months ago

0.3.1

9 months ago

0.3.0

9 months ago