In my react app I have buttons for logging in and out. Logging out isn't a big deal because it's never made active. When using LinkContainer (which is great) it will add an active class of active when that route is selected. This is great for everything except buttons. When it adds the `active class to my button it adds a padded background color behind the button. I don't want that. Heres the code and image now:
And here's the code:
import { Glyphicon, Nav, NavItem, Button } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';
<Nav>
<LinkContainer to={'/'} exact>
<NavItem>
<Glyphicon glyph='home' /> Home
</NavItem>
</LinkContainer>
<LinkContainer to={'/documents'}>
<NavItem>
<Glyphicon glyph='education' /> User Documents
</NavItem>
</LinkContainer>
<LinkContainer to={'/login'}>
<NavItem>
<Button bsStyle="primary" block>
<span className='glyphicon glyphicon-log-in'></span>Login
</Button>
</NavItem>
</LinkContainer>
</Nav>
I want it to set that active class on everything other than my buttons.
Using react-bootstrap and react-router-bootstrap
After looking through the code on react-router-bootstrap and a bunch of different articles and posts I figured it out.
I had to change:
<LinkContainer to={'/login'}>
<NavItem>
<Button bsStyle="primary" block>
<span className='glyphicon glyphicon-log-in'></span>Login
</Button>
</NavItem>
</LinkContainer>
To:
<LinkContainer to={'/login'} activeClassName="">
<NavItem>
<Button bsStyle="primary" block>
<span className='glyphicon glyphicon-log-in'></span>Login
</Button>
</NavItem>
</LinkContainer>
Making the activeClassName="" worked as it would make sure there was no active class being set.
Extremely helpful for buttons. I hope this saves people time. Here's what it looked like after for comparison:
Related
So I'm using styled components and found the only way to trigger my function is with a ternary operator that wraps my entire navbar component. The problem is I have to recopy the entire component code into the : statement which basically means I'm writing my nav component code twice just to get the ternary to work properly.
Is there a way to not repeat it and write the ternary with the least amount of code?
So here's my code issue
return (
<>
// If scroll is true, I want to add this active prop onto my <Nav>
{scroll ? (
<Nav active click={click}>
<NavbarContainer>
<NavLogo to="/" onClick={closeMobileMenu}>
<NavIcon />
EXPLOR
</NavLogo>
<MobileIcon onClick={handleClick}>
{click ? <FaTimes /> : <FaBars />}
</MobileIcon>
<NavMenu onClick={handleClick} click={click}>
<NavItem>
<NavLinks to="/">Home</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/images">Images</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/products">Products</NavLinks>
</NavItem>
</Nav>
:
// If the scroll is false, I remove the active prop from my nav
(
<Nav click={click}>
<NavbarContainer>
<NavLogo to="/" onClick={closeMobileMenu}>
<NavIcon />
EXPLOR
</NavLogo>
<MobileIcon onClick={handleClick}>
{click ? <FaTimes /> : <FaBars />}
</MobileIcon>
<NavMenu onClick={handleClick} click={click}>
<NavItem>
<NavLinks to="/">Home</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/images">Images</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/products">Products</NavLinks>
</NavItem>
</Nav>
}
</>
The whole point is so I can trigger this active prop from my styled component
background: ${({ active }) => (active ? "#141414" : "transparent")};
But as you can see I had to copy my entire component code twice because the <Nav> that has the active prop wraps around my entire code.
Is there an easier way to toggle the active prop with styled components without having to recopy my entire navbar in the : or statement?
Assuming active is a booelan you can smply set active={scroll } like so
<Nav active={scroll} click={click}>
.....
</Nav>
I have a basic reactstrap implementation in my app. The menu items display as configured in a nice, responsive way. One of the configured top-level menu items is "Reports" and I need to add 2 selectable submenu items for 2 different reports under this top-level menu item.
Does proper responsive design dictate that only top-level menu items should display on the main page for proper responsive handling? Or is there a proper way to configure submenu items for this scenario? I'm not sure if I need to configure a more customized navigation design like this:
https://reactstrap.github.io/components/navs/
Or does the constraint exist because that is simply considered proper design for responsive websites?
I have a couple of responsive websites with several layers of submenus and i works well.
In Reactstrap there is an example of how to do expanding submenus. This is copied from https://reactstrap.github.io/?path=/docs/components-nav--navs#tabs
import React, { useState } from 'react';
import {
Nav,
NavItem,
Dropdown,
DropdownItem,
DropdownToggle,
DropdownMenu,
NavLink,
} from 'reactstrap';
function Example(props) {
const [dropdownOpen, setDropdownOpen] = useState(false);
const toggle = () => setDropdownOpen(!dropdownOpen);
return (
<Nav tabs>
<NavItem>
<NavLink href="#" active>
Link
</NavLink>
</NavItem>
<Dropdown nav isOpen={dropdownOpen} toggle={toggle}>
<DropdownToggle nav caret>
Dropdown
</DropdownToggle>
<DropdownMenu>
<DropdownItem header>Header</DropdownItem>
<DropdownItem disabled>Action</DropdownItem>
<DropdownItem>Another Action</DropdownItem>
<DropdownItem divider />
<DropdownItem>Another Action</DropdownItem>
</DropdownMenu>
</Dropdown>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Another Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled href="#">
Disabled Link
</NavLink>
</NavItem>
</Nav>
);
}
export default Example;
As you can see it uses useState to hold flags for the openness of the menu item. You can modify this to hold state for whether items are "selected" or whatever, then just draw with that state in mind, for example:
<DropdownItem disabled>Action</DropdownItem>
to
const [actionSelected, setActionSelected] = useState(false);
<DropdownItem disabled={actionSelected} onClick={()=>setActionSelected(true)}>Action</DropdownItem>
I am currently trying to learn React.js for a school project and am having trouble with toggling images in combination with active links (I have searched high and low for a tutorial with no avail). My site is going to look similar to the old time Kingdom Hearts 1 menu theme; the Navbar looks like the following image.
As shown in the above image, the home page is hard-coded to be "active." What I need help with is making each link appear in this "active" state when selected/active. When a user clicks on one of the NavLinks, the image should go from grey to black/orange. When a link is not selected (or inactive), the image should go from black/orange back to grey. Active/selected links should also have black text while inactive links have grey. So far, all I have found out is how to toggle a singular class but not multiple. Overall, I really don't know how to go about this at all. How do I toggle one NavLink active and change its image while also changing all other NavLinks to inactive, changing their images as well? Any help would be much appreciated. I have the following code for my Navbar so far:
export class NavMenu extends Component {
static displayName = NavMenu.name;
constructor(props) {
super(props);
this.toggleNavbar = this.toggleNavbar.bind(this);
this.state = {
collapsed: true
};
}
toggleNavbar() {
this.setState({
collapsed: !this.state.collapsed
});
}
render() {
return (
<Navbar
fixed="bottom"
className="navbar-expand-sm navbar-toggleable-sm ng-white border-top mb-3"
light
>
<NavbarToggler onClick={this.toggleNavbar} className="mr-2" />
<Collapse
className="d-sm-inline-flex flex-sm-row-reverse"
isOpen={!this.state.collapsed}
navbar
>
<ul className="navbar-nav mr-auto">
<NavItem>
<NavLink
tag={Link}
id="navHome"
className="text-dark active"
to="/"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
hidden
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
/>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink
tag={Link}
d="navResume"
className="text-dark inactive"
to="/resume"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
hidden
/>
Resume
</NavLink>
</NavItem>
<NavItem>
<NavLink
tag={Link}
d="navContact"
className="text-dark inactive"
to="/contact"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
hidden
/>
Contact
</NavLink>
</NavItem>
<NavItem>
<NavLink
tag={Link}
d="navFetch"
className="text-dark inactive"
to="/fetch-data"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
hidden
/>
Fetch data
</NavLink>
</NavItem>
</ul>
</Collapse>
<div>
{' '}
<PlaySound child={this.state.child} />{' '}
</div>
</Navbar>
);
}
}
First of all remove you css (images) into a seperate css file. Make a class and put your css into that. Something like this
<NavLink tag={Link} d="navResume" className="text-dark inactive resumeImage" to="/resume">
Resume
</NavLink>;
in your css file
.resumeImage {
//declare your image styles here
}
Repeat above for all your Navlinks.
Now keep those styles which you only want to apply to the active link in a seperate class and apply that class to all the Navlinks like below
<NavLink
tag={Link}
d="navResume"
className="text-dark inactive resumeImage"
activeClassName="activestyleclass"
to="/resume"
>
Resume
</NavLink>;
You can check the current URL and change the image based on the url since active class should be depend on the url too.
You can use react hook useLocation to get current URL.
import { useLocation } from 'react-router-dom';
const Component= () => {
const [pathname, setPathname] = useState('/');
const location = useLocation();
useEffect(() => {
setPathname(location.pathname);
}, [location]);
return (
<nav className="navbar">
<NavLink to="/" className="navbar-item">
{pathname === '/' ? (
<img src="/images/navbar/home_active.png" alt="Home" />
) : (
<img src="/images/navbar/home.png" alt="Home" />
)}
</NavLink>
.....
I'm building a navbar that is expected to be responsive when it switches to mobile devices. In other words, collapse when mobile, then when the navitems are selected / clicked, it should route to the path and collapse all navitems to a toggle-style bar. However, below a snapshot of what I got and it's associated code:
CODE:
render() {
return (
!this.state.isAuthenticating &&
<div className="App">
<Navbar fluid collapseOnSelect>
<Navbar.Header>
<Navbar.Brand>
<LinkContainer to="/">
<a>
<img src={logo} alt="logo" height="70" width="75"/>
<p>hybriData</p>
</a>
</LinkContainer>
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav pullRight>
{this.state.isAuthenticated
? <Fragment>
<LinkContainer to="/settings">
<NavItem>Settings</NavItem>
</LinkContainer>
<NavItem eventKey={1} onClick={this.handleLogout}>Logout</NavItem>
</Fragment>
: <Fragment>
<LinkContainer to="/About Us">
<NavItem eventKey={2}>About Us</NavItem>
</LinkContainer>
<LinkContainer to="/Contact">
<NavItem eventKey={3}>Contact</NavItem>
</LinkContainer>
<LinkContainer to="/works">
<NavItem eventKey={5}>Works</NavItem>
</LinkContainer>
<LinkContainer to="/signin">
<NavItem eventKey={6}>SignIn</NavItem>
</LinkContainer>
</Fragment>
}
</Nav>
</Navbar.Collapse>
</Navbar>
</div>
);
}
I also integrated some of this solution react-bootstrap how to collapse menu when item is selected using the expanded and onSelect props of the navbar and nav's activeKey and onSelect props to achieve desired functionality but to no fruition. How can I implement desired functionality of having all navitem's collapsed when any path(s) is navigated to , clicked / selected? Thank you
Here is a simplified working example. It's about the order of items. If you look at the bootstrap CSS, you see some styles like
.nav > li {
position: relative;
display: block;
}}
The > symbol is a selector that selects all immediate descendants or children (first 'wrap layer' only, not applied to second 'wrap layer'), namely if you have
<ul class="nav">
<div>
<li>something</li>
<li>something</li>
</div>
</ul>
the styles are not applied, while
<ul class="nav">
<li>something</li>
<li>something</li>
</ul>
works. In your case, try replacing the <Fragment> with <Nav> and remove the outer <Nav>.
Another part you may want to modify is the LinkContainer wrapping the NavItem part. Usually we have <li> (NavItem) wrapping <a> (Link) but not the other way round.
Although react-bootstrap makes the code easier to read, it abstracts the details and may be harder to get something working. If you have difficulty with react-bootstrap, I suggest you to stick with pure bootstrap elements. The codes are slightly longer but the appearance is the same. You can follow w3schools to use bootstrap styles.
I'm using React Bootstrap and React Router Bootstrap for my Navbar, and I am making a user profile dropdown menu list.
I'd like to be able to have an user's avatar show up in place of the 'title' property. (The same idea as the user profile dropdown on Github)
Is this possible? I don't see any options to use an image instead of title for NavDropdown
<Navbar inverse>
<Navbar.Header>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav pullRight>
<NavDropdown eventKey={ 3 } id="profile-dropdown" >
<LinkContainer to="/profile/edit" >
<NavItem eventKey={ 3.4 } > Edit </NavItem>
</LinkContainer>
<LinkContainer to="/logout">
<Logout eventKey={ 3.5 } />
</LinkContainer>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Navbar>
Would a SplitButton or straight Dropdown be a better option? I don't really see much that the "NavDropdown" is adding to the HTML.
The NavDropdown's title property can take any React element as a value. This is what I did:
<Nav pullRight>
<NavDropdown eventKey={1}
title={
<div className="pull-left">
<img className="thumbnail-image"
src={src}
alt="user pic"
/>
{user.username}
</div>
}
id="basic-nav-dropdown">
<MenuItem eventKey={1.1} href="/profile">Profile</MenuItem>
<MenuItem divider />
<MenuItem eventKey={1.3}>
<i className="fa fa-sign-out"></i> Logout
</MenuItem>
</NavDropdown>
</Nav>
You'll probably need to adjust the css a little bit.
You can also use the <Image /> component, e.g.
const UserMenu = (
<Image
src={'https://github.com/mshaaban0.png'}
alt="UserName profile image"
roundedCircle
style={{ width: '40px' }}
/>
)
<NavDropdown id="nav-dropdown-dark-example" title={UserMenu}>
//....
</NavDropdown>