Get the best of both worlds. Tailwind-styled typography and Portable Text's markup-and-components structure.
Protip
You may no longer need this! The Typography Plugin now supports a not-prose class which escapes from prose formatting. Make sure your Portable Text components use this class and you'll no longer need to add the additional step described below.
Use this Component just as you would your normal PortableText Component. For example:
<ProseableText value={value} />
Considerations:
This code assumes you have setup a PortableText Component using at least version 0.5.0 of next/sanity, but it should work with any use of the portabletext/react-portabletext package.
You may prefer to setup the prose classes as a prop so this Component is more reusable
Because prose will remove the top/bottom margin from the first/last element in an element respectively – you may wish to add this back in. The py-4 class is added in the demo below for this reason.
If using the older version block-content-to-react package, In your serializers, add container: ({children}) =>children so that blocks are not rendered with a wrapping <div>
import React,{useMemo}from'react'import{PortableText}from'../lib/sanity'/**
* Use Tailwind CSS's `prose` classes with Portable Text markup (blocks)
* Without inheriting styles for custom components (types)
*/exportdefaultfunctionProseableText({value =[]}){// Group together standard `_type === "block"` blocks// eg <p>, <li>, etc – and separate out everyone elseconst valueGroups =useMemo(()=>
value.reduce((acc, item)=>{const lastIdx = acc.length -1if(// We don't have items in this group yet
acc[lastIdx].length ===0||// The last group has the same `type`
acc[lastIdx][0]._type === item._type
){
acc[lastIdx].push(item)}else{// Time to create a new group, because the `type` is different compared to last group
acc.push([item])}return acc
},[[]]),[blocks])if(!valueGroups?.length)returnnullreturn valueGroups.map((group)=>
group[0]._type ==='block'?(<div key={group[0]._key} className="prose py-4"><PortableText value={group}/></div>):(<PortableText key={group[0]._key} value={group}/>))}
In this guide, you’ll see how Sanity separates organizations, projects, datasets, and members by working through a hypothetical example of a growing company that can expand its content model as they grow – without needing a complete overhaul.