My goal is to have a container, something like @mui/Box
, that displays rows of an icon and two texts. The icon and the first text are a unit and the second text is its own. Both the first, and the second texts of each row are dynamic texts, they can vary in length. I want that all 3 elements always start at the same position no matter the content of the texts. So something like this:
And even when a texts changes in length, each of the 3 elements start at the same position
But I just can't get it to work. I tried mapping each iconText
into their own Box
, but then the layouts always differ. Probably because they are each in their own container, so I thought maybe I can just map the variables of each iconText
as an element and have them all positioned by a grid
. And that does work (that's the layout of the images above), but then I have the issue that those elements are only wrapped in a react fragment and you can't set the key
property on that.
I tried so many different layouts and looked for anything about dynamic text layouts, but nothing worked right.
The layout with grid
looks like this
<Box sx={{ display: "grid", gridTemplateColumns: "1fr auto", columnGap: 3 }}>
{iconTexts.map((iconText, index) => (
<>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
{iconText.icon}
<Typography variant="h6" component={"h3"} sx={{ color: "#394454" }}>
{iconText.label}
</Typography>
</Box>
<Typography variant="h4" component={"h2"}>
{iconText.value}
</Typography>
</>
))}
</Box>
Which would work so well, but I can't set the keys.
My question is how can I achieve the desired dynamic text layout with either grid
or flex
, or actually any styling.
You can look at the example in this codesandbox.
Grid is good solution. But since you show the list of Box, please wrap the card with Box instead of Fragment, and use key attribute.
like this.
<Box sx={{ display: "grid", gridTemplateColumns: "1fr auto", columnGap: 3 }}>
{iconTexts.map((iconText, index) => (
<Box key={index} sx={{ display: "contents" }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
{iconText.icon}
<Typography variant="h6" component="h3" sx={{ color: "#394454" }}>
{iconText.label}
</Typography>
</Box>
<Typography variant="h4" component="h2">
{iconText.value}
</Typography>
</Box>
))}
</Box>