How AI is powering better personalization in e-commerce [with Vercel]. Sign up now

Custom Portable Text decorator not showing icon/style in Sanity v3

6 repliesLast updated: Dec 2, 2025

Hi everyone, I work on Sanity v3 and I want to edit my portable text editor. I followed the documentation (https://www.sanity.io/docs/customizing-the-portable-text-editor#92d92c3189a3 ) but it doesn’t work (look on the picture).
Here’s my code :

{
  title: "Titre du block",
  name: "titleBlock",
  type: "array",
  of: [{ 
    type: "block",
    marks: {
      decorators: [
        { title: "Strong", value: "strong" },
        { title: "Emphasis", value: "em" },
        { title: "Code", value: "code" },
        { title: "Underline", value: "underline" },
        { title: "Strike", value: "strike-through" },
        {
          title: 'Highlight',
          value: 'highlight',
          icon: () => <span style={{fontWeight: 'bold'}}>H</span>,
          component: (props: any) => <span style={{ backgroundColor: 'yellow' }}>{props.children}</span>,
        }
      ],
    }
  }],
  group: "text",
  validation: (Rule: any) => Rule.required(),
},
My file is a tsx due to vite build who can’t work with js file (the doc use js file, how ?)

How can I add my icon and my style in the custom component ?

Thank’s for the help
🙏
AI Update

I can see your code structure is actually correct according to the official Sanity documentation! The pattern of using icon and component directly on the decorator object is the right approach for Sanity v3. However, there are a few things that might be causing issues. Let me help you troubleshoot:

Your code structure is correct, but here are some common issues and solutions:

1. Import React properly

Make sure you have React imported at the top of your file since you're using JSX:

import React from 'react'

2. Icon component needs to return valid JSX

Your icon function should return a proper React element. Try this:

{
  title: 'Highlight',
  value: 'highlight',
  icon: () => <span style={{fontWeight: 'bold'}}>H</span>,
  component: (props: any) => (
    <span style={{ backgroundColor: 'yellow' }}>{props.children}</span>
  ),
}

3. Alternative: Use a proper icon from @sanity/icons

Instead of an inline function, you could import an icon from the @sanity/icons package:

import { HighlightIcon } from '@sanity/icons'

// Then in your decorator:
{
  title: 'Highlight',
  value: 'highlight',
  icon: HighlightIcon,
  component: (props: any) => (
    <span style={{ backgroundColor: 'yellow' }}>{props.children}</span>
  ),
}

4. Complete working example

Here's a complete working example based on the official documentation:

import React from 'react'

const HighlightIcon = () => (
  <span style={{ fontWeight: 'bold' }}>H</span>
)

const HighlightDecorator = (props: any) => (
  <span style={{ backgroundColor: 'yellow' }}>{props.children}</span>
)

export default {
  title: "Titre du block",
  name: "titleBlock",
  type: "array",
  of: [{ 
    type: "block",
    marks: {
      decorators: [
        { title: "Strong", value: "strong" },
        { title: "Emphasis", value: "em" },
        { title: "Code", value: "code" },
        { title: "Underline", value: "underline" },
        { title: "Strike", value: "strike-through" },
        {
          title: 'Highlight',
          value: 'highlight',
          icon: HighlightIcon,
          component: HighlightDecorator,
        }
      ],
    }
  }],
  group: "text",
  validation: (Rule: any) => Rule.required(),
}

5. Regarding TypeScript/TSX files

You're absolutely right to use .tsx files! Sanity v3 works perfectly with TypeScript. The documentation examples use .js for simplicity, but .tsx is actually the recommended approach for type safety. This is not causing your issue.

6. Restart your dev server

After making schema changes, make sure to restart your Sanity Studio dev server:

npm run dev

or if you're using the newer commands:

npx sanity dev

Common troubleshooting steps:

Possible issues based on the pattern:

Without seeing the picture you mentioned, the most common issues are:

The pattern you're using matches the official documentation exactly, so if it's still not working after these adjustments, please share any error messages from the console and I can help further! 🙏

Show original thread
6 replies

Was this answer helpful?

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.

Related contributions