0
votes

I apologize if these questions come off as dumb. I'm trying to jump into React & Material-UI and I don't have a mentor to ask questions to or guide me. Kind of shooting in the dark as I go using documentation and tutorials etc. I have a lot of questions.. (in fact is there a better place to ask these sorts of quick one-off questions? a beginners chat forum maybe? a Slack group? not sure if Stack is the best place for this..)

I'm building out a form for a client. One of the questions is a four quadrant chart where the user selects an option that combines 4 different vectors. It's hard to explain, and I'm not sure what the technical term is for this type of chart, so I drew a diagram to make it clear what I'm trying to achieve:

Example of the grid I want to do make

I started building out a component in React to handle this selection chart, but I'm already getting kind of lost.. Here is what I have so far...

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardActionArea from '@material-ui/core/CardActionArea';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1,
  },
  h2: { //<-- is there a better way to do this? Or do I need to target each h2 with a className classes.h2 ?
    color: "#f00",    
  },
  paper: {
    padding: theme.spacing(1),
    textAlign: 'center',
    color: theme.palette.text.secondary,
  },
  card: {
    maxWidth: 345,
  },
  media: {
    height: 140,
  },
}));

export default function ProjectMap() {
  const classes = useStyles();

  function Slow_Expensive() {
    return (
      <Card className={classes.card}>
      <CardActionArea>
        <CardContent>
          <Typography variant="body2" color="textSecondary" component="p">
            Selection box slow but expensive.
          </Typography>
        </CardContent>
      </CardActionArea>
    </Card>
    );
  }


  function TopRow() {
    return (
      <React.Fragment>
        <Grid item xs={4}></Grid>
        <Grid item xs={4}>
          <h2>Expensive</h2>
        </Grid>
        <Grid item xs={4}></Grid>
      </React.Fragment>
    );
  }

  function MidRow() {
    return (
      <React.Fragment>
        <Grid item xs={4}>
          <h2 className={classes.h2}>Slow</h2> {/*Do I need to set a className on all of my h2's or is there a better way to target all of them within this component. */}
        </Grid>
        <Grid item xs={4}>
          <h2>The Four Quadrants go here.. maybe cards assembled into maybe another grid?? a table??</h2>
        </Grid>
        <Grid item xs={4}>
          <h2>Fast</h2>
        </Grid>
      </React.Fragment>
    );
  }

  function BotRow() {
    return (
      <React.Fragment>
        <Grid item xs={4}></Grid>
        <Grid item xs={4}>
           Cheap
        </Grid>
        <Grid item xs={4}></Grid>
      </React.Fragment>
    );
  }

  return (
    <div className={classes.root}>
    <h2>Choose one of hte options:</h2>
      <Grid container spacing={1}> {/*is grid the best way to layout this component? Should I use a table instead?*/}
        <Grid container justify="center" item  xs={12} spacing={2}>{/* Justify is not working.. I don't know why?*/}
          <TopRow />
        </Grid>
        <Grid container justify="center" item  xs={12} spacing={2}>
          <MidRow />
        </Grid>
        <Grid container justify="center"  item xs={12} spacing={2}>
          <BotRow />
        </Grid>
      </Grid>
    </div>



  );
}
  1. I'm still learning how Material-UI's Grid works. I come from a traditional vanilla JS/CSS/HTML background, and back in the day we used to use tables to lay out little widgets like this. In my code above I'm attempting to build out a table layout using the responsive grid system in Material-UI. Is this dumb? Or am I on the right track? Is grid used for little components like this? Or is it meant for larger layout elements like menus and page containers?
  2. I'm attempting to use cards for the four quadrants, but how would I assemble these into my larger grid? Do I need to nest another grid inside the larger grid? Or should I be using some sort of grid rowSpan or colSpan? Do grids even do that?
  3. I was thinking about using react radio boxes and styling them like divs since that would handle the click/select functionality, but I settled on using "Cards" and just using javascript to make them like radio boxes on click.
  4. I don't fully understand how useStyles hook is used here. I know it's meant to overrride the Material-UI component styles, but am I supposed to use it for everything? For example I'm using tags for the chart labels since semantically they seem to be chart headings, but to style them, do I need to add them to my useStyles function, and then add a className={classes.h2} to ALL of my H2's? Seems like there must be a better way to style these elements globally within my chart component. Should I be simply using a CSS template attached to my component instead? like : import './Chart.css';?
  5. Each of my other Components in this project also use "useStyles" but I noticed some of them work, some of them don't. For example I tried to resize a dialogue box to 80% width, but when I tried to apply it to my dialogue box using className={classes.dialogue}, the styles would not apply. I ended up using maxWidth = {'md'} property to get it to stretch wider, but is that the best way to do that?

s

<Dialog className={classes.root} 
        open={this.state.dialogOpen} 
        onClose={this.onDialogClose}

        maxWidth = {'md'}
        >

Let me know your thoughts.. any tips or suggestions on which way to go with these issues would be greatly appreciated.

Thanks!

1

1 Answers

1
votes

Do you need to support Internet Explorer? If not, easiest way to achieve this is using css grid.

Here is a example:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";

import Paper from "@material-ui/core/Paper";

const useStyles = makeStyles({
  paper: {
    display: "grid",
    gridTemplateColumns: "3rem 250px 250px 3rem",
    gridTemplateRows: "3rem 250px 250px 3rem",
    gridGap: "1rem",
    justifyItems: "center",
    alignItems: "center",
    justifyContent: "center"
  },
  top: {
    gridRow: "1 / 2",
    gridColumn: "1 / 5"
  },
  bottom: {
    gridRow: "4 / 5",
    gridColumn: "1 / 5"
  },
  left: {
    gridRow: "2 / 4",
    gridColumn: "1 / 2"
  },
  right: {
    gridRow: "2 / 4",
    gridColumn: "4 / 5"
  },
  card: {
    width: "100%",
    height: "100%"
  }
});

function MyCard({ title }) {
  const classes = useStyles();
  return (
    <Card className={classes.card}>
      <CardContent>
        <Typography>{title}</Typography>
      </CardContent>
    </Card>
  );
}

function Quadrants() {
  return (
    <React.Fragment>
      <MyCard title="Slow but expensive" />
      <MyCard title="Fast but expensive" />
      <MyCard title="Slow but Cheap" />
      <MyCard title="Slow but Fast" />
    </React.Fragment>
  );
}

function FourQuadrants() {
  const classes = useStyles();

  return (
    <Paper className={classes.paper}>
      <Typography className={classes.top}>Expensive</Typography>
      <Typography className={classes.bottom}>Cheap</Typography>
      <Typography className={classes.left}>Slow</Typography>
      <Typography className={classes.right}>Fast</Typography>
      <Quadrants />
    </Paper>
  );
}

export default FourQuadrants;

Live example:

Edit suspicious-goodall-6pgpq