how to change a styled component's before content on hover [emotion.js , styled components ] - reactjs

on button hover I want to make changes to the :before content too , I couldn't find an answer in the official documentation I wonder f this is possible .
here is the css selector I want to convert to a styled component syntax is:
.button:hover::before{}
and here is the styled component :
import styled from '#emotion/styled'
export const Button =styled.button(props=>{
return`
padding: .75rem 2rem ;
color: #fff;
background-color: transparent;
border: 1px solid #000;
position: relative;
z-index: 1;
transition: all .5s cubic-bezier(0.785, 0.135, 0.15, 0.86);
cursor: pointer;
width: ${props.width ? props.width:'fit-content'};
margin-top: ${props.marginTop ? props.marginTop :0}rem;
&:before{
content: '';
position: absolute;
z-index: -1;
height: 100%;
width: 100%;
top: 0;
left: 0;
${props.collection?"background-color: #fff;":"background-color: var(--colorGrey);"}
transition: all .5s cubic-bezier(0.785, 0.135, 0.15, 0.86);
transform-origin: left center;
//I want to change style on hover
}
&:hover{
color:var(--colorGrey);
}
`})

Simply nest a :before pseudo-element inside the :hover pseudo class.
Also, consider using a template literal, instead of a function that takes props.
import styled from '#emotion/styled';
export const Button = styled.button`
padding: 0.75rem 2rem;
color: #fff;
background-color: transparent;
border: 1px solid #000;
position: relative;
z-index: 1;
transition: all 0.5s cubic-bezier(0.785, 0.135, 0.15, 0.86);
cursor: pointer;
width: ${(props) => (props.width ? props.width : 'fit-content')};
margin-top: ${(props) => (props.marginTop ? props.marginTop : 0)}rem;
&:before {
content: '';
position: absolute;
z-index: -1;
height: 100%;
width: 100%;
top: 0;
left: 0;
${(props) => (props.collection ? 'background-color: #fff;' : 'background-color: var(--colorGrey);')}
transition: all .5s cubic-bezier(0.785, 0.135, 0.15, 0.86);
transform-origin: left center;
}
&:hover {
color: var(--colorGrey);
&:before {
content: 'Hovered';
}
}
`;

Related

How to design a UI Component like this in React?

I got the requirement for developing a UI component for teams-info like this.
I have just started using React with React-Bootstrap, but I couldn't find a UI layout which can render this. I have used react-responsive-carousel, but It's a flat icon at the bottom of the image as Thumbnail not like a half-circular option shown in the image.
Update:
On selecting another image the image positions must not change. Like this.
Can anyone guide me how can I achieve this?
Thanks in advance.
Something like this may bring you closer to the result. One way of mapping the user information in the middle would be through utilizing different pieces of content in an array.
function Circle() {
function elementMethod(){
return (
<span onMouseEnter={...} onMouseLeave={...} className='individual--circ'><img src={...}></img> </span>
}
return (
<React.Fragment>
{ circleElement.map((element) => {
<div classname='cir-menu'>
{element}
</div>
}
</React.Fragment>
)
}
I've built something similar before which has a similar appearance (animated, however). The CSS looked like this:
.contact-icon{
background-color: #000000;
border-radius: 50%;
padding: 20px;
box-shadow: 1px 1px 1px 1px rgba(0,0,0,0.1),
2px 2px 2px 2px rgba(0,0,0,0.1),
4px 4px 4px 4px rgba(0,0,0,0.1);
}
.middle-cir{
position: relative;
}
.contact-outer{
background-color: #611427;
color: white;
height: 100vh;
width: 100vw;
position: fixed;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
margin: 0;
opacity: 100;
visibility: visible;
z-index: 4;
transition: visibility .5s, opacity 1s ease;
}
.contact-outer h1{
top: 0;
margin-top: 4em;
position: absolute;
opacity: 100
}
.contact-outer-none h1{
top: 0;
margin-top: 4em;
position: absolute;
}
.contact-outer-none{
background-color: #611427;
color: #F2F2E9;
height: 100vh;
width: 100vw;
position: fixed;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
margin: 0;
opacity: 0;
visibility:hidden;
z-index: 4;
transition: visibility .5s,opacity 1s ease;
}
.cir-menu{
position: relative;
justify-self: center;
display: flex;
justify-content: center;
align-items: center;
transform: rotate(-87deg);
}
.cir-a{
position: absolute;
transform: rotate(72deg) translateX(80px) rotate(10deg);
transition: transform 1s;
}
.cir-a:hover{
position: absolute;
transform: rotate(72deg) translateX(110px) rotate(10deg);
}
.cir-a-min{
position: absolute;
transform: rotate(72-20deg) translateX(0px) rotate(-72deg);
transition: transform 1s;
}
.cir-b{
position: absolute;
transform: rotate(144deg) translateX(80px) rotate(-60deg);
transition: transform 1s;
}
.cir-b:hover{
position: absolute;
transform: rotate(144deg) translateX(110px) rotate(-60deg);
}
.cir-b-min{
position: absolute;
transform: rotate(144-20deg) translateX(0px) rotate(-144deg);
transition: transform 1s;
}
.cir-c{
position: absolute;
transform: rotate(216deg)translateX(80px) rotate(-132deg);
transition: transform 1s;
}
.cir-c:hover{
position: absolute;
transform: rotate(216deg) translateX(110px) rotate(-132deg);
}
.cir-c-min{
position: absolute;
transform: rotate(216-20deg) translateX(0px) rotate(-216deg);
transition: transform 1s;
}
.cir-d{
position: absolute;
transform:rotate(288deg) translateX(80px) rotate(-204deg);
transition: transform 1s;
}
.cir-d:hover{
position: absolute;
transform: rotate(288deg) translateX(110px) rotate(-204deg);
}
.cir-d-min{
position: absolute;
transform:rotate(288-20deg) translateX(0px) rotate(-288deg);
transition: transform 1s;
}
.cir-e{
position: absolute;
transform: rotate(360deg) translateX(80px) rotate(-276deg);
transition: transform 1s;
}
.cir-e:hover{
position: absolute;
transform: rotate(360deg) translateX(110px) rotate(-276deg);
}
.cir-e-min{
position: absolute;
transform: rotate(360-20deg) translateX(0px) rotate(-360deg);
transition: transform 1s;
}
.nav-icon-ctr{
visibility: visible !important;
background-color: #F2F2E9;
position: relative;
justify-self: center;
align-self: center;
z-index: 99;
border-radius: 50%;
color: black;
height: 20px;
width: 20px;
padding: 1rem;
transform: rotate(87deg);
box-shadow: 1px 1px 1px 1px rgba(0,0,0,0.2),
3px 3px 3px 3px rgba(0,0,0,0.2);
}

Is it possible to use the same React component with different CSS, using css modules?

I found the React CSS modules usefull, but having problem when I tried to reuse the same component with a little modified css I stuck. For example I created Neon glowing button, but now need to change only the width of the Button and some additional small changes in the css.
The only option I see is component without css and for every different case need to rewrite the whole css. Is there a smarter way?
import React from "react";
import styles from "./index.module.css";
import { Link } from "react-router-dom";
const GlowingButton = ({ title, path }) => {
return (
<div className={styles.buttonWrapper}>
<Link className={styles.button} to={path}>
<button className={styles["glow-on-hover"]}>{title}</button>
</Link>
</div>
);
};
export default GlowingButton;
And here is index.module.css
.buttonWrapper {
margin: 0px;
padding: 0px;
display: flex;
justify-content: center;
align-items: center;
background: transparent;
font-family: "consolas";
}
.button {
margin: 0;
padding: 0;
width: 80%;
height: 8vh;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background: #100f;
text-decoration: none;
}
.glow-on-hover {
width: 400px;
height: 50px;
border: none;
outline: none;
color: #fff;
background: #111;
cursor: pointer;
position: relative;
z-index: 0;
border-radius: 10px;
}
.glow-on-hover:before {
content: "";
background: linear-gradient(
45deg,
#ff0000,
#ff7300,
#fffb00,
#48ff00,
#00ffd5,
#002bff,
#7a00ff,
#ff00c8,
#ff0000
);
position: absolute;
top: -2px;
left: -2px;
background-size: 400%;
z-index: -1;
filter: blur(5px);
width: calc(100% + 4px);
height: calc(100% + 4px);
animation: glowing 20s linear infinite;
opacity: 0;
transition: opacity 0.3s ease-in-out;
border-radius: 10px;
}
.glow-on-hover:active {
color: #000;
}
.glow-on-hover:active:after {
background: transparent;
}
.glow-on-hover:hover:before {
opacity: 1;
}
.glow-on-hover:after {
z-index: -1;
content: "";
position: absolute;
width: 100%;
height: 100%;
background: #111;
left: 0;
top: 0;
border-radius: 10px;
}
#keyframes glowing {
0% {
background-position: 0 0;
}
50% {
background-position: 400% 0;
}
100% {
background-position: 0 0;
}
}

Bottom navigation bar animation

I want to make it so that when you click on one of the icons, a certain strip appears under it, which will mean that the person is on this page (something like this)
At the moment, my navbar looks like this
Here's what I have at the moment (HTML):
let marker = document.querySelector('#marker');
let item = document.querySelectorAll('nav a .MuiSvgIcon-root');
function indicator(e) {
marker.style.left = e.offsetLeft + "px";
marker.style.width = e.offsetWidth + "px";
}
item.forEach(link => {
link.addEventListener('click', (e) => {
indicator(e.target)
})
})
body {
position: fixed;
bottom: 0;
left: 0;
background: #f2f2f2;
width: 100%;
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 40px;
border-top: 1px solid lightgray;
z-index: 100;
}
.MuiSvgIcon-root {
font-size: 35px;
cursor: pointer;
transition: 0.3s cubic-bezier(0.1, 0.1, 0.5, 1.4);
:hover {
transform: translateY(-5px);
}
}
#marker {
position: absolute;
height: 4px;
width: 0;
background: #000;
bottom: 8px;
left: 0;
transition: 0.5s;
border-radius: 4px;
}
<div id="marker"></div>
<HomeIcon/>
<TimelineIcon/>
<AccountCircleIcon/>
<ExploreIcon/>
.MuiSvgIcon-root there is defining all icons.
Your js code is correct. You should check your HTML and CSS. Because their structure is important

Problem accessing styled component nth-child

Sorry for my bad English. I have some difficulty accessing the children of a menu in styled component. This is my component I want to access the AccountMenuItem children, I want to apply a higher height to the first and last children, but I can not access the way and the way.
CodeSandbox
I tried many options, but to no avail:
These are the last ones.
&:nth-child(2) ${AccountMenuItem} {
height: 80px;
}
&${AccountMenuItem}:nth-child(2) {
height: 80px;
}
<AccountMenu>
{menuItems.map((item, indice) => {
return (
<AccountMenuItem key={indice}>
<MenuImage src={item.icon} alt={item.text} />
<MenuItem>{item.text}</MenuItem>
</AccountMenuItem>
)
})}
</AccountMenu
const AccountMenuItem = styled.span`
height: 40px;
color: ${props => props.theme.primary[100]};
display: flex;
align-items: center;
text-decoration: none;
background-color: ${props => props.theme.TextPalette[100]};
&:hover {
background-color: rgba(131, 0, 196, 0.05);
font-weight: bold;
}
`
const AccountMenu = styled.div`
display: inline-block;
visibility: hidden;
position: absolute;
bottom: -240px;
width: 198px;
right: 0;
z-index: 99999;
text-decoration: none;
background-color: #f1f1f1;
border-bottom: 5px solid ${props => props.theme.primary[100]};
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
#media only screen and (min-width: 720px) {
left: -55px;
bottom: -240px;
}
&:hover {
visibility: visible;
}
&::after {
content: '';
position: absolute;
bottom: 100%;
left: 90%;
margin-left: -10px;
border-width: 10px;
border-style: solid;
border-color: transparent transparent #12ff92 transparent;
#media only screen and (min-width: 720px) {
margin-right: 0;
height: 120px;
left: 50%;
}
}
&:nth-child(2) ${AccountMenuItem} {
height: 80px;
}
`
There are two solutions to this. I have implemented both solutions in this link, one by setting background of the second child to black, and another by setting the background of the third child to blue.
Code: https://codesandbox.io/s/determined-tree-0l1hs
The important bit is that you were missing a space between & and the child's identifier in your first example. It should be like this:
// v-- Space here!!
& ${AccountMenuItem}:nth-child(3) {
background: blue;
}
The difference of the space is the same as this difference in traditional CSS:
.account-menu.account-menu-item // means an element that has both classes
.account-menu .account-menu-item // means the second element is a descendant of the first
The other way to do this, which I prefer, is just define the rule in the AccountMenuItem instead of defining it in the parent. That way you can skip the weird inheritance stuff and apply the style directly. So in AccountMenuItem you just need this:
&:nth-child(2) {
background: black;
}

flip an image when onClick event

In order to implement some features in my react app I need to flip an image in a grid horizonaly when the user choose it with onClick event.
I've readed regarding states in react , and noticed that this is what I need.
When onClick event, flip the image.
The follwing code isn't working well.
The isExpanded working fine, but the image in the grid isn't fliping.
What I'm doing wrong ?
I have initiated the isExpanded to false in my constractor.
handleToggle(e){
e.preventDefault();
this.setState({
isExpanded: !this.state.isExpanded,
})
render() {
const {isExpanded } = this.state;
return (
<div
className={`image-root ${isExpanded ? 'image-flip' : ''}`}
style={{
backgroundImage: `url(${this.urlFromDto(this.props.dto)})`,
width: this.state.size + 'px',
height: this.state.size + 'px'
}}
>
<div>
<FontAwesome className="image-icon" onClick={(e)=>
this.handleToggle(e)} name="arrows-alt-h" title="flip"/>
</div>
</div>
);
}
}
The .scss code:
.image-root {
background-size: cover;
background-position: center center;
display: inline-block;
vertical-align: top;
box-sizing: border-box;
position: relative;
border: 1px solid white;
> div {
visibility: hidden;
background: rgba(0, 0, 0, 0.7);
cursor: pointer;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
color: white;
padding: 15px;
text-align: center;
text-align: center;
box-sizing: border-box;
white-space: pre;
display: flex;
align-items: center;
justify-content: center;
}
&:hover > div {
visibility: visible;
}
.image-icon {
font-size: 20px;
vertical-align: middle;
border: 1px solid #ccc;
color: #ccc;
border-radius: 5px;
cursor: pointer;
padding: 12px;
margin: 3px;
&:hover {
color: white;
border-color: white;
}
}
.image-flip {
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";
}
The issue was accured due to the image-flip css was in the wrong scope.
I just move the image-flip css out of the image-root scope.
Thanks.

Resources