React Router Dom v6 - hover styles on active nav - css

I have a navbar that has a hover state as well as active nav styles. I'm trying to get my ACTIVE navlink to have a custom hover state as well. Right now the active styles are overriding the hover state. how do i maintain my hover state styles over the active nav link?
whats happening....
active nav styles (looks good)
when i hover over the active nav (want the text to be white)
<NavLink
to="/games"
className='nav-link'
style={({ isActive }) =>
isActive
? {
color: '#0E1333',
borderBottom: 'solid 2.5px #0E1333',
paddingBottom: 2.5
}
: {}
}
>
<img src={require('../../assets/icons/gamesIcon.png')} id='projects-icon' />
Games
</NavLink>
stylesheet
.nav-link {
text-decoration: none;
background-color: white;
color: #0E1333;
font-family: 'Gilroy-ExtraBold';
font-size: 18px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100%;
padding-left: 25px;
padding-right: 25px;
}
.nav-link:hover {
background-color: #0E1333;
color: #fff;
}
I've tried...
a.nav-link.active:hover {
color: white
}

Move the "style" logic to the className prop and add the "active" class. The inline style attribute adds higher CSS specificity and overrides styles defined in your CSS.
<NavLink
to="/games"
className={({ isActive }) =>
["nav-link", isActive ? "active" : null]
.filter(Boolean)
.join(" ")
}
>
<img src={require('../../assets/icons/gamesIcon.png')} id='projects-icon' />
Games
</NavLink>
CSS
.nav-link {
text-decoration: none;
background-color: white;
color: #0E1333;
font-family: 'Gilroy-ExtraBold';
font-size: 18px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100%;
padding-left: 25px;
padding-right: 25px;
}
.nav-link:hover, .active:hover {
background-color: #0E1333;
color: #fff;
}
.active {
color: #0E1333;
border-bottom: solid 2.5px #0E1333;
padding-bottom: 2.5rem;
}
Note the the NavLink component already adds an "active" classname by default, so the link logic can be simplified to:
<NavLink to="/games" className="nav-link">
<img src={require('../../assets/icons/gamesIcon.png')} id='projects-icon' />
Games
</NavLink>

That's because style props in NavBar overrides the hover state declarations.
Possible Solution would be remove the style prop and declare styles directly in .css file.
<NavLink to="/games" className="nav-link">
<img src={require("../../assets/icons/gamesIcon.png")} id="projects-icon" />
Games
</NavLink>;
a.nav-link.active {
color: #0E1333;
border-bottom: solid 2.5px #0E1333;
padding-bottom: 2.5em;
}
a.nav-link.active:hover {
color: white
}

Related

Applying :not(:last-child) to parent class with SCSS

I have JSX which renders a card-like component:
{userResourceGuides && userResourceGuides.map((guide) => (
<div className='UserResourceGuides' key={guide.id}>
<div className='UserResourceGuides__col-1'>
<h2>{guide.file_label}</h2>
<p>From: {guide.service_name}</p>
</div>
<div className='UserResourceGuides__col-2'>
<div>
<a href={guide.file_url} target='_blank' rel='noreferrer'>
<span><AiOutlineLink /></span>
</a>
<p>View</p>
</div>
<div>
<span><AiOutlineDelete /></span>
<p>Delete</p>
</div>
</div>
</div>
))}
UserResourceGuides is the parent class. How can I apply a :not(:last-child) selector to this class?
SCSS
.UserResourceGuides {
display: flex;
justify-content: space-between;
margin: 1rem;
&:not(:last-child) {
border: 1px solid red; // all entries have border styling applied
}
&__col-1 {
margin-left: 2rem;
h2 {
color: $color-blue-subheader;
font-size: 1.8rem;
}
p {
color: black;
font-weight: 300;
font-size: 1.2rem;
}
}
&__col-2 {
display: flex;
align-items: center;
margin-right: 1rem;
...
The current styling I have still renders all entries with the border styling applied, and does not exclude the last-child. Not my desired result. What is my error here?

How to remove NavLink styling for unselected Routes

I would like to know how to restore to the default style of NavLink as marked in the screenshot below. The color should be white and without the underlines. You would find my code below the screenshot:
Home is the default path that is currently selected. The activeClass property on this is working as it should.
The code:
const NavBar = () => {
return(
<div className="navBar">
<div className="logo">LOGO</div>
<div className="navOptions">
<ul>
<li>
<NavLink exact activeClassName="activeClass" to="/">Home</NavLink>
</li>
<li>
<NavLink exact activeClassName="activeClass" to="/advanceFilter">Advanced Search</NavLink>
</li>
<li>
<NavLink exact activeClassName="activeClass" to="viewAll">View All</NavLink>
</li>
<li>Logout</li>
</ul>
</div>
</div>
);
}
export default NavBar;
The CSS:
.navBar {
display: flex;
justify-content: space-between;
width: 100%;
height: 100%;
color: white;
font-weight: bold;
}
.logo {
display: flex;
flex: 1;
align-items: center;
padding-left: 50px;
}
.navOptions {
display: flex;
justify-content: flex-end;
flex: 1;
height: 100%;
}
//The li items don't have the color and text-decoration properties on them
li {
display: inline;
margin-right: 20px;
cursor: pointer;
height: 100%;
text-decoration: none;
color: white;
}
li:hover {
background-color: gray;
}
ul {
margin-right: 40px;
list-style-type: none;
}
.activeClass {
text-decoration: none;
color: purple;
}
The NavLink component renders an anchor <a /> tag, update the selector in your CSS to also target anchor tags that are children of li elements.
li, li a {
display: inline;
margin-right: 20px;
cursor: pointer;
height: 100%;
text-decoration: none;
color: white;
}
Alternatively you could also specify a "navlink" class and apply default non-active CSS styling there.

grid-template-columns not respected in Safari 13

I'm having an issue where the grid columns in my React component are showing up on separate rows in Safari 13. Numerous Google searches have come up with nothing and I'm really hoping somebody here can help. Here is the code of my React component (I've left out a bunch of state stuff and functions that aren't relevant):
import React, { useState, useRef } from 'react'
import classNames from 'classnames'
import SlideToggle from 'react-slide-toggle'
import styles from './shoppingListItem.module.css'
const ShoppingListItem = ({
itemId,
listTitle,
canEdit,
description,
quantity,
notes
}) => {
const [currentQuantity, setCurrentQuantity] = useState(quantity)
return(
<div className={styles.root}>
<button className={styles.button} onClick={toggleDetails}>
<span ref={headerRef} className={classNames(styles.header, { [styles.headerEditable]: canEdit })}>
{canEdit &&
<span className={styles.editIcons} ref={iconsRef}>
<div className={styles.icon} ref={deleteRef} onClick={destroyItem}><FontAwesomeIcon className={classNames(styles.fa, styles.destroyIcon
)} icon={faTimes} /></div>
<div className={styles.icon} ref={editRef} onClick={showEditForm}><FontAwesomeIcon className={styles.fa} icon={faEdit} /></div>
</span>}
<h4 className={styles.description}>{description}</h4>
</span>
<span className={styles.quantity}>
{canEdit && <div className={styles.icon} ref={incRef} onClick={incrementQuantity}>
<FontAwesomeIcon className={styles.fa} icon={faAngleUp} />
</div>}
<div className={styles.quantityContent}>
{currentQuantity}
</div>
{canEdit && <div className={styles.icon} ref={decRef} onClick={decrementQuantity}>
<FontAwesomeIcon className={styles.fa} icon={faAngleDown} />
</div>}
</span>
</button>
<SlideToggle toggleEvent={toggleEvent} collapsed>
{({ setCollapsibleElement }) => (
<div className={styles.collapsible} ref={setCollapsibleElement}>
<p className={styles.notes}>{notes || 'No details available'}</p>
</div>
)}
</SlideToggle>
</div>
)
}
The relevant CSS is:
.root {
font-family: 'Quattrocento Sans', Arial, Helvetica, sans-serif;
background-color: var(--main-color);
border-bottom: 1px solid var(--border-color);
}
.root:hover {
background-color: var(--hover-color);
}
.button {
width: 100%;
background: none;
border: none;
border-bottom: 1px solid var(--border-color);
text-align: left;
cursor: pointer;
padding: 0;
display: grid;
grid-template-columns: 2fr 1fr;
}
.fa {
color: var(--title-text-color);
}
.destroyIcon {
margin-right: 8px;
}
.header {
display: inline-block;
padding: 32px 16px;
border-right: 1px solid var(--border-color);
}
.headerEditable {
display: flex;
align-items: flex-start;
}
.editIcons {
display: flex;
flex-direction: row;
margin: auto 12px auto 0;
}
.quantity {
font-family: 'Quattrocento Sans', Arial, Helvetica, sans-serif;
font-size: 1rem;
color: var(--title-text-color);
display: inline-block;
margin: auto 0;
padding: 32px 8px;
display: flex;
justify-content: space-between;
}
.quantityContent {
margin: auto;
}
.icon {
display: inline-block;
padding: 4px;
cursor: pointer;
}
.description {
display: inline-block;
font-family: 'Quattrocento Sans', Arial, Helvetica, sans-serif;
font-size: 1.025rem;
color: var(--title-text-color);
margin: auto 0;
line-height: 1.25;
}
This is what the list item .button element/its children look like in Chrome (i.e., the way it's supposed to look):
This is the way the element looks in Safari (i.e., how it's not supposed to look):
The issue here turned out to be that I was using the button element incorrectly as the slide-toggle trigger and Chrome didn't mind but Safari didn't like it. I had made it a button because of accessibility reasons but I guess that was the wrong way to go. Changing the slide-toggle trigger into a div made it look the same in both Chrome and Safari.

Hover effect not being applied to SVG Nested in NavLink

How do I get the nested SVG to have the same hover effect as the anchor tag? When I hover over one it should change both, but right now they are not being seen as the same entity.
I am trying to apply a style to an SVG on hover. The SVG is nested inside of a NavLink component. The CSS that is class-specific gets applied to the SVG, but the hover for the a tag that the SVG is nested in only applies to the a tag's text. I have tried using just the Link component from react-router-dom. I have noticed that when I removed the text-decoration: none from my CSS, the underline only applies to the text. In the rendered HTML the a tag DOES nest the svg tag.
I have tried wrapping the anchor tag and SVG in a span and giving the span the hover effect, it did not work.
component
import {Link, NavLink} from "react-router-dom";
import logo from '../../assets/LogoOnly_Square_Transparent.png';
import { ReactComponent as CalculatorIcon } from '../../assets/calculator.svg';
import './header.styles.scss';
export const Header = () => {
return (
<nav className="header">
<div className='options'>
<Link className='logo-container' to='/'>
<img src={logo} alt="Logo" className='logo'/>
</Link>
<NavLink to='/calculator' className='header-option'>CALCULATOR<CalculatorIcon className='link-icon'/></NavLink>
</div>
<div className='options-right'>
<Link to='/sign-in-sign-up' className='header-option'>SIGN IN</Link>
</div>
</nav>
)
}
CSS
border-bottom: 1px solid #D1D3D4;
height: 70px;
width: 100%;
display: flex;
justify-content: space-between;
margin-bottom: 25px;
padding: 5px;
.options {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
.logo-container {
width: 70px;
margin: 5px 0;
height: 100%;
.logo {
height: 100%;
}
}
.header-option {
padding: 10px 15px;
font-size: 16px;
.link-icon {
height: 13px;
fill: #58595B;
margin: auto 5px;
}
&:hover {
color: #4FB47C;
fill: #4FB47C;
}
}
}
a {
text-decoration: none;
color: #58595B;
&:hover {
color: #4FB47C;
fill: #4FB47C;
}
}
.options-right {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
.header-option {
padding: 10px 15px;
}
}
}

React button has blue border around it when clicking

Hi I'm making a project with react and I've noticed that with some buttons I make and style they sometimes get this weird looking blue border when clicking it. I tried to get rid of it by setting border:none !important or even trying override the color of it but I can't seem to get it away. I'm just using scss for styling and also have react-bootstrap installed.
this is an example of a button that has the blue border:
code of buttons
// button 1
<button type="button" className="btn employee-button" value={employee} key={employee.id} onClick={(e) => this.onEmployeeClick(employee)}>
<div className={this.state.startId === employee.id ? "selected employee-card" : "employee-card"}>
<Gravatar email={employee.email} className="employee-gravatar" />
<div>
<p className="employee-name">{employee.firstname} {employee.lastname}</p>
<p className="employee-job">{employee.jobTitle}</p>
</div>
</div>
</button>
// button 2
<button className="btn" onClick={this.openPopUp}>Create new client</button>
styling
// button 1
.employee-button {
.employee-card {
display: flex;
flex-direction: row;
background-color: $white;
width: 250px;
height: 70px;
padding: 10px;
border-radius: 10px;
margin-left: 15px;
.employee-gravatar {
border-radius: 5px;
}
div {
margin-top: 10px;
width: 80%;
margin-top: 0;
display: flex;
flex-direction: column;
font-size: 0.9em;
.employee-name{
font-weight:600;
}
.employee-job{
font-weight:500;
margin-top:-10px;
}
}
&:hover {
color:#E27D60;
box-shadow: 0px 18px 40px -12px rgba(182, 181, 181, 0.356);
}
}
}
// button 2
button {
width: 200px;
height: 50px;
color: $black;
font-size: .9em;
margin: 45px 0px;
padding: 12px;
background-color: $plain-white;
font-weight: 700;
border-radius: 5px;
&:hover {
color: #17A9A3;
}
}
I'm hoping that someone can help me with this because this is getting on my nerves
You need to set focus outline for button:
button:focus {outline:none;}
If it doesn't work use !important also.
--> button:focus {box-shadow:none !important;} this solved it
It's outline not a border, to hide it you should use :
outline:none
full example :
button {
width: 200px;
height: 50px;
color: $black;
font-size: .9em;
margin: 45px 0px;
padding: 12px;
background-color: $plain-white;
font-weight: 700;
border-radius: 5px;
outline:none;
&:hover {
color: #17A9A3;
}
&:focus{
outline:none;
}
}

Resources