Styled component generate same css class with different conditions - css

I have these styles:-
import styled, { css } from "styled-components";
const H4 = css`
font-family: "Futura";
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 140%;
color: #3a786a;
`;
const H3 = css`
font-size: 24px;
`;
const Span = css`
font-size: 16px;
`;
export const Typography = styled.div`
#widgetStyles & {
${(props) => {
switch (props.variant) {
case "h4":
return H4;
case "h3":
return H3;
case "body1":
return Span;
default:
return css`
font-size: 14px;
color: #010101;
`;
}
}}
}
`;
Whenever i tried calling the Typography component with different variations Styled-components generate same css class. Which creates confliction between styles.
This is how i am calling the above defined component with different variations:-
<Typography variant="h4">{label}</Typography>
<Typography variant="h3">{label}</Typography>
But it generates the output with same class:-

Basically styled-components generates different classes but the first class is same and other class are different, as you can see in h4 and h3 tag, could you please change #widgetStyles & to #widgetStyles &&, as you can see the below code.
import styled, { css } from "styled-components";
const H4 = css`
font-family: "Futura";
font-style: normal;
font-weight: 500;
font-size: 20px;
line-height: 140%;
color: #3a786a;
`;
const H3 = css`
font-size: 24px;
`;
const Span = css`
font-size: 16px;
`;
export const Typography = styled.div`
#widgetStyles && {
${(props) => {
switch (props.variant) {
case "h4":
return H4;
case "h3":
return H3;
case "body1":
return Span;
default:
return css`
font-size: 14px;
color: #010101;
`;
}
}}
}
`;

Related

Styled component not being respected between files?

For whatever reason, the buttons (defined by AboutItem) are displaying light blue backgrounds when I hover over them. I want to make it #282828.
In a separate file I define some styled components for Buttons:
export const Button = styled.button`
display: inline-block;
font-size: 1em;
margin: 1em;
padding: 0em 1em;
`;
export const InfoButton = styled(Button)`
color: grey;
&:hover {
background-color: lightblue;
}
`;
which I then use:
interface AboutNavProps {
selected: boolean;
}
const AboutItem = styled(InfoButton) <AboutNavProps>`
color: grey;
background-color: ${props => props.selected ? "#282828" : "transparent"};
text-align: center;
&:hover {
background-color: #282828;
}
`;
export function AboutNavbar() {
const router = useRouter()
useEffect(() => {
router.prefetch("/method");
}, [])
return (
<AboutNav aria-label="Navbar">
<AboutItem as="a" href="method" selected={router.pathname == "/method"}>How It Works</AboutItem>
<AboutItem as="a" href="about" selected={router.pathname == "/about"}>About</AboutItem>
<Logo />
</AboutNav>
);
}
Is there a reason for this? I don't understand why the light blue overrides the color I define for the hover.

adding Border animations with dynamic classes in React with SCSS

I have a HeaverNav component, a pretty simple fixed position header. When the user scrolls past a certain dimension a class is added that just adds a border-bottom to the existing class. Applying an animation for the border to enter is simple enough with a
transition: all 300ms ease; But having the border animate out when the class is no longer active is tricky. Currently the border just flips off suddenly with no smoothness, how can I achieve the effect of the border animating out smoothly?
MY CODE
import React, { useEffect, useState } from 'react';
import navStyles from '../styles/nav-header.module.scss';
import { MdOutlineAddBox } from 'react-icons/md';
import { RiHeartLine } from 'react-icons/ri';
import { FiSend } from 'react-icons/fi';
const NavHeader = () => {
const [isScrolling, setIsScrolling] = useState(false);
console.log(isScrolling)
useEffect(() => {
if (typeof window !== "undefined") {
window.addEventListener("scroll", () =>
setIsScrolling(window.pageYOffset > 100)
);
}
}, []);
return (
<nav className={isScrolling ? `${navStyles.nav} ${navStyles.navIsScrolling}` : `${navStyles.nav}`}>
<h1>Instagram</h1>
<ul>
<li><MdOutlineAddBox /></li>
<li><RiHeartLine /></li>
<li><FiSend /></li>
</ul>
</nav>
)
}
export default NavHeader;
SCSS
#import "../styles/global.scss";
#font-face {
font-family: "Instagram";
src: url("../assets/instagram-font.otf") format("woff2");
}
.nav {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
width: 100%;
padding: 0.8rem;
background-color: $color-black;
h1 {
font-family: "Instagram", sans-serif;
color: $color-white;
font-size: 2rem;
}
ul {
display: flex;
margin-right: 1.5rem;
li {
color: $color-white;
font-size: $icon-size;
margin: 0 0.5rem;
transform: translateY(2px);
cursor: pointer;
}
}
}
.navIsScrolling {
border-bottom: $nav-border;
transition: all 300ms ease;
}

How to center Items in react

Im crating a navbar for a cite and currently formatting the page Im pretty new to react so im trying to start with the basics. I am stuck on how to center my NavBarLinks, I have used text-center and position to make the links be in the center of the navbar but if I make the web browser smaller it wont stay in the center. My question is what is the right to center items in react.
import React, { useState } from "react";
import {
NavbarContainer,
TopContainer,
BottomContainer,
NavbarExtendedContainer,
NavbarInnerContainer,
NavbarLinkContainer,
NavbarLink,
Logo,
OpenLinksButton,
NavbarLinkExtended,
} from "../styles/Navbar.style";
import LogoImg from "../assets/logo.png";
function Navbar() {
const [extendNavbar, setExtendNavbar] = useState(false);
return (
<NavbarContainer extendNavbar={extendNavbar}>
<NavbarInnerContainer>
<TopContainer>
<NavbarLinkContainer>
<OpenLinksButton
onClick={() => {
setExtendNavbar((curr) => !curr);
}}
>
{extendNavbar ? <>✕</> : <> ≡</>}
</OpenLinksButton>
<Logo src={LogoImg}></Logo>
</NavbarLinkContainer>
</TopContainer>
<BottomContainer>
<NavbarLinkContainer>
<NavbarLink to="/"> Home</NavbarLink>
<NavbarLink to="/products"> Products</NavbarLink>
<NavbarLink to="/contact"> Contact Us</NavbarLink>
<NavbarLink to="/about"> About Us</NavbarLink>
</NavbarLinkContainer>
</BottomContainer>
</NavbarInnerContainer>
{extendNavbar && (
<NavbarExtendedContainer>
<NavbarLinkExtended to="/"> Home</NavbarLinkExtended>
<NavbarLinkExtended to="/products"> Products</NavbarLinkExtended>
<NavbarLinkExtended to="/contact"> Contact Us</NavbarLinkExtended>
<NavbarLinkExtended to="/about"> About Us</NavbarLinkExtended>
</NavbarExtendedContainer>
)}
</NavbarContainer>
);
}
export default Navbar;
Style page
import styled from "styled-components";
import { Link } from "react-router-dom";
export const NavbarContainer = styled.nav`
width: 100%;
background-color: black;
#media (min-width: 700px) {
height: 80px;
}
`;
export const TopContainer = styled.div`
padding-left: 5%;
`;
export const BottomContainer = styled.div`
padding-right: 50px;
background-color:salmon;
`;
export const NavbarInnerContainer = styled.div`
width: 100%;
height: 80px;
`;
export const NavbarLinkContainer = styled.div`
display: flex;
`;
export const NavbarLink = styled(Link)`
color: white;
font-size: x-large;
font-family: Arial, Helvetica, sans-serif;
position: relative;
left: 43%;
top:10%;
text-decoration: none;
margin: 10px;
height: 30px;
text-align: center;
#media (max-width: 700px) {
display: none;
}
`;
export const NavbarLinkExtended = styled(Link)`
color: white;
font-size: x-large;
font-family: Arial, Helvetica, sans-serif;
text-decoration: none;
margin: 10px;
`;
export const Logo = styled.img`
#media (min-width: 700px) {
margin: auto;
}
margin: 10px;
max-width: 180px;
height: auto;
`;
I really wouldn't recommend using a whole different page for css instead just add your code to index.css, from there you can access your css from any component in your react app.
And to center the NavbarLink you can use flexbox.
Create some css code in index.css:
.navbar__link {
width: 100%
display: flex;
justify-content: center;
}
And add that class in your component element:
<NavbarLinkContainer className='navbar__link'>
<NavbarLink to="/"> Home</NavbarLink>
<NavbarLink to="/products"> Products</NavbarLink>
<NavbarLink to="/contact"> Contact Us</NavbarLink>
<NavbarLink to="/about"> About Us</NavbarLink>
</NavbarLinkContainer>

How to style previous siblings in react styled-components?

I have react component like this:
const StyledMenu = () => {
const [currentStep, setCurrentStep] = React.useState('template');
const steps = ['template', 'audience', 'demography', 'action'];
const goToNextStep = () => {
const index = steps.indexOf(currentStep);
setCurrentStep(steps[index + 1]);
};
const goToPreviousStep = () => {
const index = steps.indexOf(currentStep);
if (index === 0) {
return;
}
setCurrentStep(steps[index - 1]);
};
return(
<div>
<StepsWrapper>
{steps.map((step, index) => (
<Step key={step} active={step === currentStep} last={index === 3}>
<StepDescription>{step}</StepDescription>
</Step>
))}
</StepsWrapper>
</div>
)
}
const StepsWrapper = styled('div')`
display: grid;
grid-template-columns: repeat(4, 1fr);
width: 100%;
height: 69px;
line-height: 69px;
text-align: center;
position: relative;
top: 27px;
`;
const Step = styled('div')<{ active: boolean; last: boolean }>`
color: ${({ active }) =>
active ? '#44b3db' : '#c7e8f4'};
`;
const StepDescription = styled('div')`
width: 240px;
height: 29px;
font-family: Roboto;
font-size: 18px;
font-weight: 500;
font-style: normal;
letter-spacing: normal;
line-height: normal;
text-align: center;
text-transform: uppercase;
margin: 0 auto;
`;
and I'm trying to style the items which are before the active item. If the first item is active, then nothing will be styled. I want to achieve styles from these images:
and
and
How can I achieve this? Thanks in advance!
I achieved this by adding a new state for the active index, and to styled-component I sent a boolean if the active index is bigger than the index, so the indexes less than current active index will be styled differently as #vishnu mentioned in the comment above. The code looks now like this
const StyledMenu = () => {
const [currentStep, setCurrentStep] = React.useState('template');
const steps = ['template', 'audience', 'demography', 'action'];
//added this line of code
const [activeIndex, setActiveIndex] = React.useState(0);
const goToNextStep = () => {
const index = steps.indexOf(currentStep);
setCurrentStep(steps[index + 1]);
//set the new activeIndex
setActiveIndex(index + 1);
};
const goToPreviousStep = () => {
const index = steps.indexOf(currentStep);
if (index === 0) {
return;
}
setCurrentStep(steps[index - 1]);
//set the new activeIndex
setActiveIndex(index - 1);
};
return(
<div>
<StepsWrapper>
{steps.map((step, index) => (
//sending the checked props to the styled component
<Step key={step} active={step === currentStep} last={index
=== 3} checked={activeIndex > index}>
<StepDescription>{step}</StepDescription>
</Step>
))}
</StepsWrapper>
</div>
)
}
const StepsWrapper = styled('div')`
display: grid;
grid-template-columns: repeat(4, 1fr);
width: 100%;
height: 69px;
line-height: 69px;
text-align: center;
position: relative;
top: 27px;
`;
const Step = styled('div')<{ active: boolean; last: boolean;
checked: boolean }>`
//checking if component is marked to be styled differently
color: ${({ active, checked }) =>
active ? '#44b3db' : checked ? 'red' '#c7e8f4'};
`;
const StepDescription = styled('div')`
width: 240px;
height: 29px;
font-family: Roboto;
font-size: 18px;
font-weight: 500;
font-style: normal;
letter-spacing: normal;
line-height: normal;
text-align: center;
text-transform: uppercase;
margin: 0 auto;
`;

Changing colour of active bootstrap nav-link using styled component in Nextjs app.(typescript)

I am using react-bootstrap and styled components in my react typescript app. I want change the colour of active nav-link.
code:
const StyledNav = styled(Nav)`
font-size: 12px;
text-transform: uppercase;
`;
<StyledNav>
<StyledNav.Link>BACK </StyledNav.Link>
<StyledNav.Link>HOME </StyledNav.Link>
<StyledNav.Link active>{props.page}</StyledNav.Link>
</StyledNav>
TIA
You can use props in your template literals.
const StyledLink = styled(Nav.Link)`
font-size: 12px;
text-transform: uppercase;
color: ${props => props.active ? 'red': 'inherit'};
`;
If you want to have multiple definitions you can use it like;
const StyledLink = styled(Nav.Link)`
font-size: 12px;
text-transform: uppercase;
${props => props.active && `
color: red;
border-bottom: 3px solid green;
`}
`;
<Nav>
<StyledLink>BACK </StyledLink>
<StyledLink>HOME </StyledLink>
<StyledLink active>{props.page}</StyledLink>
</Nav>

Resources