Dynamic document icons based on document values in Structure Builder

3 replies
Last updated: Apr 23, 2020
Hello! I have a question regarding document icons in the structure builder. Is it possible to provide a dynamic icon component that can render differently based on document values?
AI Update

Yes, absolutely! You can provide dynamic icons based on document values using the preview configuration in your schema. The media field in the prepare function can return different icon components based on the document's data.

Basic Dynamic Icon Example

In your schema's preview configuration, use the prepare function to conditionally return different icons based on document values:

import { CheckmarkIcon, CloseIcon, ClockIcon } from "@sanity/icons";

export const myDocumentType = defineType({
  name: 'myDocument',
  type: 'document',
  preview: {
    select: {
      title: 'title',
      status: 'status', // Select the field you want to base the icon on
    },
    prepare({title, status}) {
      // Return different icons based on document values
      let icon;
      if (status === 'published') {
        icon = CheckmarkIcon;
      } else if (status === 'archived') {
        icon = CloseIcon;
      } else {
        icon = ClockIcon;
      }
      
      return {
        title: title,
        subtitle: status,
        media: icon, // Dynamic icon based on status
      };
    },
  },
});

More Complex Logic

You can use any logic in the prepare function to determine which icon to display:

import { StarIcon, DocumentIcon, ImageIcon } from "@sanity/icons";

preview: {
  select: {
    title: 'title',
    featured: 'isFeatured',
    hasImage: 'mainImage',
    priority: 'priority'
  },
  prepare({title, featured, hasImage, priority}) {
    // Complex conditional logic
    let icon = DocumentIcon;
    
    if (featured && priority > 5) {
      icon = StarIcon;
    } else if (hasImage) {
      icon = ImageIcon;
    }
    
    return {
      title: title,
      subtitle: featured ? 'Featured' : 'Standard',
      media: icon,
    };
  },
}

Accessing Referenced Document Values

You can even make icons dynamic based on referenced document fields using dot notation in the select object, as explained in the preview configuration documentation:

preview: {
  select: {
    title: 'title',
    categoryType: 'category.type', // Access field from referenced document
  },
  prepare({title, categoryType}) {
    const icon = categoryType === 'blog' ? DocumentIcon : PageIcon;
    
    return {
      title: title,
      media: icon,
    };
  },
}

Important Notes

  • The media field can accept both image assets and icon components from @sanity/icons
  • You can use any React icon component, not just Sanity's built-in icons
  • The prepare function runs synchronously and cannot make GROQ queries, so all the data you need must be selected in the select object first
  • This works for document lists, array items, and reference fields throughout Studio

This approach gives you complete flexibility to create dynamic, contextual icons that help editors quickly understand document states at a glance! You can learn more about creating richer array item previews with similar techniques.

Show original thread
3 replies
I've seen that you can provide a React component as an Icon, but I'm not getting any props except className in that component
Nevermind, figured out how to use the media preview on documents for this purpose! 🙂
That’s right, this can be done via
preview
,
prepare
and
media
. Well figured out! 😉

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?