Categories
Material UI

Material UI — Buttons

Material UI is a Material Design library made for React. It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add buttons Material Design.

Button

We can add buttons with the Button component.

For instance, we can write:

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

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

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

  return (
    <div className={classes.root}>
      <Button variant="contained">Default</Button>
      <Button variant="contained" color="primary">
        Primary
      </Button>
      <Button variant="contained" color="secondary">
        Secondary
      </Button>
      <Button variant="contained" disabled>
        Disabled
      </Button>
      <Button variant="contained" color="primary" href="#contained-buttons">
        Link
      </Button>
    </div>
  );
}

to add a variety of buttons.

We just add the Button prop with the variant to set the variant of the button.

color lets us change the color.

disabled lets us disabled a button.

href lets us add a URL for the link.

We added some spaces to the buttons with the theme.spacing in the makeStyles call.

Text Buttons

We can create text buttons to remove the outline.

For instance, we can write:

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

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

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

  return (
    <div className={classes.root}>
      <Button>Default</Button>
      <Button color="primary">Primary</Button>
      <Button color="secondary">Secondary</Button>
      <Button disabled>Disabled</Button>
      <Button href="#text-buttons" color="primary">
        Link
      </Button>
    </div>
  );
}

to add a variety of text buttons.

We removed the variant to make them text buttons.

Outlined Buttons

We can make buttons display an outline only with the variant prop.

For example, we can write:

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

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

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

  return (
    <div className={classes.root}>
      <Button variant="outlined">Default</Button>
      <Button variant="outlined" color="primary">
        Primary
      </Button>
      <Button variant="outlined" color="secondary">
        Secondary
      </Button>
      <Button variant="outlined" disabled>
        Disabled
      </Button>
      <Button variant="outlined" color="primary" href="#outlined-buttons">
        Link
      </Button>
    </div>
  );
}

to make them display an outline only.

variant is set to outline to make them that.

Handling Clicks

To handle clicks, we can pass in an event handler to the onClick prop.

For example, we can write:

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

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

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

  return (
    <div className={classes.root}>
      <Button
        onClick={() => {
          alert("clicked");
        }}
      >
        click me
      </Button>
    </div>
  );
}

Then we see the clicked alert when we click on the button.

We can add a button for uploading files.

To add one, we write:

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

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  },
  input: {
    display: "none"
  }
}));

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

  return (
    <div className={classes.root}>
      <input
        accept="image/*"
        className={classes.input}
        id="button-file"
        multiple
        type="file"
      />
      <label htmlFor="button-file">
        <Button variant="contained" color="primary" component="span">
          Upload
        </Button>
      </label>
    </div>
  );
}

We hide the regular HTML file upload input with the display: 'none' .

Then we add the file input and the button in the JSX expression.

The id should match the htmlFor value. This way, we can see the file selection dialog when we click on the button.

Sizes

Buttons can have a variety of sizes.

For instance, we can write:

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

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

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

  return (
    <div className={classes.root}>
      <Button size="small" className={classes.margin}>
        Small
      </Button>
      <Button size="medium" className={classes.margin}>
        Medium
      </Button>
      <Button size="large" className={classes.margin}>
        Large
      </Button>
    </div>
  );
}

We use the size prop with the small , medium or large values to change the sizes of the buttons.

Conclusion

We can do many things with buttons.

The size can be changed.

We can also add outlines and fill for our buttons.

And upload button can be added.

Categories
Material UI

Material UI — Grids

Material UI is a Material Design library made for React. It’s a set of React components that have Material Design styles. In this article, we’ll look at how to create layouts Material Design.

Auto-layout

We can create auto layouts if we don’t specify a column width for our breakpoints.

For instance, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  paper: {
    padding: theme.spacing(2),
    textAlign: "center",
    color: theme.palette.text.secondary
  }
}));

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

  return (
    <div className={classes.root}>
      <Grid container spacing={3}>
        <Grid item xs>
          <Paper className={classes.paper}>foo</Paper>
        </Grid>
        <Grid item xs>
          <Paper className={classes.paper}>bar</Paper>
        </Grid>
        <Grid item xs>
          <Paper className={classes.paper}>baz</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

to create our layout.

We have xs without any breakpoints, so we’ll let Material UI determine the sizing of the columns.

Nested Grid

We can create a nested grid with the Grid component.

For instance, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  paper: {
    padding: theme.spacing(1),
    textAlign: "center",
    color: theme.palette.text.secondary
  }
}));

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

return (
    <div className={classes.root}>
      <Grid container spacing={1}>
        <Grid container item xs={3} spacing={1}>
          <Paper className={classes.paper}>foo</Paper>
        </Grid>
        <Grid container item xs={3} spacing={1}>
          <Paper className={classes.paper}>bar</Paper>
        </Grid>
        <Grid container item xs={3} spacing={1}>
          <Paper className={classes.paper}>baz</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

to create a grid within a grid.

In the nested grid item, we put the Paper as the content.

xs lets us sets the column width.

spacing lets us set the spacing between the columns.

Grid List

Grid lists lets us display a collection of images in an organized grid.

For example, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import GridList from "@material-ui/core/GridList";
import GridListTile from "@material-ui/core/GridListTile";

const tileData = [
  { img: "http://placekitten.com/200/200", title: "cat" },
  { img: "http://placekitten.com/200/200", title: "cat" }
];

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex",
    flexWrap: "wrap",
    justifyContent: "space-around",
    overflow: "hidden",
    backgroundColor: theme.palette.background.paper
  },
  gridList: {
    width: 500,
    height: 450
  }
}));

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

  return (
    <div className={classes.root}>
      <GridList cellHeight={160} className={classes.gridList} cols={3}>
        {tileData.map(tile => (
          <GridListTile key={tile.img} cols={tile.cols || 1}>
            <img src={tile.img} alt={tile.title} />
          </GridListTile>
        ))}
      </GridList>
    </div>
  );
}

We have the GridList component with some data inside.

We have the GridListTile to show our item.

It has an img element that displays images.

cols has the column width.

alt has the alt text.

Grid List with Title Bars

We can add the GridListTitleBar component to add the title bar to an image tile.

For instance, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import GridList from "@material-ui/core/GridList";
import GridListTile from "@material-ui/core/GridListTile";
import GridListTileBar from "@material-ui/core/GridListTileBar";
import IconButton from "@material-ui/core/IconButton";
import InfoIcon from "@material-ui/icons/Info";

const tileData = [
  { img: "[http://placekitten.com/200/200](http://placekitten.com/200/200)", title: "cat", author: "john smith" },
  { img: "[http://placekitten.com/200/200](http://placekitten.com/200/200)", title: "cat", author: "mary smith" }
];

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex",
    flexWrap: "wrap",
    justifyContent: "space-around",
    overflow: "hidden",
    backgroundColor: theme.palette.background.paper
  },
  gridList: {
    width: 500,
    height: 450
  }
}));

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

  return (
    <div className={classes.root}>
      <GridList cellHeight={160} className={classes.gridList} cols={3}>
        {tileData.map(tile => (
          <GridListTile key={tile.img} cols={tile.cols || 1}>
            <img src={tile.img} alt={tile.title} />
            <GridListTileBar
              title={tile.title}
              subtitle={<span>by: {tile.author}</span>}
              actionIcon={
                <IconButton
                  aria-label={`info about ${tile.title}`}
                  className={classes.icon}
                >
                  <InfoIcon />
                </IconButton>
              }
            />
          </GridListTile>
        ))}
      </GridList>
    </div>
  );
}

We have the GridListTileBar component that takes a title prop for the title.

subtitle has the subtitle for the tile.

To include the icons, we’ve installed the @material-ui/icons package to add the icons.

Conclusion

We can create a grid with tiles to display text and images. The image can go with the title and subtitle. The layout can be automatically set.

Categories
Material UI

Getting Started with Material UI

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to get started with Material Design.

Installation

We can install the package by running:

npm install @material-ui/core

with NPM or:

yarn add @material-ui/core

to install it with Yarn.

We can also add the Roboto font by writing:

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />

in our HTML.

Material design icons can be added with:

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />

We can then get started by using some components from the package.

Box

We can make our layout with the Box component.

For example, we can write:

import React from "react";
import Box from "@material-ui/core/Box";
import Button from "@material-ui/core/Button";

export default function App() {
  return (
    <Box component="span" m={1}>
      <Button>foo</Button>
    </Box>
  );
}

to add the Box component for layout with a button inside.

component specifies which component to render as.

We can use clone to call React.cloneElement to clone elements:

import React from "react";
import Box from "@material-ui/core/Box";
import Button from "@material-ui/core/Button";

export default function App() {
  return (
    <Box color="text.primary" clone>
      <Button>foo</Button>
    </Box>
  );
}

Box can also accept a render props function:

import React from "react";
import Box from "@material-ui/core/Box";
import Button from "@material-ui/core/Button";

export default function App() {
  return (
    <Box color="text.primary">{props => <Button {...props}>foo</Button>}</Box>
  );
}

Container

We can add a container with the Container component.

For instance, we can write:

import React from "react";
import Container from "@material-ui/core/Container";

export default function App() {
  return <Container maxWidth="sm">foo</Container>;
}

We can add a Container component.

maxWidth specifies the max-width of the container.

sm means it’s a small container.

It can also have a fixed size:

import React from "react";
import Container from "@material-ui/core/Container";

export default function App() {
  return <Container fixed>foo</Container>;
}

We made it fixed with the fixed prop.

Grid

We can create our own grid with the Grid component.

For instance,e we can use as follows:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  paper: {
    height: 140,
    width: 200
  },
  control: {
    padding: theme.spacing(2)
  }
}));
export default function App() {
  const [spacing] = React.useState(2);
  const classes = useStyles();

  return (
    <Grid container className={classes.root} spacing={2}>
      <Grid item xs={12}>
        <Grid container justify="center" spacing={spacing}>
          {[0, 1, 2].map(value => (
            <Grid key={value} item>
              <Paper className={classes.paper} />
            </Grid>
          ))}
        </Grid>
      </Grid>
    </Grid>
  );
}

We have the Grid components.

The outer one is used as a container.

We pass in a class that’s created by makeStyles to it to set the flexbox to expand.

spacing is set to 2 to give us a margin.

In the inner Grid , we add the item prop to indicate that it’s a grid item.

justify lets us set the alignment according to the flexbox.

Then we add the Grid to display some boxes inside the container.

Fluid Grids

We can make the grid fluid with some breakpoints:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  paper: {
    padding: theme.spacing(2),
    textAlign: "center",
    color: theme.palette.text.secondary
  }
}));

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

  return (
    <div className={classes.root}>
      <Grid container spacing={3}>
        <Grid item xs={12} sm={3}>
          <Paper className={classes.paper}>foo</Paper>
        </Grid>
        <Grid item xs={12} sm={3}>
          <Paper className={classes.paper}>bar</Paper>
        </Grid>
        <Grid item xs={12} sm={6}>
          <Paper className={classes.paper}>baz</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

We create a grid with the makeStyles function to create the styles for our grid.

We have the root class to make the grid fill the container.

Then we have some breakpoint props to let us set the width for each breakpoint.

xs is extra small and it’ll set the column size for that screen size.

sm is small and it’ll set the column size for that screen size and up.

Conclusion

We can create basic layouts with Material UI.

It’s can be fixed size or responsive.

Categories
Material UI

Material UI — Virtualized Lists and Tables

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add lists with pinned headings, virtualized lists, and tables with Material UI.

Pinned Subheader List

We can use CSS to make the subheader pinned to the top of the screen until it’s pushed off by the next subheader.

For example, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import ListSubheader from "@material-ui/core/ListSubheader";

const useStyles = makeStyles(theme => ({
  root: {
    width: "100%",
    maxWidth: 360,
    backgroundColor: theme.palette.background.paper,
    position: "relative",
    overflow: "auto",
    maxHeight: 300
  },
  listSection: {
    backgroundColor: "inherit"
  },
  ul: {
    backgroundColor: "inherit",
    padding: 0
  }
}));

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

  return (
    <List className={classes.root} subheader={<li />}>
      {Array(10)
        .fill()
        .map((s, sectionId) => (
          <li key={`section-${sectionId}`} className={classes.listSection}>
            <ul className={classes.ul}>
              <ListSubheader>{`I'm sticky ${sectionId}`}</ListSubheader>
              {[0, 1, 2].map(item => (
                <ListItem key={`item-${sectionId}-${item}`}>
                  <ListItemText primary={`Item ${item}`} />
                </ListItem>
              ))}
            </ul>
          </li>
        ))}
    </List>
  );
}

We have the makeStyles function to set the position of the root to relative .

Also, we set a maxHeight so that it will scroll when the content overflows the list.

This way, we set the subheader to stay pinned.

Inset List

We can make list items that have no icon with text that aligns with the ones with icons.

For example, we can write:

import React from "react";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import StarIcon from "@material-ui/icons/Star";

export default function App() {
  return (
    <List aria-label="contacts">
      <ListItem button>
        <ListItemIcon>
          <StarIcon />
        </ListItemIcon>
        <ListItemText primary="james smith" />
      </ListItem>
      <ListItem button>
        <ListItemText inset primary="mary jane" />
      </ListItem>
    </List>
  );
}

We added the inset prop to make the text in the 2nd list item aligns with the text on the first.

Virtualized List

If we have a list with lots of items, then we’ve to make a virtualized list.

To do that, we can write:

import React from "react";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import { FixedSizeList } from "react-window";

function renderRow(props) {
  const { index, style } = props;

  return (
    <ListItem button style={style} key={index}>
      <ListItemText primary={`Item ${index + 1}`} />
    </ListItem>
  );
}

export default function App() {
  return (
    <FixedSizeList height={300} width={300} itemSize={40} itemCount={300}>
      {renderRow}
    </FixedSizeList>
  );
}

to create a virtualized list with react-window.

We have the renderRow to render a table row.

And we used the FixedSizedList instead of a regular List .

itemCount sets the item count.

itemSize has the size of an item.

The height and width are the height and width of the list.

Table

Material UI comes with a table component to let us display data in a table.

To create a simple one, we can write the following:

import React from "react";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";

function createData(firstName, lastName, age) {
  return { firstName, lastName, age };
}

const rows = [
  createData("james", "smith", 20),
  createData("mary", "jones", 30),
  createData("may", "wong", 30)
];

export default function App() {
  return (
    <TableContainer component={Paper}>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>first name</TableCell>
            <TableCell>last name</TableCell>
            <TableCell align="right">age</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {rows.map(row => (
            <TableRow key={row.name}>
              <TableCell component="th" scope="row">
                {row.firstName}
              </TableCell>
              <TableCell>{row.lastName}</TableCell>
              <TableCell align="right">{row.age}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

We created a table with the TableContainer , Table , TableHead , TableRow and TableCell components.

TableContainer has the container.

Tabke has the table itself.

TableHead holds the headings.

TableRow has the rows.

TableCell has the cells.

We can set the align prop of a cell to right to make the content align to the right.

Also, we can set the component prop to display as th if we wish.

The scope is set to the row to indicate that the cell is for a row and we get different cell formatting than headings.

Conclusion

We can make virtualized lists if our list has lots of items.

List headings can be pinned.

Table components are part of the core Material UI package.

Categories
Material UI

Material UI — Utility Components

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add a click away listener, CSS resets, and portals with Material UI.

Click Away Listener

We can add a click away listener to listen to when we click outside an element.

This lets us add things like menus easily.

For example, we can write:

import React from "react";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";

export default function App() {
  const [open, setOpen] = React.useState(false);

const handleClick = () => {
    setOpen(prev => !prev);
  };

const handleClickAway = () => {
    setOpen(false);
  };

return (
    <ClickAwayListener onClickAway={handleClickAway}>
      <div>
        <button type="button" onClick={handleClick}>
          menu
        </button>
        {open ? <div>some menu</div> : null}
      </div>
    </ClickAwayListener>
  );
}

to add a menu to our app.

We have the ClickAwayListener to our App .

Then we put the stuff that we want to do something with when the user click away from inside.

We have a div that will be removed when we click outside of it.

The onClickAway prop takes a function that runs when we click away from something.

The handleClick prop toggles the open prop to toggle the menu.

handleClickAway sets open to false to close the menu.

When we click the button the menu will open.

When we click outside it, it’ll close.

Portal

The Portal component is like the React portal component.

It lets us render the dropdown into a new location outside of the DOM hierarchy.

To use it, we can write:

import React from "react";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import Portal from "@material-ui/core/Portal";

export default function App() {
  const [open, setOpen] = React.useState(false);

  const handleClick = () => {
    setOpen(prev => !prev);
  };

  const handleClickAway = () => {
    setOpen(false);
  };

  return (
    <ClickAwayListener onClickAway={handleClickAway}>
      <div>
        <button type="button" onClick={handleClick}>
          menu
        </button>
        {open ? (
          <Portal>
            <div>some menu.</div>
          </Portal>
        ) : null}
      </div>
    </ClickAwayListener>
  );
}

We added the Portal component, which will render the div inside in the body instead of inside the div inside the ClickAwayListener .

Leading Edge

We can configure the ClickAwayListener to listen to leading events like mouse down and touch start.

For example, we can write:

import React from "react";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import Portal from "@material-ui/core/Portal";

export default function App() {
  const [open, setOpen] = React.useState(false);

  const handleClick = () => {
    setOpen(prev => !prev);
  };

  const handleClickAway = () => {
    setOpen(false);
  };

  return (
    <ClickAwayListener
      mouseEvent="onMouseDown"
      touchEvent="onTouchStart"
      onClickAway={handleClickAway}
    >
      <div>
        <button type="button" onClick={handleClick}>
          menu
        </button>
        {open ? <div>some menu.</div> : null}
      </div>
    </ClickAwayListener>
  );
}

We have a mouseEvent and touchEvent props to set the events that we listen to.

Therefore, we listen to the mouse down and touch start events.

CSS Baseline

The CssBaseline component provides CSS resets.

It provides style normalization provided by normalize.css.

It resets the CSS defaults to the same ones across every browser.

For instance, we can use it by writing:

import React from "react";
import CssBaseline from "@material-ui/core/CssBaseline";

export default function App() {
  return (
    <>
      <CssBaseline />
      reset
    </>
  );
}

The CssBaseline component provides a global CSS reset.

If we want to scope the CSS reset to some components, we can use the ScopedCssBaseline component.

For example, we can write:

import React from "react";
import ScopedCssBaseline from "@material-ui/core/ScopedCssBaseline";

export default function App() {
  return (
    <>
      <ScopedCssBaseline>reset</ScopedCssBaseline>
    </>
  );
}

We wrap the ScopedCssBaseline component around the elements that we want to reset the defaults for.

Conclusion

We can use the click away listener to listen for users clicking away from elements.

Material UI provides CSS reset components we can use to reset the defaults to make them consistent everywhere.

Portals let us render items anywhere in the DOM hierarchy.