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')
);