Reputation: 345
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.
Upvotes: 1
Views: 57
Reputation: 100
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>
Upvotes: 2
Reputation: 196
You can try this method; I believe it will resolve your problem.
<Box
key={index}
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: 6,
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: 1,
width: "100%",
}}
>
{iconText.icon}
<Typography
variant="h6"
component={"h3"}
sx={{ color: "#394454" }}
>
{iconText.label}
</Typography>
</Box>
<Box sx={{ textAlign: "start", width: "100%" }}>
<Typography variant="h4" component={"h2"}>
{iconText.value}
</Typography>
</Box>
</Box>
Upvotes: 3