JSFiddle - React, Tailwind, and code Playground

HTML

<div id="root">
</div>

CSS

.part {
  font-size: 0.75em;
}

.part--level-0 {
  margin-left: 1em;
}
.part--level-1 {
  margin-left: 2em;
}

React

const parts = [
  {
    title: "Visual language",
    parts: [
      {
        title: "Color",
        parts: ["Palettes", "Contrast", "Meaning", "Swatches"],
      },
      {
        title: "Typography",
        parts: ["Hierarchy", "Weights / types", "Web fonts", "Baseline grid"],
      },
      "Photography",
    ],
  },
  {
    title: "UI elements",
    category: true,
    parts: [
      "Paragraph",
      "Block quote",
      "Headers (H1 - H6)",
      "Lists",
      "Links",
      {
        title: "Buttons",
        parts: [
          "Primary",
          "Secondary",
          "Button groups",
          "Menu buttons",
        ],
      },
      "Slider",
    ],
  },
];

const flatten = (obj, depth, currentDepth = 0) => {
  const array = Array.isArray(obj) ? obj : [obj];
  return array.reduce((acc, value) => {
    acc.push({
      title: value.title || value,
      depth: currentDepth,
    });
    if (value.parts) {
      acc = acc.concat(flatten(value.parts, depth, currentDepth + 1));
    }
    return acc;
  }, []);
};

const partsFlattened = parts.map((category) => {
  const categoryFlattened = {
    parts: flatten(category.parts),
    title: category.title,
    category: category.category,
  };
  return categoryFlattened;
});

function PartsList(props) {
  return <ul>
    {partsFlattened.map((category) => (
      <li>
        {category.title}<br/>
        {category.parts.map((part) => (
          <div className={`part part--level-${part.depth}`}>
            {part.title}
          </div>
        ))}
      </li>
    ))}
  </ul>;
}


const element = <PartsList />;
ReactDOM.render(
  element,
  document.getElementById('root')
);