Close mobile navigation menu after anchor link click - React - reactjs

I am new to React and am trying to create a mobile menu that I somehow created using several online resources. Now the problem is that my mobile menu is not closing after clicking on the Anchor links.
I have three different files (Burger, Navbar, and RightNav). Burger is just for icon transformation, Navbar is for main navigation, and RightNav is the mobile menu.
Can someone please specify how I can close the RightNav after clicking on any menu anchor link?
Burger.jsx file
import React, { useState } from 'react';
import styled from 'styled-components';
import RightNav from './RightNav';
const StyledBurger = styled.div`
width: 2rem;
height: 2rem;
position: fixed;
align-items:center;
right: 20px;
z-index: 20;
display: none;
top: 5%;
#media (max-width: 1000px) {
display: flex;
justify-content: space-around;
flex-flow: column nowrap;
align-items:flex-start;
}
div {
width: 2rem;
height: 0.25rem;
background-color: ${({ open }) => open ? '#00a993' : '#00a993'};
border-radius: 10px;
transform-origin: 1px;
transition: all 0.3s linear;
&:nth-child(1) {
transform: ${({ open }) => open ? 'rotate(45deg)' : 'rotate(0)' };
}
&:nth-child(2) {
transform: ${({ open }) => open ? 'translateX(100%)' : 'translateX(0)'};
opacity: ${({ open }) => open ? 0 : 1};
}
&:nth-child(3) {
transform: ${({ open }) => open ? 'rotate(-45deg)' : 'rotate(0)'};
width: ${({ open }) => open ? '20px':'16px'};
}
}
`;
const Burger = () => {
const [open, setOpen] = useState(false)
return (
<>
<StyledBurger open={open} onClick={() => setOpen(!open)} id="burger" className='burger'>
<div />
<div />
<div />
</StyledBurger>
<RightNav open={open}/>
</>
)
}
export default Burger
RightNav.jsx file
import React from 'react';
import styled from 'styled-components';
import { NavHashLink } from 'react-router-hash-link';
const Ul = styled.ul`
list-style: none;
display: flex;
flex-flow: row nowrap;
li {
padding: 18px 10px;
}
#media (max-width: 1000px) {
z-index: 1;
flex-flow: column nowrap;
background-color: #13161B;
position: fixed;
transform: ${({ open }) => open ? 'translateX(0)' : 'translateX(100%)'};
top: 10%;
right: 0;
width: 100%;
height:auto;
padding: 1.5rem;
align-items: center;
transition: transform 0.3s ease-in-out;
font-size: 16px;
font-family: 'Quicksand', sans-serif;
text-transform: uppercase;
font-weight: 600;
line-height: 7rem;
}
`;
const RightNav = ({ open, setOpen }) => {
return (
<Ul open={open} className="mobile-menu" id="mobile-menu">
<NavHashLink smooth to="/#welcome-section" activeClassName="selected" style={{ color: '#00a993' }}>
What
</NavHashLink>
<NavHashLink smooth to="/#how-section" activeClassName="selected" style={{ color: '#00a993' }}>
How
</NavHashLink>
<NavHashLink smooth to="/#IsItAThing-section" activeClassName="selected" style={{ color: '#00a993' }}>
Why
</NavHashLink>
<NavHashLink smooth to="/#team-section" activeClassName="selected" style={{ color: '#00a993' }}>
Who
</NavHashLink>
<NavHashLink smooth to="/#contact-section" activeClassName="selected" style={{ color: '#00a993' }}>
Where
</NavHashLink>
<a href='https://stories.therelevancehouse.com/' style={{ color: '#00a993' }}>
Stories
</a>
</Ul>
)
}
export default RightNav
Navbar.jsx file
import styled from 'styled-components';
import Burger from './Burger';
import React, { useEffect, useState } from 'react';
import '../App.css';
import logo from '../images/logomain.png'
import ln from '../images/LinkedIN_white.svg'
import medium from '../images/Medium_white.svg'
import twitter from '../images/Twitter_white.svg'
import fb from '../images/Facebook_white.svg'
import instagram from '../images/Instagram_white.svg'
import '../fonts/norwester.ttf'
import linkedinhover from '../images/LinkedinIconHover.svg'
import facebookhover from '../images/FacebookIconHover.svg'
import twitterhover from '../images/TwitterIconHover.svg'
import instagramhover from '../images/InstagramIconHover.svg'
import mediumhover from '../images/MediumIconHover.svg'
import { NavHashLink } from 'react-router-hash-link'
const Nav = styled.nav`
width: 100%;
border-bottom: 2px solid #f1f1f1;
padding: 20px 20px;
display: flex;
justify-content: space-between;
align-items: center;
.logo {
padding: 15px 0;
}
`
const Navbar = () => {
const [show, setShow] = useState(true);
const [lastScrollY, setLastScrollY] = useState(0);
useEffect(() => {
const controlNavbar = () => {
if (typeof window !== 'undefined') {
if ((window.scrollY > lastScrollY) && (window.scrollY > 200) && (window.innerWidth > 1000))
{
// document.getElementById("navbar").style.padding = "30px 10px";
document.getElementById("navtext").style.fontSize = "12px";
document.getElementById("navtext1").style.fontSize = "12px";
document.getElementById("navtext2").style.fontSize = "12px";
document.getElementById("navtext3").style.fontSize = "12px";
document.getElementById("navtext4").style.fontSize = "12px";
document.getElementById("navtext5").style.fontSize = "12px";
document.getElementById("nav-bar-logo1").style.height = "80px";
document.getElementById("nav").style.height = "90px";
// setShow(false);
} else {
setShow(true);
document.getElementById("navtext").style.fontSize = "14px";
document.getElementById("navtext1").style.fontSize = "14px";
document.getElementById("navtext2").style.fontSize = "14px";
document.getElementById("navtext3").style.fontSize = "14px";
document.getElementById("navtext4").style.fontSize = "14px";
document.getElementById("navtext5").style.fontSize = "14px";
document.getElementById("nav-bar-logo1").style.height = "105px";
document.getElementById("nav").style.height = "120px";
}
setLastScrollY(window.scrollY);
}
};
if (typeof window !== 'undefined') {
window.addEventListener('scroll', controlNavbar);
return () => {
window.removeEventListener('scroll', controlNavbar);
};
}
}, [lastScrollY]);
return (
<Nav >
<nav id='nav' className={ `${show && 'nav'}`} >
<a href="./" >
<img id='nav-bar-logo1' className='nav-bar-logo' alt="Marketing, Branding and Communications Agency"
src={logo} />
</a>
<div id='navigation-social'>
<a href='/'>
<img className='social-nav' src={ln} alt='linkedin' onMouseOver={e => e.currentTarget.src = linkedinhover} onMouseOut={e => e.currentTarget.src = ln} />
</a>
<a href='/'>
<img className='social-nav' src={medium} alt='medium' onMouseOver={e => e.currentTarget.src = mediumhover} onMouseOut={e => e.currentTarget.src = medium} />
</a>
<a href='/'>
<img className='social-nav' src={twitter} alt='twitter' onMouseOver={e => e.currentTarget.src = twitterhover} onMouseOut={e => e.currentTarget.src = twitter} />
</a>
<a href='/'>
<img className='social-nav' src={fb} alt='facebook' onMouseOver={e => e.currentTarget.src = facebookhover} onMouseOut={e => e.currentTarget.src = fb} />
</a>
<a href='/'>
<img className='social-nav' src={instagram} alt='instagram' onMouseOver={e => e.currentTarget.src = instagramhover} onMouseOut={e => e.currentTarget.src = instagram} />
</a>
</div>
<div id='navigation-items'>
<NavHashLink id="navtext" smooth to="/#welcome-section" activeClassName="selected" activeStyle={{ color: '#00a993' }}>
What
</NavHashLink>
<NavHashLink id="navtext1" smooth to="/#how-section" activeClassName="selected" activeStyle={{ color: '#00a993' }}>
How
</NavHashLink>
<NavHashLink id="navtext2" smooth to="/#IsItAThing-section" activeClassName="selected" activeStyle={{ color: '#00a993' }}>
Why
</NavHashLink>
<NavHashLink id="navtext3" smooth to="/#team-section" activeClassName="selected" activeStyle={{ color: '#00a993' }}>
Who
</NavHashLink>
<NavHashLink id="navtext4" smooth to="/#contact-section" activeClassName="selected" activeStyle={{ color: '#00a993' }}>
Where
</NavHashLink>
<a id="navtext5" href='https://stories.therelevancehouse.com/'>
Stories
</a>
</div>
</nav>
<Burger />
</Nav>
)
}
export default Navbar

Related

Why are my link tags delayed before activating in react

I set up a list of React Link tags in my website and when one gets clicked on, it should immediately automatically scroll down to the section the user clicks on. That works, however, for whatever reason there's about a 1-2 second delay before this action actually occurs after a click. I've been trying to figure out what is causing this but I can't figure out what the problem is.
Here is the NavBar component:
import React from "react";
import { Link } from 'react-scroll';
import { FaBars, FaTimes } from 'react-icons/fa';
import { useState, useEffect } from "react";
import './Navbar.css';
const Navbar = () => {
const [click, setClick] = useState(false);
const handleClick = () => setClick(!click);
const closeMenu = () => setClick(false);
const [fix, setFix] = useState(window.scrollY >= 950);
useEffect(() => {
const setFixed = () => {
setFix(window.scrollY >= 950);
};
window.addEventListener("scroll", setFixed);
return () => {
window.removeEventListener("scroll", setFixed);
};
}, []);
return (
<div className={fix ? 'header active' : 'header'}>
<nav className={fix ? 'navbar fixed' : 'navbar'}>
<div className='hamburger' onClick={handleClick}>
{click ? (<FaTimes size={30} style={{ color: '#ffffff' }} />)
: (<FaBars size={30} style={{ color: '#ffffff' }} />)}
</div>
<ul className={click ? "nav-menu active" : "nav-menu"}>
<li className='nav-item'>
<Link to="header" spy={true} smooth={true} offset={-100} onClick={closeMenu}>Home</Link>
</li>
<li className='nav-item'>
<Link to="aboutMe" spy={true} smooth={true} offset={-100} onClick={closeMenu}>About</Link>
</li>
<li className='nav-item'>
<Link to="portfolio" spy={true} smooth={true} offset={-100} onClick={closeMenu}>Projects</Link>
</li>
<li className='nav-item'>
<Link to="resume" spy={true} smooth={true} offset={-100} onClick={closeMenu}>Resume</Link>
</li>
</ul>
</nav>
</div>
)
}
export default Navbar;
Here is the css for the NavBar component:
.header {
position: fixed;
height: 90px;
width: 100%;
top: 0;
left: 0;
z-index: 1;
transition: .3s ease-in;
overflow: hidden;
background-color: transparent;
}
.header.active {
background-color: rgba(0,0,0,.9);
}
.header .navbar {
display: flex;
justify-content: center;
align-items: center;
margin: auto;
height: 100%;
padding: 0 1rem;
}
.header .nav-menu a {
color: #ffffff;
}
.header .nav-menu {
display: flex;
}
.header .nav-item {
padding: 1rem;
font-weight: 500;
}
.header .nav-item a:hover {
padding-bottom: 4px;
color: #d4af37;
cursor: pointer;
}
.nav-menu a.active {
color: #d4af37;
text-decoration: none;
}
.hamburger {
display: none;
}
.nav-item {
list-style: none;
}
#homeLink {
text-decoration: none;
}
#media screen and (max-width:940px) {
.header {
max-width: 100%;
background-color: rgba(0,0,0,.9);
}
.header .navbar {
max-width: 100%;
justify-content: space-between;
}
.hamburger {
display: block;
}
.nav-menu {
position: fixed;
left: -100%;
top: 90px;
flex-direction: column;
background-color: rgba(0,0,0,.9);
width: 100%;
height: 90vh;
z-index: 999;
text-align: center;
transition: .3s;
}
.nav-menu.active {
left: 0;
}
.nav-item {
margin: 1.5rem 0;
}
.header .navbar img {
width: 150px;
}
}
Played around with it a bit more. I found that the smooth={true} prop in the Link tags was what slowed it down. Not entirely sure why that was the case, but removing it made my navbar work as intended.

astro react component not getting styled with styled component

I'm importing this navbar component into an astro file, the component shows up on the page but the but the styling from styled-component is not working and it is throwing an error in my code editor that says:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
import React from 'react';
import { useState } from 'react';
import styled from 'styled-components'
import { AiOutlineClose, AiOutlineMenu } from 'react-icons/Ai'
import { Link } from 'react-scroll';
function Navigation() {
const [navb, setNavb] = useState(true);
const handleClick = () => setNavb(!navb) ;
const [click, setClick] = useState(true)
const handleMenu= () => setNavb(!navb)
const iconStyle = {width: "30px" , height:"30px", color: "#ffffff", }
const linkStyleDesktop = { color: "#000000", padding: "0 10px ", cursor: "pointer"}
const linkStyleMobile = { color: "#ffffff", padding: "30px 0", fontSize: "1.5rem", cursor: "pointer"}
return (
<Header className = "style">
<Container>
LOGO
<Nav className="desktop-nav">
<div className="desktop-navItems" >
<Link style = {linkStyleDesktop} to="/" smooth={true} duration={500}>
Home
</Link>
<Link style = {linkStyleDesktop} to="about" smooth={true} duration={500}>
About
</Link>
<Link style = {linkStyleDesktop} to="portfolio" smooth={true} duration={500}>
Portfolio
</Link>
<Link style = {linkStyleDesktop} to="footer" smooth={true} duration={500}>
Contact
</Link>
</div>
</Nav>
<button className = "btn" onClick = {handleClick}> {!navb ? <AiOutlineClose style={iconStyle}/>: <AiOutlineMenu style={iconStyle} /> }
</button>
</Container>
<Nav className="mobile-nav">
<div className={!navb || !click ? 'display-mobile-nav' : 'display-none'} >
<Link onClick={handleMenu} style = {linkStyleMobile} to="app" smooth={true} duration={500}>
Home
</Link>
<Link onClick={handleMenu} style = {linkStyleMobile}to="about" smooth={true} duration={500}>
About
</Link>
<Link onClick={handleMenu} style = {linkStyleMobile} to="portfolio" smooth={true} duration={500}>
Portfolio
</Link>
<Link onClick={handleMenu} style = {linkStyleMobile} to="footer" smooth={true} duration={500}>
Contact
</Link>
</div>
</Nav>
</Header>
)
}
export default Navigation;
const Header = styled.header`
background-color: #262b33;
padding: 1rem 0;
width: 100vw;
position:fixed;
z-index: 999;
.display-mobile-nav {
display: block;
}
.display-none{
display: none;
}
.desktop-nav {
display: none;
}
.mobile-nav {
.display-mobile-nav {
display:flex;
flex-direction: column;
align-items: center;
box-shadow: 10px 10px 5px 0px rgba(189,189,189,0.75);
-webkit-box-shadow: 10px 10px 5px 0px rgba(189,189,189,0.75);
-moz-box-shadow: 10px 10px 5px 0px rgba(189,189,189,0.75);
transition: opacity 5s ease-in;
}
}
`;
//container for desktop nav
const Container = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
padding:0 8rem;
font-family:Arial, Helvetica, sans-serif;
#media (max-width: 1200px){
padding: 1rem 1rem;
}
a {
color: #ffffff;
}
button {
background-color: transparent;
border: none;
}
#media (min-width: 800px){
.desktop-nav {
display: block;
}
.btn {
display: none
}
.mobile-nav {
display: none;
.display-mobile-nav {
display: none;
}
}
}
`
const Nav = styled.div`
.desktop-navItems {
display: flex;
li {
padding: 0 10px;
}
}
#media (min-width: 800px){
.mobile-nav {
display: block;
}
`;
Warning: Invalid hook call....
To resolve this error modify the first line of your code to;
export default function Navigation() {
and remove the default function export referenced lower in the code.
I haven't yet figured out why but astro.js seems to take issue
with naming convention for default exports on functional components.
I can't resolve the styling issue unfortunately.

How to make sidenav mobile link in react js about this situation?

I want to make the sidenav mobile to show when clicking.
I tried to use jquery, but don't know how to configure in webpack.
const SignedOutLinks = () => {
return (
<div>
<NavLink to="#" className="sidenav-trigger nav-wrapper" data-target="mobile-links">
<i className="material-icons">menu</i>
</NavLink>
<ul className="right hide-on-med-and-down">
<li className="waves-effect waves-light">
<NavLink to="/signup">Signup</NavLink>
</li>
<li className="waves-effect waves-light">
<NavLink to="/signin">Login</NavLink>
</li>
</ul>
<ul className="sidenav" id="mobile-links">
<li className="waves-effect waves-light">
<NavLink to="/signup">Signup</NavLink>
</li>
<li className="waves-effect waves-light">
<NavLink to="/signin">Login</NavLink>
</li>
</ul>
</div>
);
};
if you want to write it, this is some code i make:
or this link
react:
class Drawer extends React.Component{
constructor(props){
super(props)
this.state = {
open: false,
}
}
handleDrawer(){
let currentState = this.state.open
this.setState({open: !currentState})
}
componentDidMount(){
if (this.state.open = true){
document.addEventListener("keydown", (event) => {
if (event.keyCode === 27){
this.setState({open: false})
}
})
}
}
handleClickOut(){
if(this.state.open === true){
this.setState({open: false})
}
}
render(){
console.log(this.state)
return (
<div>
<div
onClick={this.handleClickOut.bind(this)}
className={this.state.open ? "deactive" : "container"}>
<button onClick={this.handleDrawer.bind(this)}>Click on me to see the
drawer</button>
</div>
<div className={this.state.open ? "active" : "drawer"}>Hellllo i'm a
drawer</div>
</div>
)
}
}
export default Drawer
css:
.drawer {
display: none;
}
.active {
display: show;
position: absolute;
left: 0;
width: 25vw;
height: 100vh;
background-color: #C10E00;
transition: display 0.4s ease-in-out;
text-align: center;
padding: 10px;
}
.container {
position: relative;
text-align: center;
}
.deactive {
position: absolute;
text-align: center;
background-color: #FF5346;
width: 100vw;
height: 100vh;
transition: 0.4s ease-in-out;
opacity: 0.5;
}
button {
width: 300px;
height: 150px;
background-color: #910B00;
color: white;
box-shadow: 2px 5px grey;
margin: 25px;
}
or if you want to get it full coded you can use Material-UI framework

How to get a particular div into fullscreen(full window size) in reactjs

I am making a Image viewer in ReactJs as I am newbie in this so I stuck at a point. actually I have to add a full screen option. when user click on any particular image the image is open and there is a option like next,prev,close,rotate and fullscreen(that is takes height and width of browser) so when user click on full screen that particular image will get the full window size and user still have option like rotate,next.close and prev. I searched for so many solution but nothing worked.
I tried so many things but it only does the fullscreen whole body but I want .center-image to be full screen with options as I said. This is the gallary modal component.
class GalleryModal extends React.Component {
constructor(props) {
super(props);
this.state = {
rotation: 0
};
this.rotate = this.rotate.bind(this);
}
render() {
const { rotation } = this.state;
if (this.props.isOpen === false) {
return null;
}
return (
<div className="modal-overlay" name={this.props.name}>
<div className="modal-body">
<a href="#" className="button" onClick={() => this.rotate()}>
<i className="fas fa-sync-alt" />
</a>
<a href="#" className="button" onClick={this.props.onPrev}>
<i className="fas fa-angle-left" />
</a>
<img
className="center_image"
id="image"
src={this.props.src}
style={{ transform: `rotate(${rotation}deg)` }}
/>
<a href="#" className="button" onClick={this.props.onNext}>
<i className="fas fa-angle-right" />
</a>
<a
className="modal-close"
href="#"
onClick={this.props.onClick}
>
<span className="fa fa-times" />
</a>
</div>
</div>
);
}
rotate() {
let newRotation = this.state.rotation + 90;
if (newRotation >= 360) {
newRotation = -360;
}
this.setState({
rotation: newRotation
});
}
}
Full code
This is my code and I am confused how to add the fullscreen option and where to add it .
I recommend using css viewport units, setting a component to height: 100vh and width: 100vw will make it fullscreen. You then conditionally render the component based on when you want it to be fullscreen.
Had to use some css tricks, but I believe this is what you're looking to achieve. The image is centered and takes up the maximum amount of width that is available within the window; however, if you stretch the window, it'll adjust its width up until it hits its max width (not advised to stretch it beyond its max value, otherwise, you'll get pixelation).
I did simplify your code a bit by elevating state and class methods to a single container, as well as, used setState() callbacks to manage state more efficiently and the ternary operator (cond ? true : false) in replace of simple if/else conditional statements.
Working example: https://codesandbox.io/s/zr5k7v0zp3
containers/Gallery/Gallery.js
import React from "react";
import GalleryImages from "../../components/GalleryImages/galleryImages";
import GalleryModal from "../../components/GalleryModal/galleryModal";
const imgUrls = [
"https://source.unsplash.com/3Z70SDuYs5g/800x600",
"https://source.unsplash.com/01vFmYAOqQ0/800x600",
"https://source.unsplash.com/2Bjq3A7rGn4/800x600",
"https://source.unsplash.com/t20pc32VbrU/800x600",
"https://source.unsplash.com/pHANr-CpbYM/800x600",
"https://source.unsplash.com/3PmwYw2uErY/800x600",
"https://source.unsplash.com/uOi3lg8fGl4/800x600",
"https://source.unsplash.com/CwkiN6_qpDI/800x600",
"https://source.unsplash.com/9O1oQ9SzQZQ/800x600",
"https://source.unsplash.com/E4944K_4SvI/800x600",
"https://source.unsplash.com/-hI5dX2ObAs/800x600",
"https://source.unsplash.com/vZlTg_McCDo/800x600"
];
export default class Gallery extends React.Component {
constructor(props) {
super(props);
this.state = {
imgIndex: 0,
imgUrlLength: imgUrls.length,
showModal: false,
rotation: 0
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.nextClick = this.nextClick.bind(this);
this.prevClick = this.prevClick.bind(this);
this.rotateImage = this.rotateImage.bind(this);
}
openModal(index) {
this.setState({
showModal: true,
imgIndex: index
});
}
closeModal() {
this.setState({
showModal: false,
imgIndex: 0,
rotation: 0
});
}
nextClick() {
this.setState(prevState => {
return {
imgIndex:
prevState.imgIndex === prevState.imgUrlLength - 1
? 0
: prevState.imgIndex + 1
};
});
}
prevClick() {
this.setState(prevState => {
return {
imgIndex:
prevState.imgIndex === 0
? prevState.imgUrlLength - 1
: prevState.imgIndex - 1
};
});
}
rotateImage() {
this.setState(prevState => {
return {
rotation: prevState.rotation + 90 <= 270 ? prevState.rotation + 90 : 0
};
});
}
render() {
return (
<div className="container-fluid gallery-container">
<GalleryImages imgUrls={imgUrls} openModal={this.openModal} />
<GalleryModal
isOpen={this.state.showModal}
onClick={this.closeModal}
onNext={this.nextClick}
onPrev={this.prevClick}
rotateImage={this.rotateImage}
rotation={this.state.rotation}
src={imgUrls[this.state.imgIndex]}
/>
</div>
);
}
}
components/GalleryImages/galleryImages.js
import React from "react";
import PropTypes from "prop-types";
const GalleryImages = ({ imgUrls, openModal }) => {
return (
<div className="row">
{imgUrls.map((url, index) => {
return (
<div key={index} className="col-sm-6 col-md-3 col-xl-2">
<div className="gallery-card">
<img
key={index}
className="gallery-thumbnail"
src={url}
alt={`Image number ${index + 1}`}
/>
<span
className="card-icon-open fa fa-expand"
onClick={() => openModal(index)}
/>
</div>
</div>
);
})}
</div>
);
};
GalleryImages.propTypes = {
imgUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
openModal: PropTypes.func.isRequired
};
export default GalleryImages;
components/GalleryModal/galleryModal.js
import React from "react";
import PropTypes from "prop-types";
const GalleryModal = ({
isOpen,
onClick,
onNext,
onPrev,
rotateImage,
rotation,
src
}) => {
return isOpen ? (
<div className="modal-overlay">
<div className="modal-body">
<div className="close-modal">
<a className="modal-close" href="#" onClick={onClick}>
<span className="fa fa-times" />
</a>
</div>
<div className="rotate-container">
<a href="#" className="button" onClick={rotateImage}>
<i style={{ fontSize: 44 }} className="fas fa-sync-alt" />
</a>
</div>
<div className="image-container">
<div>
<a href="#" className="button" onClick={onPrev}>
<i className="fas fa-angle-left" />
</a>
</div>
<div>
<img
src={src}
style={{ transform: `rotate(${rotation}deg)`, width: "100%" }}
/>
</div>
<div>
<a href="#" className="button" onClick={onNext}>
<i className="fas fa-angle-right" />
</a>
</div>
</div>
</div>
</div>
) : null;
};
GalleryModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
onNext: PropTypes.func.isRequired,
onPrev: PropTypes.func.isRequired,
rotateImage: PropTypes.func.isRequired,
rotation: PropTypes.number.isRequired,
src: PropTypes.string
};
export default GalleryModal;
styles.css
html,
body {
min-height: 100%;
height: 100%;
}
html {
font-size: 16px;
}
body {
position: relative;
font-size: 100%;
}
.button {
font-size: 50px;
color: #eee;
margin: 5px;
}
.card-icon-open {
display: block;
position: relative;
left: 45%;
top: 35px;
font-size: 30px;
width: 30px;
color: #fff;
cursor: pointer;
opacity: 0;
transform: translate(0%, -400%);
transition: all 0.25s ease-in-out;
}
.card-icon-open:focus,
.card-icon-open:hover {
color: #111;
}
.close-modal {
position: fixed;
top: 0;
right: 5px;
}
.fullscreen {
position: relative;
text-decoration: none;
font-size: 25px;
color: #eee;
z-index: 999;
}
.fullscreen:hover,
.fullscreen:focus,
.fullscreen:blur {
text-decoration: none;
color: red;
}
.gallery-container {
padding-top: 10px;
}
.gallery-card {
position: relative;
overflow: hidden;
margin-bottom: 10px;
}
.gallery-thumbnail {
max-width: 100%;
height: auto;
border-radius: 4px;
}
.gallery-thumbnail:focus ~ .card-icon-open,
.gallery-thumbnail:hover ~ .card-icon-open,
.gallery-thumbnail ~ .card-icon-open:focus,
.gallery-thumbnail ~ .card-icon-open:hover {
opacity: 1;
}
.image-container {
display: flex;
justify-content: center;
align-items: center;
}
.image-rotate {
font-size: 44px;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
background: rgba(21, 21, 21, 0.75);
}
.modal-body {
position: relative;
top: 15%;
z-index: 11;
padding: 0;
overflow: hidden;
max-width: 100%;
max-height: 100%;
}
.modal-close {
font-size: 44px;
z-index: 99;
color: #eee;
transition: all 0.25s ease-in-out;
}
.modal-close:focus,
.modal-close:hover {
color: red;
}
.rotate-container {
font-size: 44px;
position: fixed;
top: 0;
left: 5px;
}
Found this library which does exactly what you describe:
https://www.npmjs.com/package/react-fullscreen-image
You can use as is or look into the code for guidance

Material-UI drawer persistent state

I'm new to Material-ui and react. What I'm trying to do is have my drawer stay in a persistent open state when the user clicks the hamburger menu on the AppBar. I want my main content 'pushed' to the right when the drawer opens, not the drawer laying on top of it. I'm stuck and don't know how to get this to work. Here's my code thus far. Thanks in advance for any tips or tricks! :)
Application.js
import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {ClassificationBanner} from './ClassificationBanner'
import TitleBar from './TitleBar'
import styles from './Application.css'
import injectTapEventPlugin from 'react-tap-event-plugin'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
injectTapEventPlugin();
class Application extends Component {
render() {
return (
<MuiThemeProvider>
<div className={styles.root}>
<ClassificationBanner />
<TitleBar />
{this.props.children}
</div>
</MuiThemeProvider>
)
}
}
Application.propTypes = {
children: PropTypes.object.isRequired,
bbox: React.PropTypes.arrayOf(React.PropTypes.number),
};
export default Application
TitleBar.js
import React, {Component} from 'react'
import logo from '../../images/logo.1.png'
import AppBar from 'material-ui/AppBar'
import Drawer from 'material-ui/Drawer'
import Subheader from 'material-ui/Subheader'
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MenuItem from 'material-ui/MenuItem'
import { Link, IndexLink } from 'react-router';
import css from './TitleBar.css'
class TitleBar extends Component {
constructor(props){
super(props);
this.state = {drawerOpen:false};
}
getChildContext() {
return {muiTheme: getMuiTheme(baseTheme)};
}
handleToggle() {
this.setState({drawerOpen: !this.state.drawerOpen});
}
handleClose() { this.setState({drawerOpen: false}); }
render() {
const styles = {
appBar: {
backgroundColor: 'black',
height: '70px',
top: '25px'
},
img: {
position: 'absolute',
left: '50%',
marginLeft: '-127px',
marginTop: '10px',
height: '50px'
},
drawer: {
width: '200px',
marginTop: '95px',
backgroundColor: '#010101',
marginLeft: '0px',
padding: '0px'
},
mainMenu: {
color: '#3e3f3f',
display: 'inline-block',
marginRight: '40px',
fontSize: '20px',
align: 'left',
},
};
const img = <img style={styles.img} src={logo}/>
return (
<header className="header">
<AppBar style={styles.appBar} title={img} onLeftIconButtonTouchTap={this.handleToggle.bind(this)} />
<Drawer containerStyle={styles.drawer}
overlayStyle={styles.drawer}
docked={false}
open={this.state.drawerOpen}
onRequestChange={(open) => this.setState({open})}>
<Subheader inset={false}><span style={{width:'100%'}}><div style={styles.mainMenu}>MAIN MENU</div><div style={{display:'inline-block'}}><i className="fa fa-long-arrow-left fa-lg" style={{color: '#4498c0'}} onTouchTap={this.handleClose.bind(this)} aria-hidden="true"></i></div></span></Subheader>
<MenuItem className={css.menuItem} onTouchTap={this.handleClose.bind(this)}><IndexLink className={css.link} activeClassName={css.active} onlyActiveOnIndex={true} to="/exports"><i className="fa fa-book" aria-hidden="true"></i> DataPack Library</IndexLink></MenuItem>
<MenuItem className={css.menuItem} onTouchTap={this.handleClose.bind(this)}><Link className={css.link} activeClassName={css.active} to="/create" ><i className="fa fa-plus-square" aria-hidden="true"></i> Create Datapack</Link></MenuItem>
<MenuItem className={css.menuItem} onTouchTap={this.handleClose.bind(this)}><Link className={css.link} activeClassName={css.active} to="/about" ><i className="fa fa-info-circle" aria-hidden="true"></i> About EventKit</Link></MenuItem>
<MenuItem className={css.menuItem} onTouchTap={this.handleClose.bind(this)}><Link className={css.link} activeClassName={css.active} to="/account" ><i className="fa fa-user" aria-hidden="true"></i> Account Settings</Link></MenuItem>
<MenuItem className={css.menuItem} onTouchTap={this.handleClose.bind(this)}><Link className={css.link} activeClassName={css.active} to="/logout" ><i className="fa fa-sign-out" aria-hidden="true"></i> Log Out</Link></MenuItem>
</Drawer>
</header>
)
}
}
TitleBar.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
};
export default TitleBar
TitleBar.css
.menuItem > div > div{
margin-left: 0px !important;
padding: 0px !important;
}
.img {
width: 205px;
height: 40px;
}
/* =========================================================================
Link
========================================================================= */
.link {
position: relative;
display: block;
padding: 5px;
text-align: left;
text-decoration: none;
color: #4498c0;
}
.link:visited {
text-decoration:none;
}
.atHome .link {
line-height: 150px;
}
.link:hover {
background-color: #161e2e;
text-decoration: none;
}
.link:active {
text-decoration: none;
}
a:link {
text-decoration: none;
}
/* Link: State
========================================================================= */
.active,
.active:hover {
box-shadow: 0 2px rgba(0,0,0,.1);
background-color: #161e2e;
text-decoration: none;
}
.active:visited {
text-decoration: none;
}
.active .icon {
fill: #1675aa;
filter: none;
-webkit-filter: none;
box-shadow: 0 2px rgba(0,0,0,.1);
text-decoration: none;
}
Application.css
.root {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.body {
font-family: 'Roboto', sans-serif;
}

Resources