React Material Box Hover Tile and Stackable Alerts

Overview

The example below show 3d box shadows using MUI’s box component and icons. When a box is clicked, MUI snack bars components will appear. The snack bar notifications are stacked vertically.

Libraries Needed

MUI – Material UI v5.4.3

Material UI library for React

npm install @mui/material @mui/lab @mui/icons-material @emotion/react @emotion/styled

Notice Stack AKA notistack is a library that gives you more options for displaying notifications like snackbars. It provides a way to stack notifications on top of one another.

npm install notistack

MUI Box Hover Tile

With MUI’s <Box> component, style it with CSS to show a slight shadow box with a transition triggered on hover to give it a 3d effect.

Box CSS

Inside the Box component, use a sx property to add custom CSS styling. Below is the CSS for creating a box with a shadow. Also, setting the transition property for 300 milliseconds so we can animate the hover event.

    position: 'relative',
    width: 200,
    height: 180,
    padding: '14px',
    border: '1px solid #FAFAFA',        
    background: 'smoke',
    opacity: [0.9, 0.8, 0.7],
    boxShadow: '0px 1px 11px rgba(0,0,0,0.2)',
    transition: '.3s',    

Transition on Hover

Using CSS transform, increase the opacity and boxShadow to give it a smooth pop out effect. Also, change the cursor to a pointer so users will know they can click on it.

'&:hover': {
          boxShadow: '0px 4px 10px rgba(0,0,0,0.4)',
          cursor: 'pointer',
          transform: 'scale(1.05,1.05)',
          opacity: [1.0, 1.0, 1.0],
 },

The code for the Box component.

Box
   onClick={() => props.handleClick(props.title)}
   sx={{
        position: 'relative',
        width: 200,
        height: 180,
        padding: '14px',
        border: '1px solid #FAFAFA',        
        background: 'smoke',
        opacity: [0.9, 0.8, 0.7],
        boxShadow: '0px 1px 11px rgba(0,0,0,0.2)',
        transition: '.3s',
        '&:hover': {
          boxShadow: '0px 4px 10px rgba(0,0,0,0.4)',
          cursor: 'pointer',
          transform: 'scale(1.05,1.05)',
          opacity: [1.0, 1.0, 1.0],
        },

    }}
 />

Code for the ‘HoverTile.js’ component.

import * as React from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Stack from '@mui/material/Stack';


export default function TileMediaType(props) {

  return (
    <>
    <Box
      onClick={() => props.handleClick(props.title)}
      sx={{
        position: 'relative',
        width: 200,
        height: 180,
        padding: '14px',
        border: '1px solid #FAFAFA',
        
        background: 'smoke',
        opacity: [0.9, 0.8, 0.7],
        boxShadow: '0px 1px 11px rgba(0,0,0,0.2)',
        transition: '.3s',
        '&:hover': {
          boxShadow: '0px 4px 10px rgba(0,0,0,0.4)',
          cursor: 'pointer',
          transform: 'scale(1.05,1.05)',
          opacity: [1.0, 1.0, 1.0],
        },

      }}
    >
      <Stack spacing={4} sx={{mt: 1}}  alignItems="center" >
        <Typography variant="h4" component="div" align="center">
            {props.title}
        </Typography>
       {props.children}
       </Stack>    
    </Box>
    
  </>
  );
}

Using notistack for Snackbar Alerts

Notice Stack AKA notistack

The notistack library gives you options for displaying notifications. In this example, it will stack up to four notifications vertically. In order to use notistack, you have to wrap the application with a provider (example below).

Wrapping the Root Component with Notistack

import { SnackbarProvider, useSnackbar } from 'notistack';

...

 const { enqueueSnackbar } = useSnackbar();

 const handleClick = (event) => {    
   enqueueSnackbar(event);
 };

...

export default function IntegrationNotistack() {
  return (
    <SnackbarProvider maxSnack={4}>
      <MyApp />
    </SnackbarProvider>
  );
}

Source Code for App.js

Code for ‘.\App.js

import * as React from 'react';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import Container from '@mui/material/Container';
import Stack from '@mui/material/Stack';
import HoverTile from './components/HoverTile'
import SettingsIcon from '@mui/icons-material/Settings';
import SettingsInputCompositeIcon from '@mui/icons-material/SettingsInputComposite';
import WidgetsIcon from '@mui/icons-material/Widgets';
import { SnackbarProvider, useSnackbar } from 'notistack';

function MyApp() {
  const { enqueueSnackbar } = useSnackbar();

  const handleClick = (event) => {    
    enqueueSnackbar(event);
  };

  return (
    <React.Fragment>
      
        <Container maxWidth='lg'>
          <Stack direction="row" spacing={4} sx={{mt: 7}}>
            <HoverTile title="Option I" handleClick={handleClick}>
            <PowerSettingsNewIcon sx={{fontSize: '82px'}}/>
            </HoverTile>
            <HoverTile title="Option II" handleClick={handleClick}>
              <SettingsIcon sx={{fontSize: '82px'}}/>
            </HoverTile>
            <HoverTile title="Option III" handleClick={handleClick}>
              <SettingsInputCompositeIcon sx={{fontSize: '82px'}}/>
            </HoverTile>
            <HoverTile title="Option IV" handleClick={handleClick}>
              <WidgetsIcon sx={{fontSize: '82px'}}/>
            </HoverTile>
          </Stack>
        </Container>
    
      </React.Fragment>
  );
}

export default function IntegrationNotistack() {
  return (
    <SnackbarProvider maxSnack={4}>
      <MyApp />
    </SnackbarProvider>
  );
}