Categories
Material UI

Material UI — Slider

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 sliders with Material UI.

Discrete Sliders

We can add sliders to snaps to discrete values.

To do that, we set the marks prop to true .

For instance, we can write:

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

export default function App() {
  return (
    <form>
      <Slider marks />
    </form>
  );
}

to make an uncontrolled slider that snaps to the nearest 10.

Small Steps

We can change the steps with the steps prop.

For example, we can write:

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

export default function App() {
  return (
    <form>
      <Slider step={0.00001} marks />
    </form>
  );
}

to change the increment between each discrete value.

Custom Marks

We can add our own custom marks with the marks prop.

For example, we can write:

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

const marks = [
  {
    value: 0,
    label: "0m"
  },
  {
    value: 25,
    label: "25m"
  },
  {
    value: 50,
    label: "50m"
  },
  {
    value: 75,
    label: "75m"
  },
  {
    value: 100,
    label: "100m"
  }
];

export default function App() {
  return (
    <form>
      <Slider step={10} marks={marks} valueLabelDisplay="auto" />
    </form>
  );
}

We add the marks array with the value and label properties in each entry to show the labels with the text in the label property.

Restricted Values

We can restrict values to the ones that are in the marks array by setting step to null .

For example, we can write:

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

const marks = [
  {
    value: 0,
    label: "0m"
  },
  {
    value: 25,
    label: "25m"
  },
  {
    value: 50,
    label: "50m"
  },
  {
    value: 75,
    label: "75m"
  },
  {
    value: 100,
    label: "100m"
  }
];

export default function App() {
  return (
    <form>
      <Slider step={null} marks={marks} valueLabelDisplay="auto" />
    </form>
  );
}

Now we can only select the values that are marked in the marks array because of the null value we passed into the step prop.

Make Label Always Visible

We can make the labels always visible by setting the valueLabelDisplay prop to on .

For example, we can write:

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

const marks = [
  {
    value: 0,
    label: "0m"
  },
  {
    value: 25,
    label: "25m"
  },
  {
    value: 50,
    label: "50m"
  },
  {
    value: 75,
    label: "75m"
  },
  {
    value: 100,
    label: "100m"
  }
];

export default function App() {
  return (
    <form>
      <Slider step={10} valueLabelDisplay="on" marks={marks} />
    </form>
  );
}

Now we see the value above the slider dot.

Range Slider

We can allow users to select a value range with the Slider .

To do that, we can set an array as the value as the initial value.

For example, we can write:

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

export default function App() {
  const [value, setValue] = React.useState([20, 30]);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };
  return (
    <form>
      <Slider valueLabelDisplay="auto" value={value} onChange={handleChange} />
    </form>
  );
}

to make a range slider.

We set an array as the initial value of the value state to make the slider a range slider.

Vertical Sliders

We can make a slider vertical with the orientation prop set to vertical .

For instance, we can write:

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

const useStyles = makeStyles({
  root: {
    height: 300
  }
});

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

  return (
    <div className={classes.root}>
      <Slider
        orientation="vertical"
        valueLabelDisplay="auto"
        defaultValue={30}
      />
    </div>
  );
}

to create a vertical slider.

We’ve to set the height of the wrapper so that the slider is displayed.

Track

We can set track to false to remove the track that’s displayed when we select a value.

To do that, we write:

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

export default function App() {
  return (
    <div>
      <Slider track={false} defaultValue={30} />
    </div>
  );
}

to remove th track.

We can also set it to inverted to change the track to be opposite of the default.

Non-Linear Scale

The scale is linear by default, but we can change it to a nonlinear scale with the scale prop set to a function.

We can write:

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

export default function App() {
  return (
    <div>
      <Slider scale={x => x ** 5} defaultValue={30} />
    </div>
  );
}

to change the scale.

Conclusion

We can add sliders to let users select a number or a range of numbers from a slider.

Categories
Material UI

Material UI — Transfer List

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 transfer list with Material UI.

Transfer List

A transfer list lets us move one or more items between lists.

To use it, we can write:

import React from "react";
import Grid from "@material-ui/core/Grid";
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 Checkbox from "@material-ui/core/Checkbox";
import Button from "@material-ui/core/Button";
import Paper from "@material-ui/core/Paper";

function not(a, b) {
  return a.filter(value => b.indexOf(value) === -1);
}

function intersection(a, b) {
  return a.filter(value => b.indexOf(value) !== -1);
}

export default function App() {
  const [checked, setChecked] = React.useState([]);
  const [left, setLeft] = React.useState([0, 1, 2, 3]);
  const [right, setRight] = React.useState([4, 5, 6, 7]);

  const leftChecked = intersection(checked, left);
  const rightChecked = intersection(checked, right);

  const handleToggle = value => () => {
    const currentIndex = checked.indexOf(value);
    const newChecked = [...checked];

    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

  setChecked(newChecked);
  };

  const handleAllRight = () => {
    setRight(right.concat(left));
    setLeft([]);
  };

  const handleCheckedRight = () => {
    setRight(right.concat(leftChecked));
    setLeft(not(left, leftChecked));
    setChecked(not(checked, leftChecked));
  };

  const handleCheckedLeft = () => {
    setLeft(left.concat(rightChecked));
    setRight(not(right, rightChecked));
    setChecked(not(checked, rightChecked));
  };

  const handleAllLeft = () => {
    setLeft(left.concat(right));
    setRight([]);
  };

  const customList = items => (
    <Paper>
      <List dense component="div" role="list">
        {items.map(value => {
          const labelId = `transfer-list-item-${value}-label`;

  return (
            <ListItem
              key={value}
              role="listitem"
              button
              onClick={handleToggle(value)}
            >
              <ListItemIcon>
                <Checkbox
                  checked={checked.indexOf(value) !== -1}
                  tabIndex={-1}
                  disableRipple
                  inputProps={{ "aria-labelledby": labelId }}
                />
              </ListItemIcon>
              <ListItemText id={labelId} primary={`item ${value + 1}`} />
            </ListItem>
          );
        })}
        <ListItem />
      </List>
    </Paper>
  );

  return (
    <Grid container spacing={2} justify="center" alignItems="center">
      <Grid item>{customList(left)}</Grid>
      <Grid item>
        <Grid container direction="column" alignItems="center">
          <Button
            variant="outlined"
            size="small"
            onClick={handleAllRight}
            disabled={left.length === 0}
            aria-label="move all right"
          >
            ≫
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={handleCheckedRight}
            disabled={leftChecked.length === 0}
            aria-label="move selected right"
          >
            &gt;
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={handleCheckedLeft}
            disabled={rightChecked.length === 0}
            aria-label="move selected left"
          >
            &lt;
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={handleAllLeft}
            disabled={right.length === 0}
            aria-label="move all left"
          >
            ≪
          </Button>
        </Grid>
      </Grid>
      <Grid item>{customList(right)}</Grid>
    </Grid>
  );
}

We have a grid 2 lists side by side.

We added the list with the List component.

The left list is created with the customList component, which has a List with some items inside it.

Each item has its own checkbox so that’s we can check them off and move them.

The moving is done by a few functions.

The handleAllRight function moves everything to the right.

handleCheckedRight moves everything that’s checked to the right.

handleCheckedLeft moves the items that are check to the left list.

handleAllLeft moves all items to the left list.

The move is done by a few helper functions.

setLeft and setRight sets the items for the left and right respectively.

We concatenate the existing items with the ones that’s checked in each function.

setChecked is used to set the checked value of each item.

It only unchecks that values that are moved.

The example is simplified from the one at https://material-ui.com/components/transfer-list/

Conclusion

We can make a transfer list by following the Material UI example.

We make 2 lists with their own items.

The items are on each list are determined by the state.

Then we can move them by concatenating to the new list and removing them from the old list.

Categories
Material UI

Material UI — Text Field Customization

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 text fields with Material UI.

Sizes

We can change the size of a text field with the size prop.

For example, we can write:

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

export default function App() {
  return (
    <div className="App">
      <TextField label="Size" id="small" defaultValue="Small" size="small" />
    </div>
  );
}

to add a text field with the size small .

Layout

We can layout our text fields our way.

To do that, we can write:

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

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex",
    flexWrap: "wrap"
  },
  textField: {
    marginLeft: theme.spacing(1),
    marginRight: theme.spacing(1),
    width: "25ch"
  }
}));

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

return (
    <>
      <div>
        <TextField
          id="filled-full-width"
          label="Label"
          style={{ margin: 8 }}
          placeholder="Placeholder"
          helperText="Full width!"
          fullWidth
          margin="normal"
          InputLabelProps={{
            shrink: true
          }}
          variant="filled"
        />
        <TextField
          label="None"
          id="filled-margin-none"
          defaultValue="foo"
          className={classes.textField}
          helperText="foo"
        />
        <TextField
          label="Dense"
          style={{ margin: 3 }}
          id="filled-margin-dense"
          defaultValue="bar"
          className={classes.textField}
          helperText="bar"
          margin="dense"
        />
      </div>
    </>
  );
}

to add text fields.

We have one full-width text field at the top and 2 shorter ones at the bottom.

They have the usual props, which have the helperText for the hint.

margin have the margin.

We also have some styles to change the margins.

className have the class names.

placeholder have the placeholder for the text fields.

variant can be filled or not.

margin can be smaller than the default with dense .

Uncontrolled vs Controlled

Text fields can be uncontrolled, which means that it doesn’t have any state attached to it.

Or it can be controlled, which means that it has state attached to it.

To make a controlled text field, we can add the value and onChange props to the TextField .

For example, we can write:

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

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <TextField
          id="standard-name"
          label="Name"
          value={name}
          onChange={handleChange}
        />
      </div>
    </>
  );
}

We have the name state which is passed into the value prop.

And the handleChange function which is passed into the onChange prop.

Then when we type something in, the handleChange function will run and call setName to update the name state.

Components

A TextField is made of smaller components.

They include FormControl , Input , FilledInput , InputLabel , OutlinedInput and FormHelperText .

For instance, we can substitute a TextField with:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <Input id="input" value={name} onChange={handleChange} />
        </FormControl>
      </div>
    </>
  );
}

We have an Input for the input box and InputLabel for the label for the input box.

To add hint text, we can use the FormHelperText component:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
import FormHelperText from "@material-ui/core/FormHelperText";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <Input id="input" value={name} onChange={handleChange} />
          <FormHelperText>enter your name</FormHelperText>
        </FormControl>
      </div>
    </>
  );
}

We can also use the OutlinedInput and FilledInput components to add input boxes with those varieties:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import OutlinedInput from "@material-ui/core/OutlinedInput";
import InputLabel from "@material-ui/core/InputLabel";
import FormHelperText from "@material-ui/core/FormHelperText";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <OutlinedInput
            id="input"
            value={name}
            onChange={handleChange}
            label="Name"
          />
          <FormHelperText>enter your name</FormHelperText>
        </FormControl>
      </div>
    </>
  );
}

to add an input box with the outline to the box.

And we can use the FilledInput to add an input box with the background:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import FilledInput from "@material-ui/core/FilledInput";
import InputLabel from "@material-ui/core/InputLabel";
import FormHelperText from "@material-ui/core/FormHelperText";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <FilledInput id="input" value={name} onChange={handleChange} />
          <FormHelperText>enter your name</FormHelperText>
        </FormControl>
      </div>
    </>
  );
}

Conclusion

A TextField is composed of many form components.

Therefore, we can add those instead of a TextField .

We can also make a text field and controller input.

Categories
Material UI

Material UI — Text Field Basics

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 text fields with Material UI.

Text Field

Text fields are form controls to let users enter and edit text.

To add them, we use the TextField component.

For example, we can write:

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

export default function App() {
  return (
    <div className="App">
      <TextField label="Standard" />
    </div>
  );
}

to add a basic text field.

label is displayed as the placeholder.

We can also add the variant prop to change the styling.

For example, we can write:

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

export default function App() {
  return (
    <div className="App">
      <TextField label="filled" variant="filled" />
    </div>
  );
}

to add a text field with a background color.

Form Props

We can add the required prop to make the field required.

disabled disables the text field.

type has the input type.

helperText lets us show users hints.

For example, we can write:

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

export default function App() {
  return (
    <div className="App">
      <TextField label="required" required helperText="required field" />
    </div>
  );
}

to add helper text to our field, which will be displayed at the bottom.

required adds an asterisk to the label to indicate that it’s required.

Validation

The error prop lets us toggle the error state.

For example, we can write:

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

export default function App() {
  return (
    <div className="App">
      <TextField label="error" error />
    </div>
  );
}

to show a text field with errors in it.

It’ll be all red.

Select

The select prop makes the text field use the Select component internally.

For example, we can write:

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

const fruits = [
  { value: "apple", label: "Apple" },
  { value: "orange", label: "Orange" },
  { value: "grape", label: "Grape" }
];

export default function App() {
  const [fruit, setFruit] = React.useState("apple");

  const handleChange = event => {
    setFruit(event.target.value);
  };

  return (
    <div className="App">
      <TextField
        select
        label="Select"
        value={fruit}
        onChange={handleChange}
        helperText="Please select your fruit"
      >
        {fruits.map(option => (
          <MenuItem key={option.value} value={option.value}>
            {option.label}
          </MenuItem>
        ))}
      </TextField>
    </div>
  );
}

We create a dropdown with the TextField component.

label has the label.

value is the selected value.

onChange runs when we change the selection, which we can use to set the select value state.

Inside the TextField , we have the MenuItem components to display the options.

Icons

We can add icons to our TextFields .

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
import AccountCircle from "@material-ui/icons/AccountCircle";

export default function App() {
  return (
    <div className="App">
      <Grid container spacing={1} alignItems="flex-end">
        <Grid item>
          <AccountCircle />
        </Grid>
        <Grid item>
          <TextField id="input-with-icon-grid" label="input" />
        </Grid>
      </Grid>
    </div>
  );
}

to add a text field beside an icon.

AccountCircle is the icon.

The TextField is to the right of it.

Input Adornments

We can use the InputAdornment component to add prefix, suffix or an action to an input.

For example, we can write:

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

const useStyles = makeStyles(theme => ({
  margin: {
    margin: theme.spacing(1)
  },
  textField: {
    width: "25ch"
  }
}));

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

  return (
    <div className="App">
      <TextField
        label="length"
        id="filled-start-adornment"
        className={clsx(classes.margin, classes.textField)}
        InputProps={{
          startAdornment: (
            <InputAdornment position="start">meters</InputAdornment>
          )
        }}
      />
    </div>
  );
}

We add a TextField with an InputAdornment .

position set to start which means that we add a prefix to the input.

It’ll be displayed on the left.

We have a class to add some margins between the prefix and the input box.

Conclusion

We can add text fields to let users enter text.

There are many options we can change to style it the way we want.

Also, we can icons and text beside the input box.

There are also styles for errors.

Categories
Material UI

Material UI — Switches

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 switches with Material UI.

Switches

Switches are toggles that let us set something on or off.

To add one, we use the Switch component.

For instance, we can write:

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

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <Switch checked={checked} onChange={handleChange} name="checked" />
    </div>
  );
}

We set the checked prop with the checked state.

onChange has a function that runs when we click on the toggle.

event.target.checked has the checked value so that we use it to change the checked state.

We can change the color with the color prop.

For example, we can write:

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

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <Switch
        color="primary"
        checked={checked}
        onChange={handleChange}
        name="checked"
      />
    </div>
  );
}

With the color prop, we changed the color.

primary is purple.

Also, we can disable it with the disabled prop.

For example, we can write:

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

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <Switch
        disabled
        checked={checked}
        onChange={handleChange}
        name="checked"
      />
    </div>
  );
}

With the disabled prop, users can’t interact with it.

Switch with FormControlLabel

To add a label with the switch, we can use the FormControlLabel component.

For example, we can write:

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

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <FormControlLabel
        control={
          <Switch checked={checked} onChange={handleChange} name="checked" />
        }
        label="switch"
      />
    </div>
  );
}

to add a switch with a label to the right.

The label prop is the text for the label.

Switches with FormGroup

FormGroup s let us wrap a bunch of for,m controls into a group.

We can use these with switches.

For instance, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormLabel from "@material-ui/core/FormLabel";
import FormControl from "@material-ui/core/FormControl";
import FormGroup from "@material-ui/core/FormGroup";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <FormControl component="fieldset">
        <FormLabel component="legend">choose</FormLabel>
        <FormGroup>
          <FormControlLabel
            control={
              <Switch
                checked={checked}
                onChange={handleChange}
                name="checked"
              />
            }
            label="switch"
          />
        </FormGroup>
      </FormControl>
    </div>
  );
}

We have a FormGroup surrounding our FormControlLabel for the switch.

Sizes

We can change the size with the size prop.

For example, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormLabel from "@material-ui/core/FormLabel";
import FormControl from "@material-ui/core/FormControl";
import FormGroup from "@material-ui/core/FormGroup";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <FormControlLabel
        control={
          <Switch size="small" checked={checked} onChange={handleChange} />
        }
        label="Small"
      />
    </div>
  );
}

to add a small switch.

We set size to small to make it small.

Customizable Switch

We can customize our switch with our own classes.

For example, we can write:

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

const useStyles = makeStyles({
  switchBase: {
    color: yellow[300],
    "&$checked": {
      color: yellow[500]
    },
    "&$checked + $track": {
      backgroundColor: yellow[500]
    }
  },
  checked: {},
  track: {}
});

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

  return (
    <div className="App">
      <Switch
        focusVisibleClassName={classes.focusVisible}
        disableRipple
        classes={{
          root: classes.root,
          switchBase: classes.switchBase,
          thumb: classes.thumb,
          track: classes.track,
          checked: classes.checked
        }}
      />
    </div>
  );
}

to make a switch with our own classes.

We have an object with switchBase property with styles for the color when it’s checked.

We set the color to yellow if it’s checked.

The background is also set to yellow.

Then we use the useStyles hook to get the classes and apply them to our Switch .

We can also pass any props into our Switch component as we wish.

Conclusion

We can add switches with different styles to let us add toggles for users to use.