Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Custom Image Gallery Preview Component - Portable Text

By James Rea

Learn how to build a custom image gallery preview component that can be added to Portable Text.

Image Url Builder

import { client } from './sanity-client'
import imageUrlBuilder from '@sanity/image-url'

const builder = imageUrlBuilder(client)

export function urlFor(source) {
  return builder.image(source)
}

Image Gallery - Preview Component

import { Flex, Stack } from '@sanity/ui'
import { urlFor } from './image-url-builder'

export default function ImageGalleryPreview(props) {

  const { images, schemaType } = props
  const schemaTitle = schemaType.title

  const modifiedProps = { 
    ...props, 
    title: schemaTitle,
  }

  return (
    <Stack space={[1]}>
      <>
        {props.renderDefault(modifiedProps)}
      </>
      <Flex 
        style={{ 
          gap: '5px',
          overflowX: 'scroll'
        }}
      >
        {images?.map((image) => (
          <img
            key={image._ref}
            src={image.asset ? urlFor(image).url() : ''}
            style={{
              width: '400px',
              height: '200px',
              objectFit: 'cover',
            }}
            alt={image.alt}
          />
        ))}
      </Flex>
    </Stack>
  )
}

Image Gallery - Object Type

import { ImagesIcon } from '@sanity/icons'
import ImageGalleryPreview from './image-gallery-preview';

export default {
  name: 'imageGallery',
  title: 'Image Gallery',
  type: 'object',
  icon: ImagesIcon,
  fields: [
    {
      name: 'images',
      title: 'Images',
      type: 'array',
      of: [{ 
        type: 'image',
        fields: [
          {
            name: 'alt',
            title: 'Alt',
            type: 'string'
          }
        ]
      }],
    },
  ],
  preview: {
    select: { 
      images: 'images',
    },
  },
  components: {
    preview: ImageGalleryPreview,
  }, 
}

Post - Document Type

export default {
  name: 'post',
  title: 'Posts',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
      validation: (Rule) => Rule.required(),
    },
    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
      },
      validation: (Rule) => Rule.required(),
    },
    {
      name: 'content',
      title: 'Content',
      type: 'array',
      of: [
        { type: 'block' }, 
        { type: 'imageGallery' },
      ]
    },
  ]
}

This custom preview component for Portable Text gives content editors a nice visual representation of an image gallery inside their Sanity Studio with the ability to scroll left and right to see all images.

This snippet is part of an open-source project I've recently started which is a collection of custom blocks to be used with Sanity's Portable Text editor.

To view the source code for this project check out the GitHub repository.

Over the next few weeks I'll be adding more blocks to the collection so give the project a star and watch on GitHub to be notified of any updates!

Contributor