How do I add a hover selector to a style object? - reactjs

I created a style object in react that I will pass through a style prop:
const iconStyle = {
color: "#464545",
fontSize: "24px",
margin: "20px",
transitionProperty: "color",
transitionDuration: "1s",
}
Any idea on how I could add a hover selector inside of it, because I've looked around and I still have no clue.

probably this pseudo selector will help.
const iconStyle = {
color: "#464545",
fontSize: "24px",
margin: "20px",
transitionProperty: "color",
transitionDuration: "1s",
"&:hover": {
background: "#efefef"
},
}

In React.js there is no such way hover.
You can accomplish your goal with these two states.
onMouseEnter={() => this.setState({hover: true})}
onMouseLeave={() => this.setState({hover: false})}
And you can use "hover" state(for example) to specify styles like
style = this.state.hover ? style1 : style2
Hope this helps you to understand!

Related

How to make an MUI 5 checkbox & label change color on hover?

I'd like to have a checkbox with a label in a wrapper. When the wrapper is hovered everything should change color. See the image:
Here is my code:
const styles = {formControlLabel:{
color:'#d7dae0',
border: '1px solid white',
span: {
color: '#d7dae0',
'&:hover':{border: '1px solid red'},
}
},
}}
export function MyCheckbox(){
return(
<FormControlLabel
control={<Checkbox />}
label={'test'}
sx={styles.formControlLabel}
/>
)
}
I've tried many different things, but this is the closest I've come. I can't seem to put a '&:hover' on the formControlLabel styles at the top level - it has to be imbedded in another element. Why is that?
Sandbox: https://codesandbox.io/s/magical-feynman-lzy1e2?file=/src/App.tsx
You need to change your :hover to your parent and set borderColor in the parent and having span inside the :hover parent, it will change to red at the same time
const styles = {
formControlLabel: {
border: "1px solid",
p: "8px",
m: "20px",
"&:hover": {
borderColor: "red",
span: {
color: "red"
},
}
}
};

is it possible to animate a strikethrough with React Spring?

I'm new to React Spring and I initially tried this
const strikeProps = useSpring({
textDecoration: "line-through",
from: { textDecoration: "none" },
});
But it's not working. I think there should be a way simulate the CSS solution for this.
The problem here is, that the original CSS solution is uses pseudo element for emulating the strike trough. We can only add react-spring properties for normal html elements. So the most compact way is to create a separate strike through component for this problem. For example:
const StrikeTroughtText = ({ children, weight = 1 }) => {
const props = useSpring({
from: { width: "0%" },
to: { width: "100%" }
});
return (
<div style={{ position: "relative", display: "inline-block" }}>
{children}
<animated.div
style={{
position: "absolute",
top: "50%",
left: 0,
width: props.width,
height: `${weight}px`,
background: "black"
}}
/>
</div>
);
};
We basically animate the width of the absolutely positioned div containing a black line over the text.
You can use it like a div component:
<StrikeTroughtText>text</StrikeTroughtText>
For bigger font size the default 1 px line weight is not enough, so I added a weight property also.
Here is my example: https://codesandbox.io/s/react-strike-trought-text-component-with-react-spring-animation-86cfd?file=/src/App.js

material ui Tooltip distance from the anchor

Is there a clear/easy way to control Tooltip's distance from the anchor element? The default positioning does not fit well for my case, the tooltip is too close to the anchor. I have checked all the props of it and PopperProps no visible option to do that.
You can customize the tooltip's margin using withStyles.
In my case (Material-UI 3), the tooltip was too far away from the anchor.
Here is what I needed :
const StyledTooltip = withStyles({
tooltipPlacementTop: {
margin: "4px 0",
},
})(Tooltip);
I targeted tooltipPlacementTop because it was the rule name when using the placement="top" prop.
You can find the adequate rule names in the Tooltip API documentation.
Last tip: I used the PopperProps={{ keepMounted: true }} prop to see in my navigator's inspector what CSS was applied to the tooltip.
Hope it helps.
For Material-UI V.5 it could be done like this:
<Tooltip
PopperProps={{
modifiers: [
{
name: "offset",
options: {
offset: [50, 0],
},
},
],
}}
.......
Follow up with Hugo's suggestion, since the tooltip position is absolute, instead of changing the margin I changed the anchor position by adjusting the properties right and top like so:
const StyledTooltip = withStyles({
tooltipPlacementTop: {
right: "1px",
top: "8px",
},
})(Tooltip);
It works as I expected. You can use left or right to adjust the tooltip horizontal position accordingly.
I was using material ui styled to adjust my tooltip properties. I used the normal theme which is available in the MUI documentation.
const LightTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} classes={{ popper: className }} />))(({ theme }) => ({
[`& .${tooltipClasses.tooltip}`]: {
backgroundColor: theme.palette.common.white,
color: 'rgba(0, 0, 0, 0.87)',
boxShadow: theme.shadows[1],
fontSize: 11
},}));
I tried to adjust the position property with Mui styled, but it wasn't working.
I fixed it with my external style sheet.
.MuiTooltip-popper {
inset: -25px auto 0px auto;}
In Material-UI v4, you can add margin via style prop in the PopperProps.
<Tooltip
placement="bottom"
title="hello"
PopperProps={{ style: { marginTop: -12 } }}
>
<div>Some text</div>
</Tooltip>
I'm using Material-UI 4.x version and changed tooltip distance from the anchor using following style
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: { // this part will change the distance
margin: '4px 0',
},
}))(Tooltip)
you can set it through the style prop
<Tooltip style={{ padding: '4px 0'}} > {children} </Tooltip>

How to change the styles of ListItem element with the "onclick" event?

My goal is when I click on a ListItem, it should change the background-color and text: "line-through". And then, if I click again, these changes should be canceled.
But it happens very strangely for me. I just can't understand why ListItem changes background-color only after I click to any place of the window? And why text into ListItem becomes crossed out only after I move pointer beyond the element
const styles = () => ({
listItem: {
borderRadius: "1em"
},
listItemDone: {
borderRadius: "1em",
backgroundColor: "#F6F6E8",
textDecoration: "line-through"
},
iconButton: {
padding: 5
},
important: {
color: "#00ACE9",
fontWeight: "bold"
}
});
class TodoListItem extends Component {
state = {
done: false
};
onClickItem = () => {
this.setState({
done: !this.state.done
});
};
render() {
const { label, important = false, classes } = this.props;
const { done } = this.state;
return (
<ListItem
onClick={this.onClickItem}
className={done ? classes.listItemDone : classes.listItem}
button
divider
>
<ListItemText
primary={label}
classes={{ primary: important ? classes.important : "" }}
/>
</ListItem>
);
}
}
Whenever you are trying to override Material-UI styles and it isn't working like you would expect, the best resource is the source code. Here is the URL for the ListItem source code: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/ListItem/ListItem.js. For the most part, you only need to look at the styles variable near the top of the source file.
Below I've copied all of the portions of the styles variable that deal with backgroundColor and textDecoration:
export const styles = theme => ({
/* Styles applied to the (normally root) `component` element. May be wrapped by a `container`. */
root: {
textDecoration: 'none',
'&$selected, &$selected:hover, &$selected:focus': {
backgroundColor: theme.palette.action.selected,
},
},
/* Styles applied to the inner `component` element if `button={true}`. */
button: {
transition: theme.transitions.create('background-color', {
duration: theme.transitions.duration.shortest,
}),
'&:hover': {
textDecoration: 'none',
backgroundColor: theme.palette.action.hover,
// Reset on touch devices, it doesn't add specificity
'#media (hover: none)': {
backgroundColor: 'transparent',
},
},
'&:focus': {
backgroundColor: theme.palette.action.hover,
},
},
/* Styles applied to the root element if `selected={true}`. */
selected: {},
});
The main styles causing difficulty are the button hover and focus styles. In order to override these successfully without resorting to "!important", you need to have the appropriate CSS specificity.
The following seems to do the trick:
listItemDone: {
borderRadius: "1em",
"&,&:focus,&:hover": {
backgroundColor: "#F6F6E8",
textDecoration: "line-through"
}
},
However, the above prevents there from being any hover effect on "done" items, so you may instead want to do something more like:
listItemDone: {
borderRadius: "1em",
"&,&:focus": {
backgroundColor: "#F6F6E8",
textDecoration: "line-through"
},
"&:hover": {
textDecoration: "line-through"
}
},
This allows the hover background color of done items to still be theme.palette.action.hover. If you want the hover color to be different for done items, you can specify it explicitly along with the textDecoration.
There is one other detail to take care of. If you click a list item to put it in a "done" state and then click it again, it will not be in the "done" state anymore but it will have the button focus styles applied. In order to remove that focus styling, you also need the following:
listItem: {
borderRadius: "1em",
"&,&:focus": {
backgroundColor: theme.palette.background.paper // or whatever color you want this to be
}
},
Here is my modified version of your sandbox:
So I've tried to add !important to this styles and it started working as expected:
listItemDone: {
borderRadius: "1em",
backgroundColor: "#F6F6E8 !important",
textDecoration: "line-through !important"
},
demo.
It looks like this material-ui just overrides your styles (textDecoration and backgroundColor) when you hover over elements. Hope that helps.

How to do CSS :hover function in JSX ?

Hi and thanks for the great job here. I am using react.js for my project to build my components and I feel a little bit stuck in my project right now. I am trying to style a button with a hover function and I don't know how to apply this to react.
Here is the code :
let button = {
backgroundColor: colorPalette.white,
border: "1px solid rgb(12,106,145)",
color: colorPalette.brandCol1,
textAlign: 'center',
textDecoration: 'none',
fontSize : 'inherit',
fontWeight : 600,
padding : "5px 8px 5px 8px"
}
and I would like to add a hover style to it just like we do in css with
button:hover {
style here.......
}
What is the correct syntax ?
You can use:
const styles = {
myStyleClassName: {
padding: '16px 0px 16px 0px',
'& a': {
textDecoration: 'none',
color: '#0000ee',
},
'& a:hover': {
textDecoration: 'underline',
},
},
myButtonClass: {
'&:hover': {
textDecoration: 'underline',
},
},
};
....
render() {
<span className={myStyleClassName}><a tag><button><someDomObjct></span>
<button className={myButtonClass}>my label</button>
}
See: http://cssinjs.org/jss-nested/?v=v6.0.1
The repo isn't necessary for everything, the above should work out of the box.
You can use onMouseEnter onMouseLeave to adjust the state of the component
<button
onMouseEnter={() => setButtonHovered(true)}
onMouseLeave={() => setButtonHovered(false)}
className={buttonIsHovered ? 'hover' : null}
/>
see here for more info
or just use a css class?
import './style.css'
<button className="Button"/>
.Button:hover {
...
}
Using react to manage state for a hover animation is way overkill. You shouldn't need to use javascript for a simple CSS hover...You're in the browser, use the right tool for the right job, right?
So here I'll show a couple different ways to approach the same goal:
In my component I import glamor and my styles file:
import { style } from 'glamor';
import styles from '../styles';
And in my styles file, I have something like this:
import { style } from 'glamor';
const styles = {
redHoverbutton: style({
backgroundColor: "#aaaaaa",
fontSize: "1.1rem",
transition: "all ease .5s",
":hover": {
backgroundColor: "#ff0000",
color: "#ffffff"
}
})
};
export default styles;
And this makes the hover functionality work via css, like this:
<div {...styles.redHoverbutton}></div>
This is a css driven hover effect (with transition if you noticed) but this isn't inline css. None the less, your style can be crafted in the same file, like this:
let theStyle = style({ backgroundColor: "#aaaaaa",transition: "all ease .5s", ":hover": { cursor: "pointer", backgroundColor: "#ffff9b", color: "#fd0808" } });
return (<div {...theStyle}>Hover me!</div>);
Now, how to get the style and the spread operator onto the same line and inside of the JSX element?
<div {...style({ backgroundColor: "#aaaaaa", height: "30px", width: "100%", padding: "6px", fontsize: "16px", transition: "all ease .5s", ":hover": { cursor: "pointer", backgroundColor: "#ffff9b", color: "#fd0808" } })}>Hover Me!</div>
It may not be perfect but it works well and accomplished the same thing as a true inline style and in a similar manner.

Resources