How to make activeClass on NavLink - styled component - reactjs

Hi everyone im in trouble with active Link, i use Styled Component.
I want my link to be Red when i'm on active link but nothing work.
I tried ActiveCLassName but this not work too.
can someone help me?
thanks a lot
const NavLink = styled(Link)`
display: flex;
justify-content: center;
align-items: center;
height: 100%;
padding: 0 10px;
list-style-type: none;
text-decoration: none;
color: black;
background-color: yellow;
border: 0.1px solid lightgrey;
`;
export default function Nav() {
return (
<NavWrapper>
<UlNav>
<LiNav>
<NavLink to="/Burgers">Burgers</NavLink>
</LiNav>
<LiNav>
<NavLink to="/Burgers">Pizza</NavLink>
</LiNav>
<LiNav>
<NavLink to="/Burgers">Drinks</NavLink>
</LiNav>
</UlNav>
</NavWrapper>
)};

Issues
The issue I see is you are styling the Link component instead of the NavLink component. The Link component doesn't take any additional props for handling active links.
Solution
The NavLink component uses a .active class by default, so of you don't need any special classname you should use this class.
Example:
import { NavLink as BaseNavLink } from "react-router-dom";
const NavLink = styled(BaseNavLink)`
display: flex;
justify-content: center;
align-items: center;
height: 100%;
padding: 0 10px;
list-style-type: none;
text-decoration: none;
color: black;
background-color: yellow;
border: 0.1px solid lightgrey;
&.active {
.... your active CSS rules here
}
`;
Tested and works in both RRDv5 and RRDv6.
RRDv5
RRDv6
"/drinks"
"/burgers"

Your code is missing some stuff, like I am not seeing anywhere you are setting color: red like you want. Basically, the active link will have the class active applied, so either using a normal stylesheet or inside your styled(Link, you have to write a rule for that class that does what you want.
Like it says here Use 'active' state from React Router in Styled Components. You may have to use the &.active selector to apply the styles.
activeClassName just changes what the class name is, which isn't what you want. By default it is active which is fine, you just have to write the CSS rule to match it. https://v5.reactrouter.com/web/api/NavLink/activeclassname-string

Related

Styled Components Injects wrong classes on wrong elements

I'm witnessing a weird behavior when in styled-components with SSR in remix.run
I have a ProductCard Component that renders a normal product card with styled-components
ProductCard.tsx
import Button from "../Button";
function ProductCard({ product }: props) {
return (
<>
<Wrapper>
....
<ButtonsWrapper>
<Cart
onClick={addToCart}
mode={addedToCart ? "secondary" : "primary"}
disabled={loading}
key="cart-button"
>
{addedToCart ? "Added!" : "Add to cart"}
{loading && <LoadingSpinner src="/images/responses/loader.svg" />}
</Cart>
<ShareButton mode="secondary" aria-label="share">
<Icon id="share" />
</ShareButton>
</ButtonsWrapper>
</Wrapper>
</>
);
}
const Cart = styled(Button)`
flex: 1.1;
display: flex;
justify-content: center;
gap: 10px;
`;
const ShareButton = styled(Button)`
padding: 0.9rem;
`;
const Wrapper = styled.div`
--border-radius: ${clamp(15, 20)};
--columnGap: ${clamp(20, 30)};
display: flex;
flex-direction: column;
gap: var(--columnGap);
justify-content: space-between;
width: 100%;
height: 100%;
margin: auto;
background-color: var(--azure-15);
padding: 1.9rem 1.5rem;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow-lg);
border: var(--border-lg);
`;
const ButtonsWrapper = styled.div`
display: flex;
justify-content: space-between;
gap: 0.625rem;
`;
export default ProductCard;
Button.tsx
const Button = styled.button<{ mode: "primary" | "secondary" | "dark" }>`
display: grid;
/* justify-content: center; */
align-items: center;
text-align: center;
color: var(--mintCream);
padding: ${clamp(9, 10)} ${clamp(20, 30)}; // this clamp function just generates the css clamp func with calculating the values with some equations
box-shadow: var(--box-shadow-md);
border: var(--border-md);
border-radius: 12px;
text-decoration: none;
cursor: pointer;
transition: all 500ms ease;
font-size: ${clamp(13, 16)};
&:disabled {
cursor: not-allowed;
opacity: 0.7;
}
#media (hover: hover) and (pointer: fine) {
&:hover:enabled {
transform: translateY(-2px); }
}
width: fit-content;
`;
The normal render of this Component is as follows
But when navigating to another path and returning to it on / , it renders like this
This problem only happens in production and works fine on local server...
when inspecting elements, I find that the class name of the Cart Component is also injected into the ShareButton Element
I can't find an explanation for this problem and it gets weirder... When I swap the order of the variables Cart and ShareButton or swap them with the Wrapper Element, some other weird behaviors happen like the one below
In this case, the class name of the Cart Component got injected on the parent elemnt of the parent element of the ProductCard Component
I've probably hit on 4 of these rendering issues but all of them share the same problem, the class name of the Cart Components gets injected on a wrong dom element, whether it's a parent or a sibiling
You can view the first weird behaviour here https://store.ieeenu.com
You will find the product component on the root path, navigate to some path like categories/circuits-1-ecen101 and return to the root and you will see the issue
also, you can review the second weird behavior in a previous build here
https://ieee-nu-store-r243eocii-omarkhled.vercel.app/
I just changed the initialization order of the Cart and ShareButton Components as I said earlier
I don't know whether this problem is from styled-components or from remix (this is the first time for me using remix), it's mentioned here https://github.com/remix-run/remix/issues/1032 that the lack of the babel-plugin-styled-components in remix.run introduces some problems in rehydration but I'm not sure that this is the issue I'm facing...
Thanks for reading this till the end and excuse my English, I'm not a native speaker :"

Effect to selected link gastby styled-component

I have a header and I want to mark the link currently by selecting.
With Styled-Component I must write something like: Const NavLink = styled (link) ... But with the properties of the NAV element there is one that is called ActiveClassname and it can be put on an already defined class, my question is how I define that Independent class with Styled-Component.
I would like to create a class that is called something like Linkactive and that can happen something so ActiveClassname = "Linkactive". But I have not been able to.
code of navMenu
<NavMenu>
{menuData.map((item, index) => (
<NavLink to={item.link} key={index} activeClassName="active">
{item.title}
</NavLink>
))}
</NavMenu>
code with styled-component
const NavMenu = styled.div`
display: flex;
align-items: center;
/* margin-right: -48px; */
#media screen and (max-width: 768px) {
display: none;
}`
const NavLink = styled(Link)`
color: #00286d;
display: flex;
align-items: center;
text-decoration: none;
padding: 0 1rem;
height: 100%;
cursor: pointer;
`
You can define static props/attributes using .attrs
This is a chainable method that attaches some props to a styled
component.
const NavLink = styled(Link).attrs(() => ({
activeClassName: "LinkActive",
}))`
color: #00286d;
display: flex;
align-items: center;
text-decoration: none;
padding: 0 1rem;
height: 100%;
cursor: pointer;
&.LinkActive {
// Apply active style here
}
`
If you wanted to use the activeClassName. You can create a class selector on the styling of your NavMenu.
That way, it would only affect .active class of direct/deep child nodes of your NavMenu
const NavMenu = styled.div`
display: flex;
align-items: center;
& .active {
// whatever styling you want
}
#media screen and (max-width: 768px) {
display: none;
}
`;

Reusing existing CSS in styled-component

We've a large project that exist of multiple styled components.
But for a next release and design update of that component we'll working together with a new partner that will deliver the styleguide and a CSS file that they are created for our client.
So I'm looking how I can re-use the styles of our partner in a styled component.
Do you think it's a good idea to do something like:
const PrimaryButton = styled(".btn-primary)``.
Instead of:
const PrimaryButton = styled.button``;
Actually, I can not find any working example, thus I think it's not possible... So, does someone know how I can do something like this?
Ehm, and for some reason I want to avoid to have something like this...
<PrimaryButton className="btn-primary"></PrimaryButton>
You can reuse styled components by extending the styles.
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// A new component based on Button, but with some override styles
const PrimaryButton = styled(Button)`
color: blue;
border-color: blue;
`;

Trying to import component but getting error

I am creating a Tetris game and a created a component (StyledDisplay), which I an trying to import but I am getting an error for my Display.Js page that says the following:
Attempted import error: 'StyledDisplay' is not exported from
'./styles/StyledDisplay'.
I know it's a very dumb question, but can someone look at how I am importing and exporting it? I was fairly confident I was exporting the file and importing it the correct way, but a new set of eyes would not hurt.
This is how I have my Display.js folder, which is where I am importing:
import React from 'react';
import { StyledDisplay } from './styles/StyledDisplay';
const Display = ({ gameOver, text }) =>(
<StyledDisplay gameOver={gameOver}>{text}</StyledDisplay>
)
export default Display;
This is how I have my Displayed.Js folder, which is where I created the component:
import styled from 'styled-components';
export const StyledDisplayed = styled.div`
box-sizzing: border-box;
display: flex;
align-items: center;
margin: 0 0 20px 0;
padding: 20px;
border: 4px; solid #333;
min-height: 30px;
width: 100%;
border-radius: 20px;
color: ${props => (props.gameOver ? 'red' : '#999')};
background: #000;
font-family: Pixel, Arial, Helvetica, sans-seriff;
font-size: 0.8rem;
`;
This is how I have my files set up in Visual Studio Code:
Your export is named StyledDisplayed not StyledDisplay.
You also appear to have some additional typos like box-sizzing and sans-seriff.
Change export const StyledDisplayed to export const StyledDisplay.
P.S. You have misspellings in your CSS that might cause weird visuals.

Passing a custom class/style to a styled-component in Gatsby (React)

I've created the following styled-component for my gatsby project.
import React from "react"
import styled, { css } from 'styled-components'
const Button = styled.div`
background-color: #4E58F5;
width: 200px;
padding: 20px;
margin-right: 30px;
margin-top: 30px;
border-radius: 30px;
color: #FFFFFF;
transition: background-color 0.25s ease;
${props => props.primary && css`
background-color: #FFF;
color: red;
`}
`;
export default props => (
<Button>{props.buttonText}</Button>
)
I've not found the examples in the documentation to be clear or consistent enough to understand how I should be passing in the "primary" option to my components.
I'm trying to do the following, on my index.js page. The Button renders, but the primary word has no effect. What am I missing here?
<Button primary buttonText="Submit" />
The component you're exporting, does not recognize the primary property, and thus cannot pass it on to the Button element. You can fix this either by exporting the styled component itself, or by passing unrecognized props to the Button.
const Button = styled.div`
[...]
`;
export default Button;
OR
export default ({buttonText, ...props})=>(
<Button {...props}>{buttonText}</Button>
);

Resources