portabletext / react-portabletext

Render Portable Text with React
https://portabletext.github.io/react-portabletext/
MIT License
315 stars 29 forks source link

Nested Lists? #69

Open ColbyMay opened 1 year ago

ColbyMay commented 1 year ago

I can't find any information on how I can target and style nested lists. Sanity uses "a series of list item blocks with the same level and listItem properties will be grouped into a virtual one inside of this library." My rich text is inputted as follows

image

and is seen queried like this:

  "2": {
    "children": [{ }],
    "level": 1,
    "listItem": "number",
    "markDefs": [],
    "style": "normal",
    "_key": "2cc0186eb9d3",
    "_type": "block"
  },
  "3": {
    "children": [{ }],
    "level": 2,
    "listItem": "number",
    "markDefs": [],
    "style": "normal",
    "_key": "984f45cfba95",
    "_type": "block"
  },
  "4": {
    "children": [{ }],
    "level": 2,
    "listItem": "number",
    "markDefs": [],
    "style": "normal",
    "_key": "730d9b626b42",
    "_type": "block"
  }
}

But is rendered without grouping the level 2 items with the same indentation treatment?

image

export default function RichText({ variant = 'default', richText }) {

    let components = {
        list: {
            // Ex. 1: customizing common list types
            bullet: ({ children }) => <ul className="mt-xl">{children}</ul>,
            number: ({ children }) => <ol className="mt-lg">{children}</ol>,

            // Ex. 2: rendering custom lists
            checkmarks: ({ children }) => <ol className="m-auto text-lg">{children}</ol>,
        },
        listItem: {
            number: ({ children }) => <Typography className='boo' paragraph={true} component='li' sx={{ color: 'red' }} >{children}</Typography>,
        },
    }

    return (
        <>
            {richText.map((block) => {
                return (
                    <PortableText
                        key={block._key}
                        value={block}
                        components={components}
                    />
                )
            })}
        </>
    )
}; 

How can we target the second level to style them properly? Am I misunderstanding how the grouping of levels should be operating?

tarcisioandrade commented 1 year ago

To with the same doubt, got a solution?

duncanmcdowell commented 1 year ago

Here is how I handled it. Keep in mind this only handles two levels since that was all I needed.

  const components: PortableTextComponents = {
    list: ({ value, children }) => {
      const { level, listItem } = value;

      if (listItem === 'bullet') {
        return <ul className="list-disc list-inside">{children}</ul>;
      }

      if (listItem === 'number') {
        if (level === 1) {
          return <ol className={'list-decimal ml-6'}>{children}</ol>;
        } else if (level === 2) {
          return <ol className={'list-[lower-alpha] ml-4'}>{children} </ol>;
        }
      } else {
        // Handle other list types if needed
        return null;
      }
    }
}