Sanity.io raises $9.3m Series A to redefine content management

Previews / List Views

Sanity will often need to render a representation of a document or object, and we call this a Preview. You can decide which fields should be used, and how, by implementing Preview. By default, Sanity tries its best to guess which fields should be used for preview by introspecting the type's defined fields. For example, if your type has a field of type string named title, it will infer that this should be used as the title when previewing values of this type.

Sanity offers two ways of customizing how documents and objects are previewed:

  1. Specify preview options for the type in schema
  2. Implementing a custom preview component.

Specify preview options

If you want to specify which fields should be used for what, you can control this by adding a preview key to the type as defined in the schema. For example:

export default {
  name: 'movie',
  type: 'document',
  fields: [
    {
      title: 'Title',
      name: 'title',
      type: 'string'
    },
    {
      title: 'Release Date',
      name: 'releaseDate',
      type: 'date'
    }
  ],
preview: {
select: {
title: 'title',
subtitle: 'releaseDate'
}
}
}

Above, the preview.select object will inform the Sanity preview logic that for this document, movie.title should be used as title and movie.releaseDate should be used as subtitle.

This might be sufficient in many cases, but sometimes you want to reformat the selected values. Say releaseDate (e.g. 2016-04-25) is a bit hard on the eyes. All we really want is the year:

export default {
  name: 'movie',
  type: 'document',
  fields: [
    {
      title: 'Title',
      name: 'title',
      type: 'string'
    },
    {
      title: 'Release Date',
      name: 'releaseDate',
      type: 'datetime'
    }
  ],
  preview: {
    select: {
      title: 'title',
date: 'releaseDate'
}, prepare(selection) { const {title, date} = selection return { title: title,
subtitle: date.split('-')[0] // YYYY-MM-DD --> YYYY
} } } }

Above, title and releaseDate are selected. The result of this selection is passed to the prepare function, where you can transform the selection however you like (only keeping the year, in this case).

Protip

In these examples we have put the preview object after the fields array, however you can also place it before it. This might give you a better idea at first glance of how the document is previewed.

Preview using fields from referenced documents

You can follow relations by using dot notation to the related document field you want to display in preview.select.

Here's an example of a preview for a movie that uses the director name as a part of its preview:

export default {
  name: 'movie',
  type: 'document',
  fields: [...],
  preview: {
    select: {
      title: 'title',
director: 'director.name' // if the movie has a director, follow the relation and get the name
}, prepare(selection) {
const {title, director} = selection
return { title: title,
subtitle: `Directed by: ${director ? director : 'unknown'}`
} } } }

Previewing from array values

Fetching entire arrays of values can potentially result in large and complex responses, especially in the case of large arrays. We encourage you to only select a subset of the array values:

export default {
  name: 'book',
  type: 'document',
  fields: [...],
  preview: {
    select: {
      title: 'title',
author0: 'authors.0.name', // <- authors.0 is a reference to author, and the preview component will automatically resolve the reference and return the name
author1: 'authors.1.name',
author2: 'authors.2.name',
author3: 'authors.3.name'
}, prepare: ({title, author0, author1, author2, author3}) => {
const authors = [author0, author1, author2].filter(Boolean)
const subtitle = authors.length > 0 ? `by ${authors.join(', ')}` : ''
const hasMoreAuthors = Boolean(author3)
return { title,
subtitle: hasMoreAuthors ? `${subtitle}` : subtitle
} } } }

Gotcha

Resolving references in arrays works the same as covered above, with dot notation.

The easiest way to show an image in the preview is to assign a field containing an image to the media property. The different views take care of a proper rendering of the image, including any hotspot and crop specifics.

export default {
  name: 'person',
  type: 'document',
  fields: [...],
  preview: {
    select: {
      title: 'name',
media: 'userPortrait' // Use the userPortait image field as thumbnail
} } }

You can also use JSX to render a thumbnail. Here's an example of how to show specific emojis based on the status of our document. This example is partly taken from our Community Studio.

{
  name: 'ticket',
  type: 'document',
  fields: [...],
  preview: {
    select: {
      title: 'title',
      summary: 'summary',
      status: 'status'
    },
    prepare({ title, summary, status }) {
const EMOJIS = {
open: '🎫',
resolved: '✅',
cancelled: '🚫'
}
return {
title: title,
subtitle: summary,
media: <span style={{fontSize: '1.5rem'}}>{status ? EMOJIS[status] : '🎫'}</span>
}
} } }

Gotcha

Remember to add import React from 'react' when you're using React components and JSX for previews.

Custom preview component

If you want complete control of how the document or object preview is rendered, you can also provide a React component that will be invoked when the document or object should be previewed.

The component you'd like to use can be provided in preview config in the document schema or object like this:

export default {
  name: 'movie',
  type: 'document',
  fields: [...],
  preview: {
    select: {
      title: 'title',
      director: 'director.name', // if the movie has a director, follow the relation and get the name
      imageUrl: 'director.image.asset.url'
    },
    prepare(selection) {
      const {title, director, imageUrl} = selection
      return {
        title: title,
        subtitle: `Directed by: ${director ? director : 'unknown'}`,
        
        // `media` takes a function, string or React element
        // Remember to import React from 'react' if you are rendering React components like below
      media: <img src={imageUrl} alt={`${title} movie poster`} />
      }
    },
component: MyPreviewComponent
} }

This will pass the value to the preview component, using the selection from select. For a more complex example, see the VideoEmbed preview.

Preview in the Studio

Depending on how your schema is set up, here is an example of how Preview could look in your Studio. This uses title, subtitle, and media.

Was this article helpful?