Styling a Router Link with styled-components - javascript

What is the best way to style the Link using the styled-components library in the code that follows.
I can find lots of examples to work with anchor tag but none to work with react-router link.
Am I going about the correct way.
import React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
const Nav = ({ className }) => {
return (
<div className={className}>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</div>
);
};
export default styled(Nav)`
color: white;
text-align: left;
background: teal;
width: 100%;
ul {
color: red;
display: flex;
flex-direction: row;
border: 1px solid green;
list-style: none;
li {
padding: 15px 15px;
border: 2px solid purple;
}
}
`;
Thanks
Joseph Shanahan

Yes thanks for your help. A slimmed down version of what I will implement is as follows.
It also has the advantage in that I did not have to implement an unordered list.
import React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
const Nav = ({ className }) => {
return (
<div className={className}>
<NavLink to="/">Home</NavLink>
<NavLink to="/about">About</NavLink>
</div>
);
};
const NavLink = styled(Link)`
padding: 20px;
color: white;
text-decoration: none;
&:hover {
color: red;
background: blue;
}
`;
export default styled(Nav)`
color: white;
width: 100%;
display: flex;
justify-content: flex-end;
`;
Thanks Joseph Shanahan

You are in the right way, but little wrong, instead of using ul you just pass the component reference.
export default styled(Nav)`
color: white;
text-align: left;
background: teal;
width: 100%;
${Link} {
/* style for Link Component */
}
`;
Check this answer, it's very familiar.

react-router link translates to after all in <a> tags so style them in the same way you would style an <a> tag
so let's say, you need to change their color to red then:
ul {
color: red;
}
won't work, you will need to do:
ul a {
color: red;
}

If you just want to style the Link component, then the usual way in my experience is to create a styled component like so:
const NavLink = styled(Link)`
/* Link styles */
`
And then just render it like <NavLink>Home</NavLink>.
This also makes it easy to reuse this styled component.

Related

How to design Custom Tab in react-bootstrap

I am using react-bootstrap components. I am using tabs in my project. I am also using styled components also. I have used tabs which looks like this
But My Requirement was this
When the tab is selected, i need only a line in below of it. And other tab names should be in grey color. I searched but can't find proper solutions. Please help me with some solutions.
Here's the Code I tried:
import Tab from "react-bootstrap/Tab";
import Tabs from "react-bootstrap/Tabs";
import styled from "styled-components";
import "bootstrap/dist/css/bootstrap.css";
export default function App() {
const CustomTabs = styled(Tabs)`
border-bottom: 0.5px solid gray;
color: white;
`;
const CustomTab = styled(Tab)`
color: gray;
font-size: 19px;
:active {
color: black;
border-bottom: 3px solid blue;
}
`;
return (
<div>
<CustomTabs defaultActiveKey="tab1" id="uncontrolled-tab-example">
<CustomTab eventKey="tab1" title="Tab1">
Tab1 Content
</CustomTab>
<CustomTab eventKey="tab2" title="Tab2">
Tab2 Content
</CustomTab>
<CustomTab eventKey="tab3" title="Tab3">
Tab3 Content
</CustomTab>
</CustomTabs>
</div>
);
}
I have found these css. But I don't how to use it in styled components. Anyone help me with this
.nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active {
color: orangered;
background-color: #fff;
border-color: none;
}
.nav-tabs {
border-bottom: none;
}
.nav-tabs .nav-link:hover{
color: color:gray
}
Ideally you don't want apply styled-components directly to the react-bootstrap components, but what you can do is create an element to wrap the react-bootstrap components and use the CSS classes you get from inspecting to make it work.
const StyledWrap = styled.div`
& .nav-tabs li {
background-color: red;
}
& .nav-tabs .active li {
background-color: yellow;
}
`
const CustomNavbar = (props) => {
return (
<StyledWrap>
<NavItem active={true} />
<NavItem />
</StyledWrap>
)
}

React js app sidebar selected item not highlighted

I created this react app with a side bar, and it looks pretty good, but one thing I can't figure out is how to mark the item (page link) that was clicked.
Here is the code, I added activeClassName="selected" to the SidebarLink const, and added it to the styled-component, but it's not working.
import React, { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
const SidebarLink = styled(Link)`
/*border: 3px solid green;*/
display: flex;
color: #e1e9fc;
justify-content: space-between;
align-items: center;
padding: 20px;
list-style: none;
height: 60px;
text-decoration: none;
font-size: 18px;
&:hover {
background: #252831;
border-left: 4px solid #ffbc2e;
cursor: pointer;
}
.selected {
color: red;
}
`;
const SidebarLabel = styled.span`
margin-left: 16px;
`;
/* Used for Training dropdown */
const DropdownLink = styled(Link)`
/*border: 3px solid red;*/
background: #252831;
height: 60px;
padding-left: 3rem;
display: flex;
align-items: center;
text-decoration: none;
color: #f5f5f5;
font-size: 16px;
font-weight: bold;
&:hover {
background: #48526F;
border-left: 4px solid #ffbc2e;
cursor: pointer;
}
`;
const SubMenu = ({ item }) => {
const [subnav, setSubnav] = useState(false);
const showSubnav = () => setSubnav(!subnav);
return (
<>
<SidebarLink to={item.path} onClick={item.subNav && showSubnav} activeClassName="selected" exact>
<div className="sidebarTextContainer">
<div className="sidebarIcon">{item.icon}</div>
<div className="sidebarText"><SidebarLabel>{item.title}</SidebarLabel></div>
</div>
<div>
{item.subNav && subnav
? item.iconOpened
: item.subNav
? item.iconClosed
: null}
</div>
</SidebarLink>
{subnav &&
item.subNav.map((item, index) => {
return (
<DropdownLink to={item.path} key={index}>
{item.icon}
<SidebarLabel>{item.title}</SidebarLabel>
</DropdownLink>
);
})}
</>
);
};
export default SubMenu;
Anyone got any idea please on how to fix this?
Even though you're asking about remembering which item was clicked, I think what you actually want is that the link corresponding to the current page be highlighted as active.
If you're using react-router v6, you should use NavLink instead of Link (docs).
A <NavLink> is a special kind of <Link> that knows whether or not it is "active".
By default, an active class is added to a <NavLink> component when it is active.
You should update the imported component and remove the activeClassName.
const SidebarLink = styled(NavLink)`
// ...
&.active {
color: red;
}
`
// ...
<SidebarLink to={item.path} onClick={item.subNav && showSubnav} exact>
...
</SidebarLink>
If you're using react-router v5, then you should also use NavLink but you have to pass the activeClassName, like you do in your example. In this case you simply need to substitute Link for NavLink.
Also note that you nested CSS syntax is incorrect. It is applied to the children of SidebarLink, not on SidebarLink itself. You'd want to replace .selected { color: red; } with &.selected { color: red }.

custom label on select as floating

I am trying to create a floating label select component, So the select box will have a label on click of that it will show a dropdown options. Like this With an icon and override the native browser options.
I was able to achieve using input field, but i am not able to understand how to create such a like component.
Dropdown.js
import React from "react";
import {
DropdownWrapper,
StyledSelect,
StyledOption,
StyledLabel
} from "./style";
export function Dropdown(props) {
return (
<DropdownWrapper onChange={props.onChange}>
<StyledLabel htmlFor={props.id}>{props.formLabel}</StyledLabel>
<StyledSelect id={props.id} name={props.id}>
{props.children}
</StyledSelect>
</DropdownWrapper>
);
}
export function Option(props) {
return <StyledOption selected={props.selected}>{props.value}</StyledOption>;
}
Style.js
import styled from "#emotion/styled";
export const DropdownWrapper = styled.div`
display: flex;
flex-flow: column;
justify-content: flex-start;
`;
export const StyledSelect = styled.select`
height: 100%;
padding: 0.5rem 0;
margin-bottom: 1rem;
border: none;
border-bottom: 1px solid black;
outline: none;
-webkit-appearance: none;
-moz-appearance: none;
text-indent: 1px;
text-overflow: "";
`;
export const StyledOption = styled.option`
color: ${(props) => (props.selected ? "lightgrey" : "black")};
`;
export const StyledLabel = styled.label`
margin-bottom: 1rem;
`;
Any help appreciated, here is what i have tried so far. link

vue js scoped slots styles error with vue styled components

I tried using vue-styled-compoenents to style a simple button with some text inside but the styles dont work and I get a scopedSlots issue in the parent component.
This is the code for the button and the text components in component.js
import styled from 'vue-styled-components';
export const sLabel = styled.label`
color: #000;
`;
export const sButton = styled.div`
height: 1rem;
width: 2rem;
background-color: #000;
${sLabel} {
color: #fff;
}
`;
This is my code in my page.
<template>
<sButton>
<sLabel>Button</sLabel>
</sButton>
</template>
<script>
import { sButton, sLabel } from './component.js'
export default {
components: {
sButton,
sLabel
}
}
</script>
This is the result I get under the sButton styles and nothing under sLabel
), scopedSlots: this.$scopedSlots
But Instead if I just use this code it works.
export const sButton = styled.div`
height: 1rem;
width: 2rem;
background-color: #000;
label {
color: #fff;
}
`;
The styles are applied to the parent component if I declare the parent component before the child even if the styles are under the child.
export const sButton = styled.div`
height: 1rem;
width: 2rem;
background-color: #000;
${sLabel} {
color: #fff;
}
`;
export const sLabel = styled.label`
color: #000;
`;
Can someone tell me where my code is incorrect and what is causing these issues ?

Dynamically add styles to styled-jsx in Next.js

Please see the code. I want to add some extra style for the about link conditionally, so I am adding it inside ${} of the template string for the tag. This doesn't apply the new styles.
I have tried by concatenating the template strings. That didn't work either.
I cannot set style={style} in the tag because then I won't be able to use the :hover style.
import Link from 'next/link'
import { withRouter } from 'next/router'
const Header = ({ children, router, href }) => {
const isIndex = router.pathname === "/";
const isAbout = router.pathname === "/about";
return (
<div>
<Link href="/">
<a id="home">Timers</a>
</Link>
<Link href="/about">
<a id="about">About</a>
</Link>
<style jsx>{
`
a {
font-family: 'Montserrat Subrayada', sans-serif;
color: #ffffff;
text-decoration: none;
font-size: 24px;
padding: 2px;
margin-right: 30px;
}
a:hover {
color: #000000;
background-color: #ffffff;
border-radius: 2px;
}
${isAbout ? `
#about {
background-color: red;
color: #000000;
}
#about:hover {
background-color: blue;
color: #ffffff;
}
` : ``}
`
}</style>
</div>
)}
export default withRouter(Header)
How can I apply conditional styles?
The solution is to only change the property values dynamically, rather than add entire new selectors in a single conditional you must do it for each property, like this:
<style jsx>{
`
a {
font-family: 'Montserrat Subrayada', sans-serif;
color: #ffffff;
text-decoration: none;
font-size: 24px;
padding: 2px;
margin-right: 30px;
border-radius: 2px;
}
a:hover {
color: #000000;
background-color: #ffffff;
}
#home {
background-color: ${isHome ? "#ffffff" : ""};
color: ${isHome ? "#000000" : ""};
}
#about {
background-color: ${isAbout ? "#ffffff" : ""};
color: ${isAbout ? "#000000" : ""};
}
`
}</style>
(I figured out the answer to my question while I was asking it, so I thought i'd just post it with my answer anyway in case someone else needs it)
Since styled-jsx compiles styles at build time, it cannot preprocess dynamic styles, this is a limitation that is mentioned in the docshere
Plugins make it possible to use popular preprocessors like SASS, Less, Stylus, PostCSS or apply custom transformations to the styles at compile time.

Categories