Issue with customizing portable text editor in Sanity v3 resolved with version update.

6 replies
Last updated: Mar 16, 2023
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:

  1. Check your browser console for any error messages - this is crucial for understanding what's going wrong
  2. Make sure you're on Sanity Studio v3 (check your package.json for sanity version)
  3. Clear your browser cache and hard refresh (Ctrl+Shift+R or Cmd+Shift+R)
  4. Try upgrading Sanity if you're on an older v3 version: npx sanity upgrade

Possible issues based on the pattern:

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

  • Icon not showing: This usually means the icon component isn't returning valid JSX or React isn't imported
  • Styling not applying: Make sure the component prop receives and renders props.children
  • Button not appearing: Check if all decorators are showing or just the custom one is missing

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! 🙏

user K
, see below. What I said here is not correct. You might find your answer though in what
user M
or I have posted later...best fortune.

I'm not where I can try code at the moment, but scanning that documentation, it looks like the code there might have a mistake. Look at the first example, and you can see they return a letter 'H' to create the icon. Simple and direct, right?

But as they build up patterns and capabilities to actually implement the highlighting in the editor, they no longer seem to return anything useful as an 'icon' from their routines, even considering the overused 'automatic' return of last item in arrow functions.

So how would an 'icon' show?

I would try adding a
return 'H'
at the end of your routine, and see if that doeesn't make things start to work....
Interesting. Your code is working in my Studio. What version of the Studio are you on?
Well, I made a mistake here... as
user M
says well, an the code you posted here,
user K
, does work, on Sanity latest 3.7, a good excuse I took to update it, and so would the Sanity documents code as I now see it.
I had missed where the proper H icon was indeed returned, as the decorator code was highlighted on the page, with the icon function proper, but just above it. The H in it was particularly hard to see in the dark mode my eyesight prefers, but this was just oversight in going too fast, my apology -- the Sanity documentation is fine.

But, it didn't work for me at first in trying it, even so, and some of the reasons might be what @Nicolas is running into:

• The main reason it didn't work is that I added the decorator to the wrong schema(!). But this is easy to do. Working on a simple blog model where I'm trying things out, I put the decorator in the seeming obvious place: the 'post' schema's block. However, I'd redefined that block to be my own type, with it's own schema. Once I put the decorator there, it worked. So maybe @Nicolas has something the same?
• to use this decorator definition, you need JSX abilities, so depending on whether you also use TypeScript or not, you need to make the schema using this a .jsx or .tsx file.
• In tsx, you might get a complaint about argument type for
marks:
after your decorator is added -- if you do, put a `// @ts-ignore`on a line above
marks:
. • Then, once actually working, there are some issues about seeing the highlight appear. If you select and apply it, the result doesn't seem to show until you move off that selection, as the decoration doesn't override the editor selection color. But you can see that it's applied by looking at the H icon - it will show the editor selection color if the selection is highlighted in your way. A small thing Sanity could perhaps improve, but workable given you let your content persons know about it.
• Last, to see the result in your website itself, you'll need some styling, css or what you prefer, to change the background color according to the class attribute delivered by Sanity, which by default seems to be
unknown__pt__mark__highlight
, until you customize Sanity's
portableTextToHtml()
with a custom element for marks.highlight. You can get an idea about that from the page for the language you use listed under Libraries on: https://www.sanity.io/docs/block-content (better advice just below)Whew. It does work, this...!
One more point, when you get to presenting your highlights on web pages. I tried this out also, for a bit this evening, and think I gave you the wrong reference, crossed out just above.
This should be the right one now on v3, I think:
https://www.sanity.io/docs/presenting-block-text , and you are possibly best served by the first on the Serialization Tooling list , given here on the same page, which is Portable Text to Html.
As I'm doing this using Astro, I used the function `portableTextToHtml`from the
astro-sanity
package, which works in the same way.
Hi, thank for your help, I updated to sanity 3.7 (I had the 3.3.x before) and now it’s working well.
user Q
I use the @portabletext/to-html to edit the
unknown__pt__mark__highlight
and it’s work perfectly on my front app. Thanks for the support.Thank you
user M
for the time !Have a nice day.
Great,
user K
, 👍 🪴

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?