How to override default location of snackbar notification DropZoneArea - reactjs

I'm trying to change the default location of the snackbar in material ui DropZone to be at the bottom center.
The default location for the snackbar notification in vertical origin is Bottom and in the horizontal origin is Left.
Any suggestions or thoughts would be helpful.
import React from "react";
import { DropzoneArea } from "material-ui-dropzone";
import { makeStyles } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
dropZoneContainer: {
width: "100%",
minHeight: "0",
},
}));
const DropZone = ({ text, onChange, error }) => {
const classes = useStyles();
const SUPPORTED_FORMATS = [
"image/jpg",
"image/jpeg",
"image/gif",
"image/png",
];
return (
<React.Fragment>
<DropzoneArea
acceptedFiles={SUPPORTED_FORMATS}
maxFileSize={2000000}
useChipsForPreview
filesLimit={1}
dropzoneText={text}
onChange={onChange}
classes={{ root: classes.dropZoneContainer }}
/>
<label style={{ color: "black", fontSize: "0.9rem" }}>
Max size allowed is 2 MB
</label>
<small
className="form-text text-danger"
style={{ color: "red", fontSize: "0.8rem", fontWeight: "bold" }}
>
{error}
</small>
</React.Fragment>
);
};
export default DropZone;

You can use alertSnackbarProps to pass props to the SnackBar withinDropzoneArea.
Use the anchorOrigin prop to position Snackbar
like
<DropzoneArea
acceptedFiles={SUPPORTED_FORMATS}
maxFileSize={2000000}
useChipsForPreview
filesLimit={1}
dropzoneText={text}
onChange={onChange}
classes={{ root: classes.dropZoneContainer }}
alertSnackbarProps={{anchorOrigin:{ vertical: 'bottom', horizontal: 'center' }}}
/>

Related

Make material ui SwipeableDrawer draggable even on desktop

I added swipeable drawer based on the documentation:
Swipeable You can make the drawer swipeable with the SwipeableDrawer
component.
This component comes with a 2 kB gzipped payload overhead. Some
low-end mobile devices won't be able to follow the fingers at 60 FPS.
You can use the disableBackdropTransition prop to help.
{(['left', 'right', 'top', 'bottom'] as const).map((anchor) => (
<React.Fragment key={anchor}>
<Button onClick={toggleDrawer(anchor, true)}>{anchor}</Button>
<SwipeableDrawer
anchor={anchor}
open={state[anchor]}
onClose={toggleDrawer(anchor, false)}
onOpen={toggleDrawer(anchor, true)}
>
{list(anchor)}
</SwipeableDrawer>
</React.Fragment>
))}
The problem with this is that it's only draggable on mobile device. Is it possible to make it draggable on desktop?
Like the user clicks on the edge with the cursor and drags the drawer to close or open it.
Especially, by adding an edge that the user can click on with the cursor:
Swipeable edge You can configure the SwipeableDrawer to have a visible
edge when closed.
If you are on a desktop, you can toggle the drawer with the "OPEN"
button. If you are on mobile, you can open the demo in CodeSandbox
("edit" icon) and swipe.
import * as React from 'react';
import PropTypes from 'prop-types';
import { Global } from '#emotion/react';
import { styled } from '#mui/material/styles';
import CssBaseline from '#mui/material/CssBaseline';
import { grey } from '#mui/material/colors';
import Button from '#mui/material/Button';
import Box from '#mui/material/Box';
import Skeleton from '#mui/material/Skeleton';
import Typography from '#mui/material/Typography';
import SwipeableDrawer from '#mui/material/SwipeableDrawer';
const drawerBleeding = 56;
const Root = styled('div')(({ theme }) => ({
height: '100%',
backgroundColor:
theme.palette.mode === 'light' ? grey[100] : theme.palette.background.default,
}));
const StyledBox = styled(Box)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'light' ? '#fff' : grey[800],
}));
const Puller = styled(Box)(({ theme }) => ({
width: 30,
height: 6,
backgroundColor: theme.palette.mode === 'light' ? grey[300] : grey[900],
borderRadius: 3,
position: 'absolute',
top: 8,
left: 'calc(50% - 15px)',
}));
function SwipeableEdgeDrawer(props) {
const { window } = props;
const [open, setOpen] = React.useState(false);
const toggleDrawer = (newOpen) => () => {
setOpen(newOpen);
};
// This is used only for the example
const container = window !== undefined ? () => window().document.body : undefined;
return (
<Root>
<CssBaseline />
<Global
styles={{
'.MuiDrawer-root > .MuiPaper-root': {
height: `calc(50% - ${drawerBleeding}px)`,
overflow: 'visible',
},
}}
/>
<Box sx={{ textAlign: 'center', pt: 1 }}>
<Button onClick={toggleDrawer(true)}>Open</Button>
</Box>
<SwipeableDrawer
container={container}
anchor="bottom"
open={open}
onClose={toggleDrawer(false)}
onOpen={toggleDrawer(true)}
swipeAreaWidth={drawerBleeding}
disableSwipeToOpen={false}
ModalProps={{
keepMounted: true,
}}
>
<StyledBox
sx={{
position: 'absolute',
top: -drawerBleeding,
borderTopLeftRadius: 8,
borderTopRightRadius: 8,
visibility: 'visible',
right: 0,
left: 0,
}}
>
<Puller />
<Typography sx={{ p: 2, color: 'text.secondary' }}>51 results</Typography>
</StyledBox>
<StyledBox
sx={{
px: 2,
pb: 2,
height: '100%',
overflow: 'auto',
}}
>
<Skeleton variant="rectangular" height="100%" />
</StyledBox>
</SwipeableDrawer>
</Root>
);
}
SwipeableEdgeDrawer.propTypes = {
/**
* Injected by the documentation to work in an iframe.
* You won't need it on your project.
*/
window: PropTypes.func,
};
export default SwipeableEdgeDrawer;

Materail UI TypeError: event.target.getAttribute is not a function

I am making a form in React using Material UI and displaying the form data in a table on client side, the problem is when I Select language by the select dropdown then I get an error of TypeError: event.target.getAttribute is not a function.
Although This language data is not displayed in the table but I need it, it needs to be stored in the database(which currently I have not implemented)
I have referred Material UI select throws event.target.getAttribute is not a function and also this github issue but it did not worked for me.
Currently I am not using any state management tool like redux, I am passing down props from my App component.
Please help me as in where am I going wrong
App.js
import Projects from './components/Projects';
import FormModal from './components/FormModal'
import Sidebar from './components/Sidebar';
import { useState } from 'react';
import {nanoid} from 'nanoid'
import DeleteModal from './components/DeleteModal';
function App() {
const [formDatas,setFormDatas] = useState(
[
{
projectName: 'Test',
projectId: nanoid(),
nameSpace: 'John Doe'
},
])
// Show Table State
const [showTable, setShowTable] = useState(false)
// HOOKS FORM MODAL
const [addFormData, setAddFormData] = useState({
projectName: '',
projectDescription: '',
nameSpace: '',
language: ''
})
const handleAddFormChange = (event) => {
event.preventDefault()
const fieldName = event.target.getAttribute('name')
console.log(fieldName)
const fieldValue = event.target.value
const newFormData = {...addFormData}
newFormData[fieldName] = fieldValue
setAddFormData(newFormData)
}
// FORM SUBMIT HANDLER
const handleAddFormSubmit = (event) => {
event.preventDefault()
const newProject = {
projectId: nanoid(),
projectName: addFormData.projectName,
projectDescription: addFormData.projectDescription,
nameSpace: addFormData.nameSpace,
language: addFormData.language
}
// Copy all the previous formDatas and add newProject Data
const newProjects = [...formDatas, newProject ]
setFormDatas(newProjects)
// console.log(newProject)
// Clear Form Input Fields after Submitting
setAddFormData({
projectName: '',
projectDescription: '',
nameSpace: '',
language: ''
})
// After Submitting close Form Modal
handleClose()
}
// Delete Handler
const deleteModalHandler = (addFormData) => {
console.log(addFormData.projectId)
}
// MODAL OPEN CLOSE STATE
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
return (
<>
<Sidebar showTable = {showTable} setShowTable = {setShowTable}/>
<FormModal addFormData = {addFormData}
handleAddFormChange = {handleAddFormChange}
handleAddFormSubmit = {handleAddFormSubmit}
open = {open}
handleOpen = {handleOpen}
handleClose = {handleClose}/>
<Projects
formDatas = {formDatas}
addFormData = {addFormData}
deleteModalHandler={deleteModalHandler}
showTable = {showTable}
setShowTable = {setShowTable}/>
</>
);
}
export default App;
FormModal.js
import * as React from 'react';
import Box from '#mui/material/Box';
import Button from '#mui/material/Button';
import { TextField } from "#mui/material";
import Modal from '#mui/material/Modal';
import InputLabel from '#mui/material/InputLabel';
import MenuItem from '#mui/material/MenuItem';
import Select from '#mui/material/Select';
import { useState } from 'react';
import SearchIcon from '#mui/icons-material/Search';
import { InputAdornment } from '#mui/material';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
export default function FormModal({handleAddFormChange, addFormData,handleAddFormSubmit,open,handleOpen,handleClose}) {
return (
<div>
<Box sx = {{display: 'flex', justifyContent: 'flex-end',alignItems: 'flex-end', flexDirection: 'column'}}>
<Button sx = {{ marginTop: '5%', marginRight: '4%', borderRadius: '10px '}} variant="contained" onClick={handleOpen}>Create project + </Button>
{/* <input style = {{marginTop: '2.5%', marginRight: '5%', padding: '5px'}} type="text" placeholder = "Search..." /> */}
<TextField sx = {{marginTop: '2%', marginRight: '4%', padding: '5px'}} placeholder = "Search..." InputProps={{
endAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
}}/>
</Box>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<div style = {{height: '5vh', display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<h3>Create New Project</h3>
</div>
<form onSubmit = {handleAddFormSubmit}>
<TextField
id="outlined-basic"
label="Project Name"
name = "projectName"
variant="outlined"
fullWidth= {true}
required = {true}
margin ="normal"
value={addFormData.projectName}
onChange={handleAddFormChange}
/>
<TextField
id="outlined-basic"
label="Project Description"
name = "projectDescription"
variant="outlined"
fullWidth = {true}
required = {true}
multiline
rows = {5}
margin ="normal"
value={addFormData.projectDescription}
onChange={handleAddFormChange}
/>
<TextField
id="outlined-basic"
label="Name Space"
name = "nameSpace"
variant="outlined"
fullWidth= {true}
required = {true}
autoComplete = {Math.random().toString()}
margin = "normal"
value={addFormData.nameSpace}
onChange={handleAddFormChange}
/>
<InputLabel id="demo-simple-select-label">Select Language</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
name = "name"
value={addFormData.language}
onChange={handleAddFormChange}
style = {{width: '100%'}}
>
<MenuItem value="english">English</MenuItem>
</Select>
<br />
<div style = {{display: 'flex', alignItems: 'center', justifyContent: 'space-evenly', marginTop: '7%'}}>
<Button style = {{width: '40%'}} variant = "contained" type="submit">Submit</Button>
<Button style = {{width: '40%'}} variant = "contained" onClick = {handleClose}>Cancel</Button>
</div>
</form>
</Box>
</Modal>
</div>
);
}
Projects.js
import React from "react";
import EditModal from "./EditModal";
import DeleteModal from "./DeleteModal";
import { styled } from "#mui/material/styles";
import Table from "#mui/material/Table";
import TableBody from "#mui/material/TableBody";
import TableCell, { tableCellClasses } from "#mui/material/TableCell";
import TableContainer from "#mui/material/TableContainer";
import TableHead from "#mui/material/TableHead";
import TableRow from "#mui/material/TableRow";
import { useState } from "react";
const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
// backgroundColor: theme.palette.common.black,
backgroundColor: "#1976D2",
color: theme.palette.common.white,
},
[`&.${tableCellClasses.body}`]: {
fontSize: 14,
},
}));
const StyledTableRow = styled(TableRow)(({ theme }) => ({
"&:nth-of-type(odd)": {
backgroundColor: theme.palette.action.hover,
},
// hide last border
"&:last-child td, &:last-child th": {
border: 0,
},
}));
const Projects = ({ showTable, setShowTable,addFormData, formDatas,deleteModalHandler}) => {
//const [showTable, setShowTable] = useState(true
return (
<div style={{ display: "flex", alignItems: "center", marginTop: "7%" }}>
{showTable ? <TableContainer > {/*component={Paper}*/}
<Table sx={{ width: '50%', marginLeft: 'auto', marginRight: 'auto' }} aria-label="customized table">
<TableHead>
<TableRow>
<StyledTableCell align="left">Project Name</StyledTableCell>
<StyledTableCell align="left">Project Id</StyledTableCell>
<StyledTableCell align="left">Created By</StyledTableCell>
<StyledTableCell align="center">Operations</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{formDatas.map((formData) => (
<StyledTableRow key = {formData.projectId}>
<StyledTableCell align="left" component="th" scope="row">
{formData.projectName}
</StyledTableCell>
<StyledTableCell align="left">
{formData.projectId}
</StyledTableCell>
<StyledTableCell align="left">
{formData.nameSpace}
</StyledTableCell>
<StyledTableCell align="center">
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-evenly",
}}
>
<EditModal />
<DeleteModal deleteModalHandler = {deleteModalHandler}/>
</div>
</StyledTableCell>
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>: null}
</div>
);
};
export default Projects;
As mentioned #Pradip Dhakal in the comment <Select> only return the {name: '', value: ''} as a target object, this is causing the issue. There is no other objects.
So I used Material UI Native Select Component and it solved the problem
The only code that I changed in FormModal.js file is below.
<NativeSelect
// defaultValue={30}
value={addFormData.language}
onChange={handleAddFormChange}
inputProps={{
name: 'language',
id: 'uncontrolled-native',
}}
>
<option value = "" disabled>Select</option>
<option value={'english'}>English</option>
<option value={'german'}>German</option>
</NativeSelect>
This is the minimal code that I've try, and it's working fine in my end.
material UI version: "#material-ui/core": "^4.11.0",
// FormModal.js
import React from 'react';
import { TextField } from "#material-ui/core"
export const FormModal = ({ handleAddFormChange }) => {
return (
<TextField
id="outlined-basic"
label="Project Name"
name="projectName"
variant="outlined"
fullWidth={true}
required={true}
margin="normal"
value=""
onChange={handleAddFormChange}
/>
);
}
// app.js
import React from 'react';
import { TextField } from "#material-ui/core"
import { FormModal } from "./FormModal"
const App = () => {
const handleAddFormChange = (event) => {
event.preventDefault()
const fieldName = event.target.getAttribute('name')
console.log("Name: ", fieldName)
}
return (
<FormModal handleAddFormChange={handleAddFormChange} />
);
}
Can you please try to breakdown your code, and start from the basic one.

How can I create a button to a dialog box inside the PopperComponent of Material UI Labs Autocomplete

I have a Material UI Autocomplete which renders a list of Chips. I have added a button at the bottom of the PopperComponent which when clicked should open a dialog box.
But the Autocomplete doesn't allow the DialogBox to be opened. But the weird part is if I add 'open' to Autocomplete it works.
I have tried adding the onMouseDown event instead of onClick. Also, tried the event.preventDefault(). None of them works. However onMouseDown definitely called my listener for the Dialog box and changed its open state to true, but the dialog box did not appear.
This is the link to the sandbox.
Sandbox to the code
This is the component that implements the Dialog Box.
import React, { useState } from "react";
import { withStyles } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import MuiDialogTitle from "#material-ui/core/DialogTitle";
import MuiDialogContent from "#material-ui/core/DialogContent";
import MuiDialogActions from "#material-ui/core/DialogActions";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import Typography from "#material-ui/core/Typography";
import { orange } from "#material-ui/core/colors";
const styles = theme => ({
form: {
display: "flex",
flexDirection: "column",
margin: "auto",
width: "fit-content"
},
formControl: {
marginTop: theme.spacing(2),
minWidth: 120
},
formControlLabel: {
marginTop: theme.spacing(1)
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500]
},
selectEmpty: {
marginTop: theme.spacing(2)
},
floatingLabelFocusStyle: {
color: "green"
},
separator: {
marginTop: theme.spacing(1)
},
menuStyle: {
border: "1px solid black",
borderRadius: "5%",
backgroundColor: "lightgrey"
}
});
const DialogTitle = withStyles(styles)(props => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={onClose}
>
<CloseIcon />
</IconButton>
) : null}{" "}
</MuiDialogTitle>
);
});
const DialogContent = withStyles(theme => ({
root: {
padding: theme.spacing(2)
}
}))(MuiDialogContent);
const DialogActions = withStyles(theme => ({
root: {
margin: 0,
padding: theme.spacing(1)
}
}))(MuiDialogActions);
const ActionButton = withStyles(theme => ({
root: {
color: "#E87424",
backgroundColor: "white",
"&:hover": {
backgroundColor: orange[100]
}
}
}))(Button);
const ManageTagButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
const TagContainer = props => {
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
console.log("Dialog box clicked");
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<ManageTagButton
onMouseDown={event => {
event.preventDefault();
handleClickOpen();
}}
size="small"
>
MANAGE TAGS
</ManageTagButton>
<Dialog
fullWidth
maxWidth={"sm"}
onClose={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
>
<DialogTitle id="customized-dialog-title">Manage Tags</DialogTitle>
<DialogContent dividers>
<h1>
This is the component of the dialog box. In reality I neeed to
display a data table with CRUD operations to add more tags.
</h1>
</DialogContent>
<DialogActions>
<ActionButton autoFocus onClick={handleClose} color="secondary">
CLOSE
</ActionButton>
</DialogActions>
</Dialog>
</div>
);
};
export default TagContainer;
This is the component that implements the Autocomplete.
import React, { Fragment } from "react";
import Chip from "#material-ui/core/Chip";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { withStyles } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import Paper from "#material-ui/core/Paper";
import TagContainer from "./TagContainer";
const ListItemCustom = withStyles(theme => ({
gutters: {
paddingLeft: 0,
paddingRight: 0
},
secondaryAction: {
paddingRight: 0
}
}))(ListItem);
const AutocompleteCustom = withStyles(theme => ({
endAdornment: {
display: "none"
}
}))(Autocomplete);
const CreateButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
const MuiFilledInputCustom = makeStyles(
{
underline: {
"&&&:before": {
borderBottom: "none"
},
"&&:after": {
borderBottom: "none"
}
}
},
{ name: "MuiFilledInput" }
);
const loadCustomStyles = () => {
MuiFilledInputCustom();
};
export default function AddTagToThread() {
loadCustomStyles();
const handleSubmit = () => {
console.log("Add tags to thread");
};
const useStyles = makeStyles({
root: {
minWidth: 300,
width: 300,
height: 250,
minHeight: 250,
zIndex: 1
},
buttons: {
display: "flex",
justifyContent: "flex-end"
}
});
const PaperComponentCustom = options => {
const classes = useStyles();
const { containerProps, children } = options;
return (
<Paper className={classes.root} {...containerProps} square>
{children}
<div className={classes.buttons}>
<TagContainer />
</div>
</Paper>
);
};
return (
<List dense={false}>
<ListItemCustom>
<ListItemText>
<AutocompleteCustom
multiple
id="size-small-filled-multi"
size="medium"
options={tagList}
noOptionsText="No options"
freeSolo
filterSelectedOptions
PaperComponent={PaperComponentCustom}
getOptionLabel={option => option.name}
onChange={(event, value) => {
console.log(value);
}}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="default"
style={{
backgroundColor: option.color
}}
label={option.name}
size="medium"
{...getTagProps({ index })}
/>
))
}
renderOption={option => (
<Fragment>
<Chip
variant="default"
style={{
backgroundColor: option.color,
padding: "15px",
marginLeft: "12px"
}}
label={option.name}
size="medium"
/>
</Fragment>
)}
renderInput={params => (
<TextField
{...params}
variant="filled"
label="Filter By Tag"
placeholder="Select Tag"
/>
)}
/>
</ListItemText>
<ListItemSecondaryAction>
<CreateButton onClick={handleSubmit}>ADD TAG</CreateButton>
</ListItemSecondaryAction>
</ListItemCustom>
</List>
);
}
const tagList = [
{ name: "Follow Up", tagId: 1, color: "#FFC107" },
{ name: "Important", tagId: 2, color: "#46B978" },
{ name: "Idea", tagId: 3, color: "#EEA5F6" },
{ name: "Non Issue", tagId: 4, color: "#2EACE2" }
];
I have been stuck at this for last couple of days. Any help is greatly appreciated.
The issue with your code is that the <Dialog/> component is in the PaperComponentCustom component which gets unmounted after the option is selected.
<Paper className={classes.root} {...containerProps} square>
{children}
<ManageTagButton onMouseDown={handleClickOpen} fullWidth>
MANAGE TAGS
</ManageTagButton>
</Paper>
The solution to keep only the <ManageTagButton/> component in the PaperComponentCustom and move the <Dialog/> component one level up. I imagine that even if you have 10 elements in the <List/> you would still have only one <Dialog>, you cannot have 10 dialog components opened at once.
So therefore your <AddTagToThread/> component should render the dialog directly and the state of the dialog open and the handlers handleOpen and handleClose should be moved in the <AddTagToThread/> component also
Working codesandbox HERE, code below
Autocomplete component
import React, { Fragment, useState } from "react";
import Chip from "#material-ui/core/Chip";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { withStyles } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import Paper from "#material-ui/core/Paper";
import TagContainer from "./TagContainer";
const ListItemCustom = withStyles(theme => ({
gutters: {
paddingLeft: 0,
paddingRight: 0
},
secondaryAction: {
paddingRight: 0
}
}))(ListItem);
const AutocompleteCustom = withStyles(theme => ({
endAdornment: {
display: "none"
}
}))(Autocomplete);
const CreateButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
const MuiFilledInputCustom = makeStyles(
{
underline: {
"&&&:before": {
borderBottom: "none"
},
"&&:after": {
borderBottom: "none"
}
}
},
{ name: "MuiFilledInput" }
);
const loadCustomStyles = () => {
MuiFilledInputCustom();
};
const ManageTagButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
export default function AddTagToThread() {
loadCustomStyles();
const handleSubmit = () => {
console.log("Add tags to thread");
};
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
console.log("Dialog box clicked");
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const useStyles = makeStyles({
root: {
minWidth: 300,
width: 300,
height: 250,
minHeight: 250,
zIndex: 1
},
buttons: {
display: "flex",
justifyContent: "flex-end"
}
});
const PaperComponentCustom = options => {
const classes = useStyles();
const { containerProps, children } = options;
return (
<Paper className={classes.root} {...containerProps} square>
{children}
<ManageTagButton onMouseDown={handleClickOpen} fullWidth>
MANAGE TAGS
</ManageTagButton>
</Paper>
);
};
return (
<>
<TagContainer open={open} handleClose={handleClose} />
<List dense={false}>
<ListItemCustom>
<ListItemText>
<AutocompleteCustom
multiple
id="size-small-filled-multi"
size="medium"
options={tagList}
noOptionsText="No options"
freeSolo
filterSelectedOptions
PaperComponent={PaperComponentCustom}
getOptionLabel={option => option.name}
onChange={(event, value) => {
console.log(value);
}}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="default"
style={{
backgroundColor: option.color
}}
label={option.name}
size="medium"
{...getTagProps({ index })}
/>
))
}
renderOption={option => (
<Fragment>
<Chip
variant="default"
style={{
backgroundColor: option.color,
padding: "15px",
marginLeft: "12px"
}}
label={option.name}
size="medium"
/>
</Fragment>
)}
renderInput={params => (
<TextField
{...params}
variant="filled"
label="Filter By Tag"
placeholder="Select Tag"
/>
)}
/>
</ListItemText>
<ListItemSecondaryAction>
<CreateButton onClick={handleSubmit}>ADD TAG</CreateButton>
</ListItemSecondaryAction>
</ListItemCustom>
</List>
</>
);
}
const tagList = [
{ name: "Follow Up", tagId: 1, color: "#FFC107" },
{ name: "Important", tagId: 2, color: "#46B978" },
{ name: "Idea", tagId: 3, color: "#EEA5F6" },
{ name: "Non Issue", tagId: 4, color: "#2EACE2" }
];
Dialog component
import React, { useState } from "react";
import { withStyles } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import MuiDialogTitle from "#material-ui/core/DialogTitle";
import MuiDialogContent from "#material-ui/core/DialogContent";
import MuiDialogActions from "#material-ui/core/DialogActions";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import Typography from "#material-ui/core/Typography";
import { orange } from "#material-ui/core/colors";
const styles = theme => ({
form: {
display: "flex",
flexDirection: "column",
margin: "auto",
width: "fit-content"
},
formControl: {
marginTop: theme.spacing(2),
minWidth: 120
},
formControlLabel: {
marginTop: theme.spacing(1)
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500]
},
selectEmpty: {
marginTop: theme.spacing(2)
},
floatingLabelFocusStyle: {
color: "green"
},
separator: {
marginTop: theme.spacing(1)
},
menuStyle: {
border: "1px solid black",
borderRadius: "5%",
backgroundColor: "lightgrey"
}
});
const DialogTitle = withStyles(styles)(props => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={onClose}
>
<CloseIcon />
</IconButton>
) : null}{" "}
</MuiDialogTitle>
);
});
const DialogContent = withStyles(theme => ({
root: {
padding: theme.spacing(2)
}
}))(MuiDialogContent);
const DialogActions = withStyles(theme => ({
root: {
margin: 0,
padding: theme.spacing(1)
}
}))(MuiDialogActions);
const ActionButton = withStyles(theme => ({
root: {
color: "#E87424",
backgroundColor: "white",
"&:hover": {
backgroundColor: orange[100]
}
}
}))(Button);
const TagContainer = ({ open, handleClose }) => {
return (
<Dialog
fullWidth
maxWidth={"sm"}
onClose={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
>
<DialogTitle id="customized-dialog-title">Manage Tags</DialogTitle>
<DialogContent dividers>
<h1>
This is the component of the dialog box. In reality I neeed to display
a data table with CRUD operations to add more tags.
</h1>
</DialogContent>
<DialogActions>
<ActionButton autoFocus onClick={handleClose} color="secondary">
CLOSE
</ActionButton>
</DialogActions>
</Dialog>
);
};
export default TagContainer;

React PDF viewer component rerenders constantly

I am using a React PDF viewer in my project. I have a react mui dialog component that I use with react draggable to drag it around.
import React from "react";
import withStyles from "#material-ui/core/styles/withStyles";
import makeStyles from "#material-ui/core/styles/makeStyles";
import DialogContent from "#material-ui/core/DialogContent";
import IconButton from "#material-ui/core/IconButton";
import ClearIcon from "#material-ui/icons/Clear";
import Draggable from "react-draggable";
import Paper from "#material-ui/core/Paper";
import Dialog from "#material-ui/core/Dialog";
import PDFViewer from "./PDFViewer";
function PaperComponent({...props}) {
return (
<Draggable
>
<Paper {...props} />
</Draggable>
);
}
const StyledDialog = withStyles({
root: {
pointerEvents: "none"
},
paper: {
pointerEvents: "auto"
},
scrollPaper: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
marginRight: 20
}
})(props => <Dialog hideBackdrop {...props} />);
const useStyles = makeStyles({
dialog: {
cursor: 'move'
},
dialogContent: {
'&:first-child': {
padding: 10,
background: 'white'
}
},
clearIcon: {
position: 'absolute',
top: -20,
right: -20,
background: 'white',
zIndex: 1,
'&:hover': {
background: 'white'
}
},
paper: {
overflowY: 'visible',
maxWidth: 'none',
maxHeight: 'none',
width: 550,
height: 730
}
});
const PDFModal = (props) => {
const classes = useStyles();
const {open, onClose, pdfURL} = props;
return (
<StyledDialog
open={open}
classes={{root: classes.dialog, paper: classes.paper}}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog"
>
<DialogContent classes={{root: classes.dialogContent}} id="draggable-dialog">
<IconButton className={classes.clearIcon} aria-label="Clear" onClick={onClose}>
<ClearIcon/>
</IconButton>
<PDFViewer
url={pdfURL}
/>
</DialogContent>
</StyledDialog>
);
};
export default PDFModal;
And this is the PDFViewer component:
import React from 'react';
import { Viewer, SpecialZoomLevel, Worker } from '#react-pdf-viewer/core';
import { defaultLayoutPlugin } from '#react-pdf-viewer/default-layout';
import '#react-pdf-viewer/core/lib/styles/index.css';
import '#react-pdf-viewer/default-layout/lib/styles/index.css';
import ArrowForward from "#material-ui/icons/ArrowForward";
import ArrowBack from "#material-ui/icons/ArrowBack";
import Button from "#material-ui/core/Button";
import IconButton from "#material-ui/core/IconButton";
import RemoveCircleOutlineIcon from '#material-ui/icons/RemoveCircleOutline';
import AddCircleOutlineIcon from '#material-ui/icons/AddCircleOutline';
import './PDFViewer.css';
const PDFViewer = ({url}) => {
const renderToolbar = (Toolbar) => (
<Toolbar>
{
(slots) => {
const {
CurrentPageLabel, CurrentScale, GoToNextPage, GoToPreviousPage, ZoomIn, ZoomOut,
} = slots;
return (
<div
style={{
alignItems: 'center',
display: 'flex',
}}
>
<div style={{ padding: '0px 2px' }}>
<ZoomOut>
{
(props) => (
<IconButton aria-label="delete" onClick={props.onClick}>
<RemoveCircleOutlineIcon />
</IconButton>
)
}
</ZoomOut>
</div>
<div style={{ padding: '0px 2px' }}>
<CurrentScale>
{
(props) => (
<span>{`${Math.round(props.scale * 100)}%`}</span>
)
}
</CurrentScale>
</div>
<div style={{ padding: '0px 2px' }}>
<ZoomIn>
{
(props) => (
<IconButton aria-label="delete" onClick={props.onClick}>
<AddCircleOutlineIcon />
</IconButton>
)
}
</ZoomIn>
</div>
<div style={{ padding: '0px 2px', marginLeft: 'auto' }}>
<GoToPreviousPage>
{
(props) => (
<Button
style={{
cursor: props.isDisabled ? 'not-allowed' : 'pointer',
height: '30px',
width: '30px'
}}
disabled={props.isDisabled}
disableElevation
disableFocusRipple
onClick={props.onClick}
variant="outlined">
<ArrowBack fontSize="small"/>
</Button>
)
}
</GoToPreviousPage>
</div>
<div style={{ padding: '0px 2px' }}>
<CurrentPageLabel>
{
(props) => (
<span>{`${props.currentPage + 1} av ${props.numberOfPages}`}</span>
)
}
</CurrentPageLabel>
</div>
<div style={{ padding: '0px 2px' }}>
<GoToNextPage>
{
(props) => (
<Button
style={{
cursor: props.isDisabled ? 'not-allowed' : 'pointer',
height: '30px',
width: '30px'
}}
disabled={props.isDisabled}
disableElevation
disableFocusRipple
onClick={props.onClick}
variant="outlined">
<ArrowForward fontSize="small"/>
</Button>
)
}
</GoToNextPage>
</div>
</div>
)
}
}
</Toolbar>
);
const defaultLayoutPluginInstance = defaultLayoutPlugin({
renderToolbar,
sidebarTabs: defaultTabs => [defaultTabs[1]]
});
// constantly called
console.log('entered')
return (
<div
style={{
height: '100%',
}}
>
<Worker workerUrl="https://unpkg.com/pdfjs-dist#2.5.207/build/pdf.worker.min.js">
<Viewer
fileUrl={url}
defaultScale={SpecialZoomLevel.PageFit}
plugins={[
defaultLayoutPluginInstance
]}
/>
</Worker>
</div>
);
};
export default PDFViewer;
I can see in the console that PDFViewer is being constantly called. I am not sure what is causing this rerenders the whole time?
Isn't it make sense to re-render when you have a new fileUrl passed to PDFModal? The following sequence should be how the app is executed.
PDFModal, PDFViewer and other related components init
When a file is dragged into the PaperComponent context, the upper level component handles it and passing pdfURL as props
const PDFModal = (props) => {
const { ......., pdfURL } = props;
//...skipped code
return (
<StyledDialog
PaperComponent={PaperComponent}
>
//...skipped code
<PDFViewer
url={pdfURL}
/>
</StyledDialog>
);
};
PDFViewer updated because there is a new prop.
const PDFViewer = ({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
);
}
I agree what #LindaPaiste said, putting Toolbar maybe an option since it doesn't use the url props passed in. For the re-render problem, I suggest that useCallback can be used to wrap the whole PDFViewer component. Only update the component when the url has changed.
This link provide some insights on when to use useCallback which can be a reference.
const PDFViewer = useCallback(
({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
)
}, [url])

How to style MUI Tooltip?

How can I style MUI Tooltip text? The default tooltip on hover comes out black with no text-wrap. Is it possible to change the background, color etc? Is this option even available?
The other popular answer (by André Junges) on this question is for the 0.x versions of Material-UI. Below I've copied in my answer from Material UI's Tooltip - Customization Style which addresses this for v3 and v4. Further down, I have added a version of the example using v5.
Below are examples of how to override all tooltips via the theme, or to just customize a single tooltip using withStyles (two different examples). The second approach could also be used to create a custom tooltip component that you could reuse without forcing it to be used globally.
import React from "react";
import ReactDOM from "react-dom";
import {
createMuiTheme,
MuiThemeProvider,
withStyles
} from "#material-ui/core/styles";
import Tooltip from "#material-ui/core/Tooltip";
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
overrides: {
MuiTooltip: {
tooltip: {
fontSize: "2em",
color: "yellow",
backgroundColor: "red"
}
}
}
});
const BlueOnGreenTooltip = withStyles({
tooltip: {
color: "lightblue",
backgroundColor: "green"
}
})(Tooltip);
const TextOnlyTooltip = withStyles({
tooltip: {
color: "black",
backgroundColor: "transparent"
}
})(Tooltip);
function App(props) {
return (
<MuiThemeProvider theme={defaultTheme}>
<div className="App">
<MuiThemeProvider theme={theme}>
<Tooltip title="This tooltip is customized via overrides in the theme">
<div style={{ marginBottom: "20px" }}>
Hover to see tooltip customized via theme
</div>
</Tooltip>
</MuiThemeProvider>
<BlueOnGreenTooltip title="This tooltip is customized via withStyles">
<div style={{ marginBottom: "20px" }}>
Hover to see blue-on-green tooltip customized via withStyles
</div>
</BlueOnGreenTooltip>
<TextOnlyTooltip title="This tooltip is customized via withStyles">
<div>Hover to see text-only tooltip customized via withStyles</div>
</TextOnlyTooltip>
</div>
</MuiThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here is documentation on tooltip CSS classes available to control different aspects of tooltip behavior: https://material-ui.com/api/tooltip/#css
Here is documentation on overriding these classes in the theme: https://material-ui.com/customization/components/#global-theme-override
Here is a similar example, but updated to work with v5 of Material-UI (pay attention that it works in 5.0.3 and upper versions after some fixes). It includes customization via the theme, customization using styled, and customization using the sx prop. All of these customizations target the "tooltip slot" so that the CSS is applied to the element that controls the visual look of the tooltip.
import React from "react";
import ReactDOM from "react-dom";
import { createTheme, ThemeProvider, styled } from "#mui/material/styles";
import Tooltip from "#mui/material/Tooltip";
const defaultTheme = createTheme();
const theme = createTheme({
components: {
MuiTooltip: {
styleOverrides: {
tooltip: {
fontSize: "2em",
color: "yellow",
backgroundColor: "red"
}
}
}
}
});
const BlueOnGreenTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} componentsProps={{ tooltip: { className: className } }} />
))(`
color: lightblue;
background-color: green;
font-size: 1.5em;
`);
const TextOnlyTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} componentsProps={{ tooltip: { className: className } }} />
))(`
color: black;
background-color: transparent;
`);
function App(props) {
return (
<ThemeProvider theme={defaultTheme}>
<div className="App">
<ThemeProvider theme={theme}>
<Tooltip title="This tooltip is customized via overrides in the theme">
<div style={{ marginBottom: "20px" }}>
Hover to see tooltip customized via theme
</div>
</Tooltip>
</ThemeProvider>
<BlueOnGreenTooltip title="This tooltip is customized via styled">
<div style={{ marginBottom: "20px" }}>
Hover to see blue-on-green tooltip customized via styled
</div>
</BlueOnGreenTooltip>
<TextOnlyTooltip title="This tooltip is customized via styled">
<div style={{ marginBottom: "20px" }}>
Hover to see text-only tooltip customized via styled
</div>
</TextOnlyTooltip>
<Tooltip
title="This tooltip is customized via the sx prop"
componentsProps={{
tooltip: {
sx: {
color: "purple",
backgroundColor: "lightblue",
fontSize: "2em"
}
}
}}
>
<div>
Hover to see purple-on-blue tooltip customized via the sx prop
</div>
</Tooltip>
</div>
</ThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Documentation on changes to the theme structure between v4 and v5: https://mui.com/guides/migration-v4/#theme
Tooltip customization examples in the Material-UI documentation: https://mui.com/components/tooltips/#customization
MUI v5 Update
You can customize the Tooltip by overriding the styles in the tooltip slot. There are 3 ways to do that in v5. For reference, see the customization section of Tooltip. More examples of sx prop and createTheme can be seen here and here.
styled()
const ToBeStyledTooltip = ({ className, ...props }) => (
<Tooltip {...props} classes={{ tooltip: className }} />
);
const StyledTooltip = styled(ToBeStyledTooltip)(({ theme }) => ({
backgroundColor: '#f5f5f9',
color: 'rgba(0, 0, 0, 0.87)',
border: '1px solid #dadde9',
}));
sx prop
<Tooltip
title="Add"
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: 'common.black',
'& .MuiTooltip-arrow': {
color: 'common.black',
},
},
},
}}
>
<Button>SX</Button>
</Tooltip>
createTheme + ThemeProvider
const theme = createTheme({
components: {
MuiTooltip: {
styleOverrides: {
tooltip: {
backgroundColor: 'pink',
color: 'red',
border: '1px solid #dadde9',
},
},
},
},
});
If you want to change text color , font-size ... of Tooltip there is a simple way.
You can insert a Tag inside Title of Martial Ui Tooltip for example :
<Tooltip title={<span>YourText</span>}>
<Button>Grow</Button>
</Tooltip>
then you can style your tag anyhow you want.
check below Example :
This answer is out of date. This answer was written in 2016 for the 0.x versions of Material-UI. Please see this answer for an approach that works with versions 3 and 4.
well, you can change the text color and the element background customizing the mui theme.
color - is the text color
rippleBackgroundColor - is the tooltip bbackground
Example: Using IconButton - but you could you the Tooltip directly..
import React from 'react';
import IconButton from 'material-ui/IconButton';
import MuiThemeProvider from 'material-ui/lib/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme';
const muiTheme = getMuiTheme({
tooltip: {
color: '#f1f1f1',
rippleBackgroundColor: 'blue'
},
});
const Example = () => (
<div>
<MuiThemeProvider muiTheme={muiTheme}>
<IconButton iconClassName="muidocs-icon-custom-github" tooltip="test" />
</MuiThemeProvider>
</div>
);
You can also pass a style object for the Tooltip (in IconButton it's tooltipStyles) - but these styles will only be applied for the root element.
It's not possible yet to change the label style to make it wrap in multiple lines.
I ran into this issue as well, and want for anyone seeking to simply change the color of their tooltip to see this solution that worked for me:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Tooltip from '#material-ui/core/Tooltip';
import Button from '#material-ui/core/Button';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles(theme => ({
customTooltip: {
// I used the rgba color for the standard "secondary" color
backgroundColor: 'rgba(220, 0, 78, 0.8)',
},
customArrow: {
color: 'rgba(220, 0, 78, 0.8)',
},
}));
export default TooltipExample = () => {
const classes = useStyles();
return (
<>
<Tooltip
classes={{
tooltip: classes.customTooltip,
arrow: classes.customArrow
}}
title="Delete"
arrow
>
<Button color="secondary"><DeleteIcon /></Button>
</Tooltip>
</>
);
};
MUI v5 custom component
Building on NearHuscarl's answer using sx, the simplest approach for me was to create a custom component to include the styling plus any other properties you want repeated on each tooltip.
For example, the component could display the tooltips on the bottom with an arrow and a larger font size:
const StyledTooltip = ({ title, children, ...props }) => (
<Tooltip
{...props}
title={title}
placement="bottom"
arrow
componentsProps={{
tooltip: {
sx: {
fontSize: '1.125rem',
},
},
}}
>
{children}
</Tooltip>
);
const Buttons = () => (
<div>
<StyledTooltip title="This is one">
<Button>One</Button>
</StyledTooltip>
<StyledTooltip title="This is two">
<Button>Two</Button>
</StyledTooltip>
</div>
);
Another solution with HtmlTooltip
I Use HtmlTooltip and add arrow: {color: '#f5f5f9',}, for the arrow tooltip style.
And much more to the tooltip style itself.
So I use ValueLabelComponent to control the label and put there a Tooltip from MaterialUI.
Hopes it give another way to edit MaterialUI Tooltip :)
const HtmlTooltip = withStyles((theme) => ({
tooltip: {
backgroundColor: 'var(--blue)',
color: 'white',
maxWidth: 220,
fontSize: theme.typography.pxToRem(12),
border: '1px solid #dadde9',
},
arrow: {
color: '#f5f5f9',
},
}))(Tooltip);
function ValueLabelComponent({ children, open, value }) {
return (
<HtmlTooltip arrow open={open} enterTouchDelay={0} placement="top" title={value}>
{children}
</HtmlTooltip>
);
}
...
...
return (
<div className={classes.root}>
<Slider
value={value}
onChange={handleChange}
onChangeCommitted={handleChangeCommitted}
scale={(x) => convertRangeValueToOriginalValue(x, minMaxObj)}
valueLabelDisplay="auto"
valueLabelFormat={(x) => '$' + x}
ValueLabelComponent={ValueLabelComponent}
aria-labelledby="range-slider"
/>
</div>
);
I used makeStyles() and ended with that:
import React from 'react';
import Grid from '#mui/material/Grid';
import Typography from '#mui/material/Typography';
import Tooltip from '#mui/material/Tooltip';
import InfoOutlinedIcon from '#mui/icons-material/InfoOutlined';
import { makeStyles } from '#material-ui/core/styles';
const styles = makeStyles({
tooltip: {
backgroundColor: '#FFFFFF',
color: '#000000',
border: '.5px solid #999999',
fontSize: '.85rem',
fontWeight: '400'
}
});
const HeaderTooltip = ({ header, tooltip }) =>
<Grid container direction="row" alignItems="center" spacing={1}>
<Grid item>
<Typography variant='h5'>{header}</Typography>
</Grid>
<Grid item>
<Tooltip title={tooltip} classes={{ tooltip: styles().tooltip }}>
<InfoOutlinedIcon />
</Tooltip>
</Grid>
</Grid>
export default HeaderTooltip;
With styledComponent and MUI V5
import styled from 'styled-components';
....
....
<StyledTooltip title={tooltip}>
<IconTextStyle>
{icon}
<Label>{label}</Label>
</IconTextStyle>
</StyledTooltip>
const StyledTooltip = styled((props) => (
<Tooltip classes={{ popper: props.className }} {...props} />
))`
& .MuiTooltip-tooltip {
display: flex;
background-color: #191c28;
border-radius: 4px;
box-shadow: 0px 0px 24px #00000034;
}
`;
I'm created custom Tooltip in the following way
import React from 'react'
import Tooltip from '#material-ui/core/Tooltip'
import ErrorOutlineOutlinedIcon from '#material-ui/icons/ErrorOutlineOutlined'
import {
makeStyles,
createStyles,
withStyles,
} from '#material-ui/core/styles'
import Typography from '#material-ui/core/Typography'
import { Divider, Link, Paper } from '#material-ui/core'
const HtmlTooltip = withStyles(theme => ({
arrow: {
'&::before': {
color: 'white'
}
},
tooltip: {
backgroundColor: '#f5f5f9',
boxShadow: theme.shadows[8],
color: 'rgba(0, 0, 0, 0.87)',
fontSize: 14,
maxWidth: 800,
padding: 0,
},
tooltipPlacementTop: {
margin: '4px 0',
},
}))(Tooltip)
const imageStyles = { root: { color: 'deeppink', height: 20, marginBottom: 0, width: 20 } }
const Image = withStyles(imageStyles)(({ classes }) => (
<ErrorOutlineOutlinedIcon classes={classes} />
))
const useStyles = makeStyles(theme =>
createStyles({
content: {
border: `1px solid ${theme.palette.grey[300]}`,
margin: 0,
minWidth: 600,
padding: 0,
zIndex: 1,
},
contentInner: {
padding: theme.spacing(1)
},
header: {
backgroundColor: 'deeppink',
fontWeight: 'bold',
padding: theme.spacing(1),
}
})
)
export default function CustomTooltip(params) {
const classes = useStyles()
const labelDisplay = params.content
const textDispaly = params.text
return (
<>
{labelDisplay && labelDisplay.length > 20 ? (<HtmlTooltip arrow interactive title={
<Paper className={classes.content}>
<div className={classes.header}>
<Typography color='inherit' variant='body1' style={{color: 'white', fontSize: '20px'}}>
{params.title}
</Typography>
</div>
<Divider />
<div className={classes.contentInner}>
{textDispaly}
</div>
</Paper>}
placement='top'
>
<div style={{ alignItems: 'center', display: 'flex', fontSize: '12px', justifyContent: 'space-between' }}>
{labelDisplay}<Image/>
</div>
</HtmlTooltip>) : (labelDisplay)}
</>
)
}

Resources