I have a navbar with a hamburger button and i want to change the style (the bar color and the hamburger button style) on tap. I mention that i've tried using &:active, &.activeBar on the scss file. For some reason the background color doesn t change and the hamburger button doesn't turn into an X
This is my SCSS file:
.topbar {
width: 100%;
background-color: $secondaryColor;
color: $mainColor;
height: 70px;
position: fixed;
top: 0;
z-index: 3;
transition: all 1s ease;
overflow: hidden;
.wrapper {
padding: 10px 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
display: flex;
align-items: center;
margin: 10;
.itemContainer {
display: flex;
align-items: center;
.icon {
font-size: 36px;
margin-right: 5px;
&:hover {
color: blue;
}
}
span {
font-size: 15px;
font-weight: 700;
}
}
.logo {
font-size: 40px;
font-weight: 700;
text-decoration: none;
color: inherit;
margin-right: 40px;
}
}
.right {
.hamburger {
width: 32px;
height: 25px;
display: flex;
flex-direction: column;
justify-content: space-between;
span {
width: 100%;
height: 3px;
background-color: $mainColor;
transform-origin: left;
transition: all 0.5s ease;
}
}
}
&.activeBar {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
}
And this is where i try to change the classname in my js file:
import React from 'react';
import styles from './topbar.module.scss';
import { Facebook } from '@material-ui/icons';
const Topbar = ({ open, toggle }) => {
function menuToggled() {
toggle(!open);
console.log('menuToggled', open);
}
return (
<div className={`${styles.topbar} ${open ? 'active' : ''}`}>
<div className={styles.wrapper}>
<div className={styles.left}>
<a href='#slider' className={styles.logo}>
Muntenia cu gust
</a>
<div className={styles.itemContainer}>
<Facebook
className={styles.icon}
onClick={() => window.open('https://stackoverflow.com/')}
/>
</div>
</div>
<div className={styles.right}>
<div className={styles.hamburger} onClick={menuToggled}>
<span className={styles.line1}></span>
<span className={styles.line2}></span>
<span className={styles.line3}></span>
</div>
</div>
</div>
</div>
);
};
export default Topbar;
CodePudding user response:
In your code, you're adding active
as a class in the "global" scope. By default with css-modules, all classes are output in "local" scope. So your .topbar
class, after compilation, would look something like: .Topbar_topbar__abc12
("abc12" would be a hash).
So, the .active
class is also being compiled to local scope, looking something like: .Topbar_active_def34
In your markup, you're toggling the .active
class as a string rather than as styles.active
. So, on output, you're expecting your "active" class to be .Topbar_topbar__abc12.active
when in actuality, your stylesheet is declaring .Topbar_topbar_abc12.Topbar_active_def32
as the "active" class.
By declaring .active
as being in the global scope, the output would then be as expected. Try adding the :global
flag to your stylesheet:
...
&:global(.active) {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
...
CodePudding user response:
use classnames
package (https://www.npmjs.com/package/classnames) to combine classes that are on the same element, the rest is handled the same as in vanilla html/css/js
In your code you use active
it also should come from styles and be combined using:
classnames('styles.ElementClassName', active && styles.active)
CodePudding user response:
Adding the active
selector on the regular .hamburger
class should trigger on touch. Also the classname in you scss is activeBar
but in your react app is only active
.
&.clicked {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
If you want to change the topBar also then you'll need to change your TopBar component a bit
import React, { useState } from 'react';
import styles from './topbar.module.scss';
import { Facebook } from '@material-ui/icons';
const Topbar = ({ open, toggle }) => {
const [isClicked, setIsClicked] = useState(false);
function menuToggled() {
toggle(!open);
console.log('menuToggled', open);
}
return (
<div className={`${styles.topbar} ${open ? 'active' : ''} ${ isClicked && ' clicked'}`}>
<div className={styles.wrapper}>
<div className={styles.left}>
<a href='#slider' className={styles.logo}>
Muntenia cu gust
</a>
<div className={styles.itemContainer}>
<Facebook
className={styles.icon}
onClick={() => window.open('https://stackoverflow.com/')}
/>
</div>
</div>
<div className={styles.right}>
<div className={styles.hamburger} onClick={menuToggled} onTouchStart={(e) => setIsClicked(true)}>
<span className={styles.line1}></span>
<span className={styles.line2}></span>
<span className={styles.line3}></span>
</div>
</div>
</div>
</div>
);
};