Discussion on passing custom props and accessing custom list items in @portabletext/react.
The className prop on the root <PortableText> component does not automatically propagate to your custom list components. This is just how the library works—it doesn't pass arbitrary props down to your serializers.
Passing className to Lists
You have two main options:
Option 1: Wrap the PortableText component
<div className={className}>
<PortableText value={content} components={ptComponents} />
</div>Option 2: Define className directly in your custom components
const ptComponents = {
list: {
bullet: ({ children }) => {
return <ul className="my-custom-bullet-list">{children}</ul>;
},
number: ({ children }) => {
return <ol className="my-custom-numbered-list">{children}</ol>;
}
}
}If you need dynamic styling, you can close over the className variable in your components definition, or create a function that returns the components object with your desired classes.
Accessing Custom List Items
For custom listItem components, you define them alongside your list components in the components object:
const ptComponents = {
list: {
bullet: ({ children }) => <ul className="bullet-list">{children}</ul>,
number: ({ children }) => <ol className="numbered-list">{children}</ol>
},
listItem: {
bullet: ({ children }) => <li className="bullet-item">{children}</li>,
number: ({ children }) => <li className="numbered-item">{children}</li>
}
}The list type (bullet or number) is determined by the Portable Text content itself—when an editor creates a bulleted or numbered list in Sanity Studio, that information is stored in the Portable Text data. The @portabletext/react library automatically matches your custom bullet or number serializers based on what's in the content. You don't need to manually designate which listItem to use.
Custom List Types Beyond Bullet and Number
If you want to add custom list types beyond the standard bullet and number, you would need to customize your Portable Text schema in Sanity Studio. The guide on customizing Portable Text covers how to extend the schema with custom list styles, which you can then handle with matching serializers in your components object.
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.