Picture of icons

How to add custom icons to your Sanity.io Studio's Portable Text

How to make your Portable Text Custom objects look more professional with custom icons

If you followed my last blog post where I added a custom YouTube embed you may have noticed that the icon used by Sanity in the Portable Text editor was a bit bland. This is because it's the default icon. It works, but is not the most user friendly or professional looking (icon is inside the red box).

In this post I will show you how to change that icon to something better.

Step 1 - About the icon library

Sanity studio uses the react-icons library which is found at https://react-icons.netlify.com/. This provides a ton of icons from several of the most popular icon libraries around. A big advantage with this library is that you only load the icons you need, so the footprint is very small. It's important to note that Sanity is using an older version of this library and so it uses the older syntax

import FaCode from 'react-icons/lib/fa/code'

It's also important to note that Sanity does not have all of the icon sets the newer version does. Sanity only has the Font Awesome, Material Design, Typicons and Github Opticons. This is quite a lot of options, but if it's not enough for you, you can upgrade the react-icons library yourself and adjust your code accordingly.

Step 2 - Choose your icon

You can see (and search) the list of icons at https://react-icons.netlify.com/. For this example I'm going to add a video icon to my custom YouTube embed object. I'm choosing the icon called 'MdOndemandVideo'

Step 3 - Identify the icon library

There are several libraries of icons, and it's important to know which library you are using when importing the icon.

The good news, is that this is really easy, as the library name is the first 2 characters of the icon name (in lowercase). In this case, that would be "md".

Step 4 - Import the font to the code file where you need it

I'll be editing youtube.js in this example. I will add the following to the top of the file (let vs-code intellisense help you git the right library name):

import MdOndemandVideo from 'react-icons/lib/md/ondemand-video'

Step 5 - Add a reference to the icon in the Studio object

A studio object has a parameter icon that you can use to assign an icon to that object. It is assigned similar to name, or title, except that it accepts an icon type. Here is the what that looks like for my file:

export default {
  name: 'youtube',
  type: 'object',
  title: 'YouTube Embed',
  icon: MdOndemandVideo,
  fields: [

Step 6 - Run your project in dev to test

You really need to test as I've run across a couple of icons that don't work and a couple that display differently than the docs show. (There are enough icons to choose from that I don't find this a huge concern. If a specific icon doesn't work, I just choose another).

Wrapping it up

This is what my Portable Text editor looked like before (the red box is only there to hightlight the icon we are changing):

And this is what it looks like now?

As you can see, not only did I update the YouTube embed icon, but also the code block, image and author reference icons. A small change but one that greatly improves usability and looks much more professional.

Bonus:

This tip isn't just for your portable text editor. You can also decide on the icons you want to show on the desktop as well.

Sanity is already doing this in the Sanity create blog starter.

Here is the studio/deskStructure.js file that defines the desktop. You will see the icon imports at the top of the file and where they are used later to assign that icon to an Item. If you want to change or add icons, just import them and assign them in a similar manner.

import S from '@sanity/desk-tool/structure-builder'
import MdSettings from 'react-icons/lib/md/settings'
import MdPerson from 'react-icons/lib/md/person'

const hiddenDocTypes = listItem =>
  !['category', 'author', 'post', 'siteSettings'].includes(listItem.getId())

export default () =>
  S.list()
    .title('Content')
    .items([
      S.listItem()
        .title('Settings')
        .icon(MdSettings)
        .child(
          S.editor()
            .id('siteSettings')
            .schemaType('siteSettings')
            .documentId('siteSettings')
        ),
      S.listItem()
        .title('Blog posts')
        .schemaType('post')
        .child(S.documentTypeList('post').title('Blog posts')),
      S.listItem()
        .title('Authors')
        .icon(MdPerson)
        .schemaType('author')
        .child(S.documentTypeList('author').title('Authors')),
      S.listItem()
        .title('Categories')
        .schemaType('category')
        .child(S.documentTypeList('category').title('Categories')),
      // This returns an array of all the document types
      // defined in schema.js. We filter out those that we have
      // defined the structure above
      ...S.documentTypeListItems().filter(hiddenDocTypes)
    ])

I'd also reccommend checking out Sanity's documentation where they show a different place you can use icons in this fashion. https://www.sanity.io/docs/icons-for-data-types