Close sidebar with react in combination with react-state - css

i have written a static sidebar which every icon opens a "sub-sidebar" onclick. i handle the switches between the differrent "sub-sidebars" with react-states.
but i didnĀ“t get to manage that the sub-sidebar closes when a icon is clicked a second time. Anyone an idea how to do this? Thanks in advance.
import React, { Component } from 'react';
import { GrAdd, BsCollection, IoSettingsOutline } from '../icons';
import New from './sidebars/new';
import Collection from './sidebars/collection';
import Settings from './sidebars/settings';
import '../css/StaticBar.css'
class StaticBar extends Component {
constructor(props) {
super(props)
this.state = {
selected: 0,
}
}
render() {
return (
<div className="StaticBar">
<ul>
<li className="ListItem" onClick={() => this.setState({ selected: 0 })}>
<GrAdd color="white"/>
</li>
<li className="ListItem" onClick={() => this.setState({ selected: 1 })}>
<BsCollection color="white" />
</li>
<li className="ListItem" onClick={() => this.setState({ selected: 2 })}>
<IoSettingsOutline color="white" />
</li>
</ul>
{(this.state.selected === 0) && <New />}
{(this.state.selected === 1) && <Collection />}
{(this.state.selected === 2) && <Settings />}
</div>
);
}
}
export default StaticBar;

You can use this conditional setState logic
import React, { Component } from 'react';
import { GrAdd, BsCollection, IoSettingsOutline } from '../icons';
import New from './sidebars/new';
import Collection from './sidebars/collection';
import Settings from './sidebars/settings';
import '../css/StaticBar.css'
class StaticBar extends Component {
constructor(props) {
super(props)
this.state = {
selected: 0,
}
}
render() {
return (
<div className="StaticBar">
<ul>
<li className="ListItem" onClick={() => this.setState({ selected: 0 })}>
<GrAdd color="white"/>
</li>
<li className="ListItem" onClick={() => this.setState({ selected: (this.state.selected==1 ? 0 : 1) })}>
<BsCollection color="white" />
</li>
<li className="ListItem" onClick={() => this.setState({ selected: ( this.state.selected==2 ? 0 : 2) })}>
<IoSettingsOutline color="white" />
</li>
</ul>
{(this.state.selected === 0) && <New />}
{(this.state.selected === 1) && <Collection />}
{(this.state.selected === 2) && <Settings />}
</div>
);
}
}
export default StaticBar;

Related

How to change overflow style to hidden when modal opens

I am trying to create react app and i want overflow to hidden when button is pressed,
i want to display contact form on modal but overflow is running everything i can scroll even with modal is open
Here is my navbar with button
import React from "react";
import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { FaBars, FaTimes } from "react-icons/fa";
import "./Navbar.css";
import { IconContext } from "react-icons/lib";
import Button from "./Button";
import Modal from "./Contact Form/Modal";
import { motion, AnimatePresence } from "framer-motion";
export default function Navbar() {
const [click, setClick] = useState(false);
const [button, setButton] = useState(true);
const [modalOpen, setModalOpen] = useState(false);
function closeModal() {
setModalOpen(false);
}
function openModal() {
setModalOpen(true);
}
function handleClick() {
setClick(!click);
}
function closeMobileMenu() {
setClick(false);
}
function showButton() {
if (window.innerWidth <= 960) {
setButton(false);
} else {
setButton(true);
}
}
function closeMobileMenu() {
setClick(false);
}
useEffect(() => {
showButton();
}, []);
window.addEventListener("resize", showButton);
return (
<>
<IconContext.Provider value={{ color: "#fff" }}>
<div className="navbar">
<div className="navbar-container container">
<Link to="/" className="navbar-logo" onClick={closeMobileMenu}>
LOGO
</Link>
<div className="menu-icon" onClick={handleClick}>
{click ? <FaTimes /> : <FaBars />}
</div>
<ul className={click ? "nav-menu active" : "nav-menu"}>
<li className="nav-item">
<Link to="/" className="nav-links" onClick={closeMobileMenu}>
Home
</Link>
</li>
<li className="nav-item">
<Link to="/" className="nav-links" onClick={closeMobileMenu}>
About Us
</Link>
</li>
<li className="nav-item">
<Link to="/" className="nav-links" onClick={closeMobileMenu}>
Contact Us
</Link>
</li>
{/* Main button */}
<li className="nav-btn">
{button ? (
<Link to='' className="btn-link">
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="btn--outline"
onClick={() => (modalOpen ? closeModal() : openModal())} //modal opens
>
CONTACT US
</motion.button>
</Link>
) : (
<Link
to=""
className="btn-link"
onClick={closeMobileMenu}
>
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="btn--mobile"
buttonSize='btn--mobile'
buttonStyle='btn--outline'
onClick={() => {(modalOpen ? closeModal() : openModal())}} //modal opens
>
Contact US
</motion.button>
</Link>
)}
</li>
</ul>
</div>
</div>
<AnimatePresence
// Disable any initial animations on children that
// are present when the component is first rendered
initial={false}
// Only render one component at a time.
// The exiting component will finish its exit
// animation before entering component is rendered
exitBeforeEnter={true}
// Fires when all exiting nodes have completed animating out
onExitComplete={() => null}
>
{modalOpen && <Modal modalOpen={modalOpen} handleClose={closeModal} />}
</AnimatePresence>
</IconContext.Provider>
</>
);
}
I was trying to do it use State but it didn't work. I use style effect but i didn't manage to achieve it
You will make a boolean state with an initial value set to false.
When the button is clicked you will update the state from false to true and I will recommend it for you instead of making it true. then you will use this state easily with your style property and do what you need.
change the style bellow based on your needs.
import { useState } from "react";
export default function App() {
const [clicked, setClicked] = useState(false);
return (
<div className="App">
<h1 style={{ display: clicked ? "none" : "block" }}>Hello
CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={() => setClicked(!clicked)}>click</button> <= here instead of making it true. I made it the oppesite of the previous value. to toggle between them.
</div>
);
}

Failed prop type: Invalid prop `className` of type 'function'

I am making a Navbar for my dashboard but encountered this error which says I should pass a string to className and not function . I am passing the function to className as I have to check if the navbar is open or not. How can I solve this error?
Here is my code for navbar:
//STYLES
import styles from "./Navbar.module.scss";
import React from 'react';
//CONTEXT
import { useContext } from "react";
import NavContext from "../../context/NavContext";
//REACT ROUTER
import { NavLink } from "react-router-dom";
//ICONS
import {
MdOutlineDashboard,
MdOutlineAnalytics,
MdOutlinedFlag,
MdPeopleOutline,
MdOutlineMessage,
MdOutlineLogout,
} from "react-icons/md";
import { FaTimes } from "react-icons/fa";
import { BsThreeDots } from "react-icons/bs";
import { VscDashboard } from "react-icons/vsc";
const NavUrl = ({ url, icon, description }) => {
const { nav, setNav } = useContext(NavContext);
const checkWindowSize = () => {
if (window.innerWidth < 1024) setNav(!nav);
};
return (
<li className={styles.li_navlink}>
<NavLink
to={`${url}`}
className={({ isActive }) => (isActive ? styles.active : undefined)}
onClick={() => checkWindowSize()}
>
{icon}
<span className={styles.description}>{description}</span>
</NavLink>
</li>
);
};
const Navbar = () => {
const { nav, setNav } = useContext(NavContext);
return (
<div
className={`${styles.navbar_container} ${
nav ? styles.navbar_mobile_active : undefined
}`}
>
<nav className={nav ? undefined : styles.nav_small}>
{/* LOGO */}
<div className={styles.logo}>
<VscDashboard className={styles.logo_icon} />
<FaTimes
className={styles.mobile_cancel_icon}
onClick={() => {
setNav(!nav);
}}
/>
</div>
{/* MENU */}
<ul className={styles.menu_container}>
{/* FIRST CATEGORY */}
<span className={styles.categories}>
{nav ? "Pages" : <BsThreeDots />}
</span>
<NavUrl
url="/"
icon={<MdOutlineDashboard />}
description="Dashboard"
/>
<NavUrl
url="usage"
icon={<MdOutlineAnalytics />}
description="Usage"
/>
<NavUrl
url="plan"
icon={<MdOutlinedFlag />}
description="Plan"
/>
<NavUrl url="documentation" icon={<MdPeopleOutline />} description="Documentation" />
<NavUrl
url="invoices"
icon={<MdOutlineMessage />}
description="Invoices"
/>
</ul>
{/* LOGOUT BUTTON */}
<div
className={`${styles.btn_logout}`}
onClick={() => {
setNav(!nav);
}}
>
<MdOutlineLogout />
</div>
</nav>
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
</div>
);
};
export default Navbar;
Here is my error which is saying to pass string in navlink , navurl ,ul , nav , navbar , div , App , route , switch , router , browserRouter classes :
index.js:1 Warning: Failed prop type: Invalid prop `className` of type
`function` supplied to `NavLink`, expected `string`.
in NavLink (at Navbar.jsx:33)
in NavUrl (at Navbar.jsx:73)
in ul (at Navbar.jsx:67)
in nav (at Navbar.jsx:54)
in div (at Navbar.jsx:49)
in Navbar (at App.jsx:24)
in div (at App.jsx:21)
in App (at src/index.js:19)
in Route (at src/index.js:19)
in Switch (at src/index.js:18)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:17)
I think you do it in the last div you have
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
may be you must use onMouseEnter
onMouseEnter={() => {
setisActive (true);
}}
onMouseLeave={() => {
setisActive (false);
}}
className={isActive ? styles.active : undefined}

props is undefined when passing from parent to component in next js

I have /pages/profile.js which calls the LovedOne element, passing values from props.
Debugging shows that these values are valid when passed
import React from "react";
import LovedOne from "../components/loved_one";
export const Profile = ({ loved_ones }) => {
const [session, loading] = useSession();
if (loading) return <div>loading...</div>;
if (!session) return <div>no session</div>;
return (
<Layout>
{session && (
<>
<img src={session.user.image} className="avatar" />
<h1>{session.user.name}</h1>
</>
)}
{loved_ones.map((loved_one, index) => (
<LovedOne
key={index}
firstname={loved_one.firstname}
surname={loved_one.surname}
email={loved_one.email}
/>
))}
<style jsx>{`
.avatar {
width: 220px;
border-radius: 10px;
}
`}</style>
</Layout>
);
};
However in /components/loved_one.js my props is undefined
import React, { useState, useRef } from "react";
export const LovedOne = ({ props }) => {
const [setActive, setActiveState] = useState("");
const [setHeight, setHeightState] = useState("0px");
const content = useRef();
function toggleAccordion() {
setActiveState(setActive === "" ? "active" : "");
setHeightState(
setActive === "active" ? "0px" : `${content.current.scrollHeight}px`
);
}
return (
<div>
<div className="row">
<button
className={`collection-item ${setActive}`}
onClick={toggleAccordion}
>
<i className="fas fa-plus teal-text"></i>
</button>
<div className="col s2">
{props.firstname} {props.surname}
</div>
<div className="col s2">{props.email}</div>
</div>
<div ref={content} style={{ maxHeight: `${setHeight}` }}>
<span>some stuff</span>
</div>
</div>
);
};
export default LovedOne;
I've tried passing single variables, and passing the entire loved_ones object. I get the same problem.
Any help much appreciated!
Have you tried passing props instead of {props} ?
lose brackets, try this way:
export const LovedOne = (props) => {

Modal dialog to present description

I am trying to make a popup window with a description for the project whenever someone clicks the description button.
I can't figure out how to do it. I have looked for components in react-mdl but I don't know how to insert it to my program.
The hirarchy of the button is:
-App
---NAVBAR
---Pages
-------Projects
---------ProjectCard
------------description button
I have tried to integrate components from react-mdl, semantic-ui etc, but I couldn't figure out how to adapt it to my program.
Thanks in advance guys!
import React from "react";
import { Layout, Content } from "react-mdl";
import Pages from "./Pages";
import { NavBar } from "./NavBar";
import { LeftDrawer } from "./LeftDrawer";
class App extends React.Component {
render() {
return (
<div>
<Layout>
<NavBar />
<LeftDrawer />
<Content className="app-content">
<Pages />
</Content>
</Layout>
</div>
);
}
}
export default App;
import React from "react";
import { Tabs, Tab } from "react-mdl";
import { CProjects } from "./CProjects";
import { ReactProjects } from "./ReactProjects";
import { SwiftProjects } from "./SwiftProjects";
import { TypescriptProjects } from "./TypescriptProjects";
import { JavaProjects } from "./JavaProjects";
import { CPPProjects } from "./CPPProjects";
import { PythonProjects } from "./PythonProjects";
import { AssemblyProjects } from "./AssemblyProjects";
class Projects extends React.Component {
state = { activeTab: 0 };
handleChange = tabId => {
this.setState({ activeTab: tabId });
};
toggleCategiries = () => {
switch (this.state.activeTab) {
case 0:
return (
<div className="react-projects">
<ReactProjects />
</div>
);
case 1:
return (
<div className="typescript-projects">
<TypescriptProjects />
</div>
);
case 2:
return (
<div className="java-projects">
<JavaProjects />
</div>
);
case 3:
return (
<div className="c-projects">
<CProjects />
</div>
);
case 4:
return (
<div className="c++-projects">
<CPPProjects />
</div>
);
case 5:
return (
<div className="swift-projects">
<SwiftProjects />
</div>
);
case 6:
return (
<div className="python-projects">
<PythonProjects />
</div>
);
case 7:
return (
<div className="assembly-projects">
<AssemblyProjects />
</div>
);
default:
return <div>lala</div>;
}
};
render() {
return (
<div className="page">
<div className="categories">
<Tabs
activeTab={this.state.activeTab}
onChange={this.handleChange}
ripple
>
<Tab className="tab">React</Tab>
<Tab className="tab">TypeScript</Tab>
<Tab className="tab">Java</Tab>
<Tab className="tab">C</Tab>
<Tab className="tab">C++</Tab>
<Tab className="tab">Swift</Tab>
<Tab className="tab">Python</Tab>
<Tab className="tab">Assembly</Tab>
</Tabs>
{this.toggleCategiries()}
</div>
</div>
);
}
}
export default Projects;
import React from "react";
import {
Card,
CardTitle,
CardActions,
Button,
CardMenu,
IconButton,
CardText
} from "react-mdl";
import { Link } from "react-router-dom";
class ProjectCard extends React.Component {
render() {
const titleStyle = {
backgroundImage: "url(" + this.props.background + ")",
backgroundSize: "100% 100%",
color: "#fff",
height: "176px"
};
return (
<div>
<Card shadow={6} style={{ borderRadius: "6px" }}>
<CardTitle style={titleStyle}>{this.props.name}</CardTitle>
<CardText>{this.props.shortDescription}</CardText>
<CardActions border>
<div style={{ display: "flex", justifyContent: "center" }}>
<a href={this.props.github} target="_blank">
<Button colored>GitHub</Button>
</a>
<Button colored>Description</Button>
</div>
</CardActions>
<CardMenu style={{ color: "#fff" }}>
<IconButton name="share" />
</CardMenu>
</Card>
</div>
);
}
}
export default ProjectCard;
import React from "react";
import { Spring } from "react-spring/renderprops";
import ProjectCard from "./ProjectCard";
import backgroundImage from "../../additional-files/images/React_background.png";
export const ReactProjects = () => {
return (
<Spring
config={{ duration: 1000 }}
from={{ opacity: 0 }}
to={{ opacity: 1 }}
>
{props => (
<div style={props}>
<div className="projects">
<div className="project">
<ProjectCard
name="Lab1"
shortDescription="Encoder and Debug mode"
description="This is the desired description in Modal"
github="https://github.com/avishaiyaniv605/Computer-Architectue-Lab1"
background={backgroundImage}
/>
</div>
<div className="project">
<ProjectCard
name="Lab1"
shortDescription="Encoder and Debug mode"
description="This is the desired description in Modal"
github="https://github.com/avishaiyaniv605/Computer-Architectue-Lab1"
background={backgroundImage}
/>
</div>
<div className="project">
<ProjectCard
name="Lab1"
shortDescription="Encoder and Debug mode"
description="This is the desired description in Modal"
github="https://github.com/avishaiyaniv605/Computer-Architectue-Lab1"
background={backgroundImage}
/>
</div>
</div>
</div>
)}
</Spring>
);
};
I managed to do it with a Dialog component of evergreen ui.
Inserted it where the Description button was and inside it, I inserted the button
import React from "react";
import {
Card,
CardTitle,
CardActions,
Button,
CardMenu,
IconButton,
CardText
} from "react-mdl";
import Component from "#reach/component-component";
import { Pane, Dialog } from "evergreen-ui";
class ProjectCard extends React.Component {
state = {
active: false
};
handleToggle = () => {
this.setState({ active: !this.state.active });
};
actions = [
{ label: "Cancel", onClick: this.handleToggle },
{ label: "Save", onClick: this.handleToggle }
];
render() {
const titleStyle = {
backgroundImage: "url(" + this.props.background + ")",
backgroundSize: "100% 100%",
color: "#fff",
height: "176px"
};
return (
<div>
<Card shadow={6} style={{ borderRadius: "6px" }}>
<CardTitle style={titleStyle}>{this.props.name}</CardTitle>
<CardText>{this.props.shortDescription}</CardText>
<CardActions border>
<div style={{ display: "flex", justifyContent: "center" }}>
<a href={this.props.github} target="_blank">
<Button colored>GitHub</Button>
</a>
<Component initialState={{ isShown: false }}>
{({ state, setState }) => (
<Pane>
<Dialog
isShown={state.isShown}
title={this.props.name + " description"}
onCloseComplete={() => setState({ isShown: false })}
confirmLabel="close"
hasFooter={false}
>
<Pane height={1800} width="100%" backgroundColor="#ddd" style={{ borderRadius: '6px' }}>
<div style={{ padding: "1vw 0 0 1vw" }}>
{this.props.description}
</div>
</Pane>
</Dialog>
<Button colored onClick={() => setState({ isShown: true })}>
Description
</Button>
</Pane>
)}
</Component>
</div>
</CardActions>
<CardMenu style={{ color: "#fff" }}>
<IconButton name="share" />
</CardMenu>
</Card>
</div>
);
}
}
export default ProjectCard;

Display dynamic content on click on menu item using semantic-ui-react

I want to display dynamic content in Sidebar.Pusher based on the item clicked from the menu. Here is my code -
<Sidebar.Pushable >
<Sidebar as={Menu} animation='push' width='thin' visible={visible} icon='labeled' vertical inverted>
<Menu.Item name='home' >
<Icon name='tasks' />
Manage categories
</Menu.Item>
<Menu.Item name='home' >
<Icon name='tasks' />
Manage products
</Menu.Item>
</Sidebar>
<Sidebar.Pusher >
<Segment basic>
Display Dynamic content
</Segment>
</Sidebar.Pusher>
Any leads will be highly appreciated.
If I understand the question correctly, there are a few possible solutions. In one of my projects I'm using it with React Router, so in the <Sidebar /> component I have <Menu.Item as={Link} to='/path' /> and then the <Route path='/path' /> is in a <Switch /> statement in <Sidebar.Pusher />.
If you want to change rendered components without React Router, here is an example of how I implemented it.
import React, { Component } from 'react'
import { Sidebar, Segment, Menu } from 'semantic-ui-react'
export default class SideNav extends Component {
constructor(props) {
super(props)
this.state = {
renderTab: 'home'
}
}
changeTab(tabName) {
this.setState({ renderTab: tabName })
}
render() {
const { renderTab } = this.state
return (
<Sidebar.Pushable as={Segment}>
<Sidebar as={Menu} visible vertical>
<Menu.Item onClick={() => this.changeTab('home')} as='a' name='home'>
Home
</Menu.Item>
<Menu.Item onClick={() => this.changeTab('about')} as='a' name='about'>
About
</Menu.Item>
</Sidebar>
<Sidebar.Pusher>
<RenderedContent tabName={renderTab} />
</Sidebar.Pusher>
</Sidebar.Pushable>
)
}
}
const RenderedContent = ({ tabName }) => {
if (tabName === 'home') {
return <Home />
}
if (tabName === 'about') {
return <About />
}
}
const Home = () => (
<div>This is the home page</div>
)
const About = () => (
<div>This is the about page</div>
)

Resources