Underline animation on hover MUI - reactjs

Before anyone removes this question and says it is similar to this one please hear me out. I am trying to do almost exactly what is being done in that post. The issue is the person who responded just gave some CSS which does not answer the question at hand. I am trying to do this FULLY in MUI. I would preferably want to be able to style my component using the makeStyles hook.
How would one implement an underline animation below a typography component such as the ones on the navigation bar here? I am really new to JS and MUI so I would appreciate something which is well explained and implemented so I can learn the terminology as well as the frameworks themselves.
This is my code so far. It's just like the one in the first link.
const useStyles = makeStyles({
link: {
color: "white",
position: "relative",
"&:before": {
content: "",
position: "absolute",
width: "0",
height: "2px",
bottom: "0",
left: "0",
backgroundColor: "#FFF",
visibility: "hidden",
transition: "all 0.3s ease-in-out",
},
"&:before:hover": {
visibility: "visible",
width: "100%"
}
}
});
function NavButton(props){
const classes = useStyles();
return (
<a href={`/#${props.text}`}>
<Link className={classes.link}>
<Typography>{props.text}</Typography>
</Link>
{/*<p className={"hover-underline-animation"}*/}
{/* {props.text}*/}
{/*</p>*/}
</a>
);
}
I am receptive to any other types of input. These questions are just as much a way for me to learn as a way to get an answer.

Working code
const useStyles = makeStyles({
link: {
color: 'white',
position: 'relative',
'&:before': {
content: "''",
position: 'absolute',
width: '0',
height: '2px',
bottom: '-3px',
left: '50%',
transform: 'translate(-50%,0%)',
backgroundColor: 'red',
visibility: 'hidden',
transition: 'all 0.3s ease-in-out',
},
'&:hover:before': {
visibility: 'visible',
width: '100%',
},
},
});
<Link underline="never" className={classes.link}>
<Typography component="span">link</Typography>
</Link>
Some explanation why your code didn't work:
Change content: "" to content: "''". Related answer.
Add underline="never" to Link to remove the built-in underline in the anchor element when hovering.
Change the Typography's root component to span or set its display to inline to make the container width and the underline width match the text content.
Change &:before:hover to &:hover:before: The former means hover the underline to run the animation, but its width is 0 so it can't be hovered, the latter means hover the link to run the line animation.
Add these 2 lines to make the underline expands from the middle:
left: '50%',
transform: 'translate(-50%,0%)',

I have spent hours trying to find the right combination to use Link and override the webkit underline to prevent the links in my navigation from having an underline without explicitly adding text-decoration: none to my global CSS. I had to add 'textDecoration: 'none' to the makeStyles function in this example and of course change red to blue but this works beautifully for my nav bar.
const useStyles = makeStyles({
link: {
color: 'white',
position: 'relative',
textDecoration: 'none',
'&:before': {
content: "''",
position: 'absolute',
width: '0',
height: '2px',
bottom: '-3px',
left: '50%',
transform: 'translate(-50%,0%)',
backgroundColor: 'blue',
visibility: 'hidden',
transition: 'all 0.3s ease-in-out',
},
'&:hover:before': {
visibility: 'visible',
width: '100%',
},
},
})

Related

react-google-autocomplete dropdown not showing up on MUI Dialog

I am trying to build Address form dialog with Google places api.
The problem is, when I use react-google-autocomplete's usePlacesWidget with MUI TextField, Google place dropdown menu is not showing up on Material UI Dialog.
I have tried adding style to .pac-container, but it still did not work.
const useStyles = makeStyles((theme) => ({
dialog: {
// the dropdown is next to the dialog root, not inside
'& .pac-container': {
zIndex: '9999 !important',
},
},
}));
<Dialog className={classes.dialog}/>
This is what I've done.
Does anyone know how to solve this problem?
Use This Custom Modal
import Dialog from '#mui/material/Dialog';
import { withStyles } from '#material-ui/styles';
const styles = theme => ({
root: {
marginTop: 24,
padding: theme.spacing(2),
position: 'absolute',
zIndex: '7 !important',
right: '0px',
bottom: '0px',
top: '0px',
left: '0px',
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(2),
color: theme.palette.grey[500]
}
});
const CustomDialog = withStyles(styles)(Dialog);

ReactJS className not being applied to component

ReactJS newbie question. I have a searchbar component, as shown below, which includes two other components (LocationLookup & EmergencyService), both of which make use of "makeStyles" in their respective components and are styled without issue. However, I'm trying to apply a field separator to appear between each of the components within the searchbar component but for some reason the styles aren't being applied. Note that I've tried adding some additional CSS to change the font color and background color to the "fieldSeparator" class as well just to confirm that the issue isn't with the current before/after selectors. Doesn't matter what CSS I add to "fieldSeparator", it doesn't apply to those two components. FYI, the "searchBarContainer" CSS is applied to the searchbar container without issue. Not sure if this a props or state issue. Any tips on what I might be doing wrong would be much appreciated. Thanks in advance!
import React from 'react';
import { makeStyles, withStyles } from '#material-ui/core/styles';
import LocationLookup from "./LocationLookup";
import EmergencyService from "./EmergencyService";
const useStyles = makeStyles((theme) => ({
searchBarContainer: {
width: "calc(100% - 300px)",
height: "44px",
float: "left",
flexGrow: "1",
border: "1px solid #989586",
borderRadius: "9999px",
backgroundColor: "#fbfbf8",
margin: "0"
},
fieldSeparator: {
'&::after': {
content: '""',
borderRight: "1px solid #ccc9b3",
position: "absolute",
top: "10px",
width: "1px",
right: "0",
height: "20px",
bottom: "0"
},
'&::before': {
content: '""',
borderRight: "1px solid #ccc9b3",
position: "absolute",
top: "10px",
width: "1px",
right: "0",
height: "20px",
bottom: "0"
},
'&:hover': {
'&::after': {
display: "none"
},
'&::before': {
display: "none"
}
},
}
}));
export default function SearchBar() {
const classes = useStyles();
return (
<div className={classes.searchBarContainer}>
<LocationLookup className={classes.fieldSeparator} />
<EmergencyService className={classes.fieldSeparator} />
</div>
);
}```
**Why not using HTM/HTML/xml formats instead? The format look abit mix-up... thanks.. the structure are base Webbase or kernel Base? **
Make sure that you have drilled down the props to your components like this:-
const LocationLookup = (props) => {
return (
<div {...props}>
Hello
</div>
)
}
Go to your components LocationLookup and EmergencyService and make sure they are properly getting the props.

Creating a responsive background video with material-ui breakpoint down not working

I would like to create a responsive background video in my react application using material-ui but it seems my understanding of material-ui breakpoints needs some help. My first attempt was doing something like:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'inline-block',
position: 'fixed',
top: '0',
right: '0',
bottom: '0',
left: '0',
overflow: 'hidden',
zIndex: -100,
padding: theme.spacing(1),
[theme.breakpoints.down('lg')]: {
background: 'url("./assets/img/MichaelPR.jpg") center center / cover no-repeat'
},
},
video: {
position: 'absolute',
top: '50%',
left: '50%',
width: 'auto',
height: 'auto',
minHeight: '100%',
WebkitTransform: 'translate(-50%, -50%)',
MozTransform: 'translate(-50%, -50%)',
MsTransform: 'translate(-50%, -50%)',
transform: 'translate(-50%, -50%)',
display: 'inline-block',
[theme.breakpoints.down('lg')]: {
display: 'none',
},
}
})
);
export default () => {
const styles = useStyles();
return (
<div className={styles.root}>
<video
autoPlay
muted
loop
className={styles.video}
>
<source src='./assets/vid/MichaelPR.mp4' type='video/mp4' />
Your device does not support playing 'video/mp4' videos
</video>
</div>
)
}
The idea here is to make the video stop displaying and cause the background of the parent div to be a static image for all devices which have a screen size of less than 'lg'. But this is now what happens. What I see is the video is NEVER displayed no matter what the screen size. If I change the breakpoint from 'down' to 'up'. I seems to work as expected but not what is desired. I get a static image for the background and the video display is stopped. So my question is how do I get the desired effect for screen sizes BELOW 'lg'?
To make it static on all devices less than lg you would want to use theme.breakpoints.down('md') as down is inclusive of the breakpoint you enter.

Tailwind CSS :before pseudo class

I've now been working in circles trying to understand what is happening. I'm making a design library using storybook with Tailwind. I can't seem to get the :before pseudo class to work. No matter where I place it in the styling, then it's never rendered.
An example is that I am trying to make a component which uses react-slick, and want to style the navigation:
'& .slick-dots': {
bottom: -30,
display: 'block',
left: 4,
listStyle: 'none',
margin: 0,
padding: 0,
position: 'absolute',
textAlign: 'center',
width: '100%',
'& li': {
cursor: 'pointer',
display: 'inline-block',
height: 20,
margin: '0 5px',
padding: 0,
position: 'relative',
width: 20,
'& button': {
border: 0,
background: 'transparent',
display: 'block',
height: 20,
width: 20,
outline: 'none',
lineHeight: 0,
fontSize: 0,
color: 'transparent',
padding: 5,
cursor: 'pointer',
'&:before': {
position: 'absolute',
top: 0,
left: 0,
content: '',
width: 20,
height: 20,
fontFamily: 'sans-serif',
fontSize: 20,
lineHeight: 20,
textAlign: 'center',
color: '#000000',
opacity: 0.75,
display: 'inline-block',
},
},
},
},
Found the problem. The :before pseudo class won't render unless there is content, but in the case of css in js, then content needs to look like this content: '"text"', and not content: 'text',
Another way is to define your content in the tailwind.config.js
theme: {
extend: {
content: {
'arrowNeonGreen': 'url("../src/images/icons/arrow-neon-green.svg")',
},
fontSize: {
...
You can render it using the following className. Make sure to include an inline-block and width.
<Link className="after:content-arrowNeonGreen after:inline-block after:w-8">Learn More</Link>
You can also apply a hover state like this hover:after:content-arrowNeonGreen
<Link className="hover:after:content-arrowNeonGreen after:content-arrowBlack after:inline-block after:w-8">Learn More</Link>
to get the :before class to work, you have to use tailwindcss-pseudo-elements package to customize your pseudo elements. check the docs below
https://www.npmjs.com/package/tailwindcss-pseudo-elements

React native - pseudo elements equivalent

I want to create a button with a stripe on top that looks like it's going behind the button (image below).
I already solved this in pure CSS by using the ::after pseudo class. But I'm not sure how to do this in React. Any suggestions or help is appriciated.
There is a way by using glamorous div.
const IconDiamond = glamorous.div(
{
width: 0,
height: 0,
border: '50px solid transparent',
borderBottomColor: 'red',
position: 'relative',
top: '-50px',
'&::after': {
content: `''`,
position: 'absolute',
left: '-50px',
top: '50px',
width: '0',
height: '0',
border: '50px solid transparent',
borderTopColor: 'red',
}
},
)
Please note:
CSS properties must be camel-cased along the lines of react https://facebook.github.io/react/docs/dom-elements.html#style
when using the content property you need to ensure the quotes are included in the passed string ie content: ''`
the syntax for before and after pseudo elements is '&::before': { & '&::after': { https://github.com/paypal/glamorous#example-style-objects
Check this for more information: https://github.com/paypal/glamorous/issues/223
To learn more about glamorous div https://glamorous.rocks/basics

Resources