Change component prop through css hover in react-materialui - javascript

I am trying to change the noWrap property of a Typography element upon hover. I have declared a custom CSS class for the parent element and the hover does work. But I have no idea how to alter the noWrap property through CSS now.
I have tried this (the hover works):
const useStyles = makeStyles((theme) => ({
paper: {
padding: theme.spacing(2),
"&:hover .questionText": {
noWrap: true
}
}
}));
And my JSX:
return(
<Paper className={classes.paper}>
<Typography className="questionText" noWrap={false} gutterBottom variant="body2">test</Typography>
</Paper>);
Thanks for your help

I'd toggle the boolean flag for your noWrap attribute via setState (or state hooks) using a js mouseover. Something like -
const [ wrap, setWrap ] = useState(false);
function toggleWrap() {
setWrap(!wrap);
}
return(
<Paper ...>
<Typography noWrap={wrap} onMouseOver={()=>toggleWrap()} ... />
</Paper>
);

Setting noWrap={true} props in Typography will apply white-space: nowrap styles to your component. This is how you do it using jss:
const useStyles = makeStyles((theme) => ({
paper: {
padding: theme.spacing(2),
"&:hover .questionText": {
whiteSpace: "nowrap",
}
}
}));
Live Demo

Thanks to Ozrix, I have solved my problem with the following:
const [wrap, setWrap] = useState(false);
and
<Paper className={classes.paper} onMouseEnter={() => {setWrap(true)}} onMouseLeave={() => {setWrap(false)}}>
<Typography noWrap={wrap} gutterBottom variant="body2">
</Paper>

Related

change color depending on value with javascript

I'm using React and want to change text color depends on the value.
The code looks like this:
const ProductCard = (props) => {
const classes = useStyles();
useEffect(() => {
const category = document.getElementById('category');
if(props.category === "youtube"){
category.style.color="#DC143C";
}
if(props.category === "blog"){
category.style.color="#00FFFF";
}
if(props.category === "instagram"){
category.style.color="#FF88FF";
}
if(props.category === "twitter"){
category.style.color="#3366FF";
}
}, []);
return (
<Card className={classes.root}>
<CardContent className={classes.content}>
<Typography id="category" className={classes.category} component="p">
{props.category}
</Typography>
</CardContent>
</Card>
)
}
export default ProductCard
With this code, only the first value of the element is changed, the rest are not.
What I'm doing wrong?
your code only runs on mount with empty array dependency, hence any change on props won't be reflected. that's the most likely the problem here.
fwiw your code is rather complicated and it's better to avoid manipulating the DOM directly, it would much simpler if you create a dictionary to apply your style to your element like:
const colors = {
youtube: "#DC143C",
blog: "#00FFFF",
instagram: "#FF88FF",
twitter: "#3366FF",
}
const ProductCard = ({ category }) => {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardContent className={classes.content}>
<Typography id="category" style={{ color: colors[category] }} className={classes.category} component="p">
{category}
</Typography>
</CardContent>
</Card>
)
}
export default ProductCard
First - you should avoid querying dom inside react app. You can create state for holding your class or styles and then pass it to component.
Second - remove empty array from useEffect it should help.
When you get an element by id, only one element is returned.
const category = document.getElementById('category'); // referring to this line
That's because technically, ids should be unique. Only one element should have the id category on the page. So when you set the style on container, only one element is changed because it is only one element.
Additionally, ids are not scoped to a specific component. So if you have multiple ProductCard components, getElementById will always return the category of the first ProductCard component.
Solutions
I'm not familiar with your exact components, so not all of these will work for you. But at least one should.
Use a color prop
If your Typography component accepts a color or style prop, use that. Then, you're telling React "this specific component should have this color".
const colors = {
youtube: "#DC143C",
blog: "#00FFFF",
instagram: "#FF88FF",
twitter: "#3366FF",
}
const ProductCard = (props) => {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardContent className={classes.content}>
<Typography id="category" className={classes.category} component="p" style={{ color: colors[props.category] }}>
{props.category}
</Typography>
</CardContent>
</Card>
)
}
export default ProductCard
Use a wrapper component
You may be able to wrap a div around just the typography and set the text color that way. Not the best option, but it will work.
const colors = {
youtube: "#DC143C",
blog: "#00FFFF",
instagram: "#FF88FF",
twitter: "#3366FF",
}
const ProductCard = (props) => {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardContent className={classes.content}>
<div style={{ color: colors[props.category] }}>
<Typography id="category" className={classes.category} component="p" style={{ color: colors[props.category] }}>
{props.category}
</Typography>
</div>
</CardContent>
</Card>
)
}
export default ProductCard

How to customize the font size of an active tab in material-ui

My Requirement is such that only the active tab should have a specific color and font-size.
This is my code:
<Tabs
value={value}
onChange={handleChange}
classes={{indicator: classes.customStyleOnActiveTab}}
aria-label="some text"
>
<Tab label={<span className={classes.customStyleOnTab}>Tab 1</span>} />
<Tab label={<span className={classes.customStyleOnTab}> Tab 2</span>}/>
</Tabs>
However, it changes the styling on both the tabs whereas I want only the active tab to have a particular style (blue color and bold font). The other tab should have a normal font-weight and color:
If I use textColor property, I can achieve the desired result but I wouldn't be able to customize it. I dug into the material doc, and eventually tried all the CSS classes they've exposed, without any luck
For adding custom/different style to the active tab you can assign a class to the active tab conditionally. Every Tab has its own value (which is their index value also) and assign them class conditionally.
Here is the link of codesandbox:- https://codesandbox.io/s/elegant-tu-lxi1g?file=/src/App.js
import React, { useState } from "react";
import "./styles.css";
import {Tabs, Tab, makeStyles} from '#material-ui/core'
export default function App() {
const classes = useStyles()
const [value, setValue] = useState(0)
const handleChange = (e, newVal)=>{
setValue(newVal)
}
return (
<div className="App">
<Tabs
value={value}
onChange={handleChange}
classes={{indicator: classes.customStyleOnActiveTab}}
aria-label="some text"
>
<Tab label={<span className={ value === 0 ? classes.activeTab : classes.customStyleOnTab}>Tab 1</span>} />
<Tab label={<span className={ value === 1 ? classes.activeTab : classes.customStyleOnTab}> Tab 2</span>}/>
</Tabs>
</div>
);
}
const useStyles = makeStyles({
customStyleOnTab:{
fontSize:'15px',
color:'green'
},
customStyleOnActiveTab:{
color:'red'
},
activeTab:{
fontSize:'16px',
fontWeight:'600',
color:'pink'
}
})
also, you can assign the className to the Tab element instead of span for keeping the label prop clean, tidy, and uniform.
You can change by use makeStyle.
const useStyle = makeStyles((theme) => ({
tab: {
"& .Mui-selected": {
color: "red",
fontSize: "20px"
}
}
})
then
<Tabs
className={classes.tab}
>
<Tab label="Teacher Information" />
<Tab label="Contract" />
</Tabs>
Another possible solution is to use withStyles.
...
import { default as MuiTab } from "#material-ui/core/Tab";
import { withStyles } from "#material-ui/core/styles";
const styles = {
// check https://material-ui.com/api/tab/#css
// for more overridable styles
selected: {
fontSize: "16px",
fontWeight: "600",
color: "pink"
}
};
const Tab = withStyles(styles)((props) => <MuiTab {...props} />);
function App() {
const [value, setValue] = React.useState(0);
const handleChange = (e, newVal) => {
setValue(newVal);
};
return (
<div className="App">
<Tabs value={value} onChange={handleChange}>
<Tab label="Tab 1" />
<Tab label="Tab 2" />
</Tabs>
</div>
);
}

How to make a button inside Material-UI tooltip's title

I was able to pass Material-UI's IconButton inside Material-UI's Tooltip title.
All the views are working properly, except I cannot press the button.
I want to add a Close button to make the tooltip close on clicking the close button, but I cannot do that. Is there a way to do this? If yes, please provide a solution to this.
MUI's Tooltip has pointer-events set to none by default, so you need to enable this. Add a class to your tooltip and then add this to the css:
pointer-events: auto;
I solved it by using Popper from Material-UI.
In case someone looking for this, here are some useful snippet for it.
import * as React from 'react';
import {Tooltip, Typography} from '#mui/material'
import CloseIcon from '#mui/icons-material/Close'
export const TooltipWithIcon = (title, message) => {
const [open, setOpen] = useState(false)
const handleClose = e => {
if (open) {
setOpen(false)
}
return null
}
return(
<Tooltip
open={open}
title={
<>
<CloseIcon sx={{ float: 'right' }} onClick={e => handleClose(e)}></CloseIcon>
<Typography variant="h6" sx={{ fontWeight: 700 }}>
{title}
</Typography>
<Typography variant="body1" sx={{ fontSize: 14 }}>
{message}
</Typography>
</>
}
>
</Tooltip>
)
}

Divider color change React Material Ui

I'm working with the divider component of the material ui framework and am stuck with the color changing aspect. With most other components from this framework I've been able to change the color by applying the useStyles() method as such:
const useStyles = makeStyles(theme => ({
textPadding: {
paddingTop: 10,
paddingBottom: 10,
color:'white',
},
}));
But I'm not able to change the color of the dividers using the same approach:
const useStyles = makeStyles(theme => ({
dividerColor: {
backgroundColor: 'white',
},
}));
I of-course then apply it to the component:
<Divider classname={classes.dividerColor}></Divider>
I looked up the docs for it but can't figure out what I've done wrong. Could someone give me a helping hand?
use the classes API to change the divider color:
const useStyles = makeStyles((theme) => ({
divider: {
// Theme Color, or use css color in quote
background: theme.palette.divider,
},
}));
<Divider classes={{root: classes.divider}} />
Divider API, To get your head around Material UI Theme
To change Divider line color in MUI v5 you need to adjust your approach depending on whether the element has children or not.
For an empty Divider:
<Divider sx={{ bgcolor: "secondary.light" }} />
For a Divider with content:
<Divider
sx={{
"&::before, &::after": {
borderColor: "secondary.light",
},
}}
>
<Typography>Some Text</Typography>
</Divider>
Comparing to the other answers for v5, note that you do not need to nest the SX props under &.MuiDivider-root and you can use the theme properties with the SX shorthand strings (e.g., secondary.light instead of (theme) => theme.palette.secondary.light.
You can use
<Divider style={{ background: 'black' }} variant="middle" />
You have to override the CSS using classes.
<Divider classes={{root: classes.dividerColor}} />
See the Material UI docs on CSS overrides: https://material-ui.com/customization/components/#overriding-styles-with-classes
You can directly add color attribute to the divider like so
<Divider color="#FDA228" sx={{ height: 2, width: '92px' }} />
the result would be something like this
You should always use className while using material-ui styling instead of typical javascript style declaration like classname.
You can refer to the official doc also: https://material-ui.com/styles/basics/#hook-api
Using #mui v5 I recognized this was the only way to make it work for myself.
Note:
Because my Divider item has text, the ::before and ::after css
selectors specify which side of the divider to style.
<Divider
sx={{
'&.MuiDivider-root': {
'&::before': {
borderTop: `thin solid ${theme?.palette.primary['700']}`
}
}
}}
style={{
color: "white",
}}
variant="middle"
> Editing as - {username} </Divider>
Example with className :
const useStyles = makeStyles((theme) => ({
divider: {
background: "white",
},
}));
<Divider className={classes.divider} />
In the latest MUI(v5), This is how it is done:
<Divider
sx={{ bgcolor: (theme) => theme.palette.divider }}
style={{
border: "none",
height: 2,
margin: 0,
}}
/>
You can do it with createTheme function inside the react component
const Theme = createTheme({
components: {
MuiDivider: {
variants: [
{
props: { variant: 'dynamic' },
style: {
":before": {
borderTop: "thin solid #ffffff"
},
":after": {
borderTop: "thin solid #ffffff"
},
}
}
]
}
},
})
Use it with the variant key in the html component
<Divider variant={'dynamic'} flexItem></Divider>

MUI Drawer set background color

How to simply set background color of MUI Drawer?
tried this, but doesn't work
<Drawer
style={listStyle3}
open={this.state.menuOpened}
docked={false}
onRequestChange={(menuOpened) => this.setState({menuOpened})}
/>
const listStyle3 = {
background: '#fafa00',
backgroundColor: 'red'
}
Edit: (May-21) - Material UI V4.11.1
This can be done differently in version 4.11.1 and functional components.
There's no need to use an HoC anymore. Here's how it's done:
You should use the makeStyles helper to create the hook with a definitions of the classes and use the hook to pull them out.
const useStyles = makeStyles({
list: {
width: 250
},
fullList: {
width: "auto"
},
paper: {
background: "blue"
}
});
const DrawerWrapper = () => {
const classes = useStyles();
return (
<Drawer
classes={{ paper: classes.paper }}
open={isOpen}
onClose={() => setIsOpen(false)}
>
<div
tabIndex={0}
role="button"
onClick={() => setIsOpen(true)}
classes={{ root: classes.root }}
>
{sideList}
</div>
</Drawer>
)
}
Here's a working sandbox
Edit: (Jan-19) - Material UI V3.8.3
As for the latest version asked, the way to configure the backgroundColor would be by overriding the classes.
Based on material-ui documentation here, and the css api for drawer here - This can be done by creating an object in the form of:
const styles = {
paper: {
background: "blue"
}
}
and passing it to the Drawer component:
<Drawer
classes={{ paper: classes.paper }}
open={this.state.left}
onClose={this.toggleDrawer("left", false)}
>
A working example can be seen in this codesandbox.
Don't forget to wrap your component with material-ui's withStyles HoC as mentioned here
Based on the props you used I have the reason to think that you're using a version which is lower than v1.3.1 (the last stable version) but for the next questions you'll ask, I recommend writing the version you're using.
For version lower than V1, you can change the containerStyle prop like this:
<Drawer open={true} containerStyle={{backgroundColor: 'black'}}/>
In MUI v5, you can use the sx prop to style MUI components:
<Drawer
PaperProps={{
sx: {
backgroundColor: "pink",
color: "red",
}
}}
Or use styleOverrides to define the custom styles in createTheme:
const theme = createTheme({
components: {
MuiDrawer: {
styleOverrides: {
paper: {
backgroundColor: "pink",
color: "red",
}
}
}
}
});
Material UI V4.3.2
As in this version you can change the backgroundColor by making use of makeStyles from '#material-ui/core/styles' as shown below:
import Drawer from '#material-ui/core/Drawer';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
paper: {
background: 'black',
color: 'white'
}
});
const SideDrawer = props => {
const styles = useStyles();
return (
<Drawer
anchor="right"
open={props.drawerOpen}
onClose={() => props.toggleDrawer(false)}
classes={{ paper: styles.paper }}
>
Items
</Drawer>
);
};
export default SideDrawer;
Drawer doesn't accept style props. Use classes instead
See Drawer API
If anyone's looking for how to do this conditionally for dark/light mode, you can make 2 separate classes and use a conditional to use the right one in the component. Here's an example of how to modify #Yirenkyi's answer do achieve this:
import Drawer from '#material-ui/core/Drawer';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
paperLight: {
background: 'white',
color: 'black'
},
paperDark: {
background: 'black',
color: 'white'
}
});
const SideDrawer = props => {
const userPrefersDarkMode = true; //here's your condition
const styles = useStyles();
return (
<Drawer
anchor="right"
open={props.drawerOpen}
onClose={() => props.toggleDrawer(false)}
classes={{ paper: userPrefersDarkMode ? styles.paperDark : styles.paperLight }}
>
Items
</Drawer>
);
};
export default SideDrawer;

Categories

Resources