component Publisher.js and other child components projectStatus.js are overlapping each other when Render the Child component. I don't know what's going wrong and how to fix this. You can see the image
this is my Publisher.js
//import useState hook to create menu collapse state
import React, { useState } from "react";
import {NavLink, Outlet} from "react-router-dom"
//import react pro sidebar components
import {
ProSidebar,
Menu,
MenuItem,
SidebarHeader,
SidebarFooter,
SidebarContent,
} from "react-pro-sidebar";
//import icons from react icons
import { FaFileContract } from "react-icons/fa";
import { FiLogOut} from "react-icons/fi";
import { HiDocumentReport } from "react-icons/hi";
import { BiCog } from "react-icons/bi";
import { GiHamburgerMenu } from "react-icons/gi";
//import sidebar css from react-pro-sidebar module and our custom css
import "react-pro-sidebar/dist/css/styles.css";
import "./publisherCss.css";
const Publisher = () => {
//create initial menuCollapse state using useState hook
const [menuCollapse, setMenuCollapse] = useState(false)
//create a custom function that will change menucollapse state from false to true and true to false
const menuIconClick = () => {
//condition checking to change state from true to false and vice versa
menuCollapse ? setMenuCollapse(false) : setMenuCollapse(true);
};
return (
<>
<div id="sidebarHeader">
{/* collapsed props to change menu size using menucollapse state */}
<ProSidebar collapsed={menuCollapse}>
<SidebarHeader>
<div className="logotext">
{/* small and big change using menucollapse state */}
<p>{menuCollapse ? "Evc" : "Publisher "}</p>
</div>
<div className="closemenu" onClick={menuIconClick}>
{/* changing menu collapse icon on click */}
{menuCollapse ? (
<GiHamburgerMenu/>
) : (
<GiHamburgerMenu/>
)}
</div>
</SidebarHeader>
<SidebarContent>
<Menu iconShape="square">
<NavLink to="/publisher/projectstatus"> <MenuItem icon={<FaFileContract />}>Project status</MenuItem> </NavLink>
<MenuItem icon={<HiDocumentReport />}>All project</MenuItem>
<MenuItem icon={<BiCog />}>Settings</MenuItem>
</Menu>
</SidebarContent>
<SidebarFooter>
<NavLink to="/login">
<Menu iconShape="square">
<MenuItem icon={<FiLogOut />}>Logout</MenuItem>
</Menu>
</NavLink>
</SidebarFooter>
</ProSidebar>
</div>
<Outlet />
</>
)
}
export default Publisher;
Publisher.css
#sidebarHeader {
position: absolute;
width: 220px;
display: flex;
}
#sidebarHeader .pro-sidebar {
height: 100vh;
/* position: absolute; */
}
#sidebarHeader .closemenu {
color: rgb(0,7,61);
position: absolute;
right: 0;
z-index: 9999;
line-height: 20px;
border-radius: 50%;
font-weight: bold;
font-size: 22px;
top: 55px;
cursor: pointer;
}
#sidebarHeader .pro-sidebar {
width: 100%;
min-width: 100%;
}
#sidebarHeader .pro-sidebar.collapsed {
width: 80px;
min-width: 80px;
}
#sidebarHeader .pro-sidebar-inner {
background-color: white;
box-shadow: 0.5px 0.866px 2px 0px rgba(0, 0, 0, 0.15);
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout {
overflow-y: hidden;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout .logotext p {
font-size: 20px;
padding: 10px 20px;
color: #000;
font-weight: bold;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul {
padding: 0 5px;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul .pro-inner-item {
color: #000;
margin: 10px 0px;
font-weight: bold;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul .pro-inner-item .pro-icon-wrapper {
background-color: #fbf4cd;
color: #000;
border-radius: 3px;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul .pro-inner-item .pro-icon-wrapper .pro-item-content {
color: #000;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout .active {
background-image: linear-gradient(0deg, #fece00 0%, #ffe172 100%);
}
#sidebarHeader .logo {
padding: 20px;
}
#media only screen and (max-width: 720px) {
html {
overflow: hidden;
}
}
.nav-link .active{
background-color: #ffe172;
}
I think I am doing some wrong CSS override property but I am unable to understand what's wrong I am doing. if anyone know please correct me
if anyone knows how to fix this please tell me. it's appreciated
update:
After updating the CSS display: flex it show the child content in flex but the problem is, I specified width: 220px for the sidebar but the child content not go above the 220px width. you can see the image.
Now how can I fix this to a child can use width?
Your picture is not complete, most likely it's styles or wrong location of "Outlet". I made simplified example, I hope it helps.
Related
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 }.
To clarify I'm working a react page that would show the user one piece of content that will be displayed on the page. When the user clicks on a link to said piece of content that they would like to see on the page.
The structure of the page goes like this. There will be a navbar that is specific to the page. The navbar has links to the components/content I'm also using styled components for this project the navbar looks like this
The servantclassnavbar file.
import react from 'react'
import styled from 'styled-components'
import { Link } from 'react-router-dom'
//useable react icon
import {FaCaretDown} from 'react-icons/fa'
const Navbarcontainer = styled.ul`
background: #D3D3D3;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
display: flex;
justify-content: center;
`
const Dropdownbtn = styled.div`
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
cursor: pointer;
&:hover{
color: cyan;
background: grey;
transition: ease-in-out 0.5s;
}
`
const Dropdowncontent = styled.div`
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
`
const Dropdownli = styled.li`
display: inline-block;
&:hover {
color: cyan;
background: grey;
transition: ease-in-out 0.4s;
}
&:hover ${Dropdowncontent} {
display: block;
}
`
const Dropdownnavlinks = styled(Link)`
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
&:hover {
color: cyan;
background-color: grey;
transition: ease-in-out 0.4s;
}
`
function Servantclassesnavbar(){
return(
<>
<Navbarcontainer>
<Dropdownli>
<Dropdownbtn>
Knight Classes<FaCaretDown />
</Dropdownbtn>
<Dropdowncontent>
<Dropdownnavlinks to="/saberclass">Saber</Dropdownnavlinks>
<Dropdownnavlinks to="/archerclass">Archer</Dropdownnavlinks>
<Dropdownnavlinks to="/lancerclass">Lancer</Dropdownnavlinks>
</Dropdowncontent>
</Dropdownli>
</Navbarcontainer>
</>
)
}
export default Servantclassesnavbar;
Here is a the page that I want to have it act as a home page for the all the other components to display their content in. You can ignore the 'Navbar' and 'sidebar' they are just navigations to other pages for this site.
import React,{useState} from "react";
import Navbar from "../componets/navbar";
import Sidebar from "../componets/sideBar";
import styled from "styled-components";
import Servantclassesnavbar from "../servantclassescomponets/servantclassesnavbar";
import Introduction from "../servantclassescomponets/Introduction"
import Saberclass from '../servantclassescomponets/Saberclass'
import Lancerclass from '../servantclassescomponets/Lancerclass'
import Archerclass from "../servantclassescomponets/Archerclass"
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";
const Displayedserventclasscontainer = styled.div`
border: 1px solid black;
margin: auto;
width: 95vw;
height: 280vw;
background: rgb(130,141,162);
background: linear-gradient(274deg, rgba(130,141,162,0.938813025210084) 0%, rgba(66,116,150,0.6306897759103641) 50%, rgba(132,152,187,1) 100%);
#media screen and (max-width: 1024px){
min-height: 100vh;
}
#media screen and (max-width: 768px){
min-height: 230vh;
}
#media screen and (max-width: 540px){
min-height: 320vh;
}
#media screen and (max-width: 414px){
min-height: 350vh;
}
#media screen and (max-width: 375px){
min-height: 415vh;
}
#media screen and (max-width: 360px){
min-height: 450vh;
}
#media screen and (max-width: 320px){
min-height: 530vh;
}
`;
function Servantclasses (){
const [isOpen, SetIsOpen] = useState(false);
function toggle (){
SetIsOpen(!isOpen)
}
return(
<>
<Navbar toggle={toggle}/>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Servantclassesnavbar />
<Displayedserventclasscontainer>
<Router>
<Switch>
<Route path="/" component={Introduction} />
<Route path="/saberclass" component={Saberclass} />
<Route path="/lancerclass" component={Lancerclass} />
<Route path="/archerclass" component={Archerclass} />
</Switch>
</Router>
</Displayedserventclasscontainer>
</>
)
}
export default Servantclasses;
Last here is an example of the component/content I'm trying to display on the page.
import react from 'react'
import styled from 'styled-components'
import sabercard from '../assets/sabercard.png'
const Maincontainer = styled.div`
margin: auto;
width: 75vw;
height: 275vw;
text-align: center;
`
const Classnameheader = styled.h1`
margin-bottom: 2%;
font-size: 2.5rem;
border-bottom: 3px solid black;
`
const Classcardimg = styled.div`
display: flex;
justify-content: center;
border-bottom: 3px solid black;
> img {
width: 15vw;
height: 30vw;
}
`
const Loreheadercontainer = styled.h2`
font-size: 2rem;
border-bottom: 3px solid black;
`
const Classlorecontainer = styled.div`
font-size: larger;
`
<Maincontainer>
<Classnameheader>Saber</Classnameheader>
<Classcardimg><img src={sabercard} alt="The Servant class card image" /></Classcardimg>
<Loreheadercontainer>Saber Lore</Loreheadercontainer>
<Classlorecontainer>Servants that are placed in this class are legendary figures who took up the sword in their life.
some are known for choosing to master their swordsmanship. others only used it briefly, but they are a Saber all the same.</Classlorecontainer>
At first I tried using react-router as you can see in the page file that houses all the content, and that's when I realize that react-router changes the whole page leaving a blank page. How would I make it so when I click on one the links the content with in the page's 'Displayedserventclasscontainer' will display just the content the user wants to see within that page?
Since the Servantclassesnavbar uses the Link component, it should be inside of the Router component as follow:
return(
<Router>
<Navbar toggle={toggle}/>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Servantclassesnavbar />
<Displayedserventclasscontainer>
<Switch>
<Route path="/" component={Introduction} />
<Route path="/saberclass" component={Saberclass} />
<Route path="/lancerclass" component={Lancerclass} />
<Route path="/archerclass" component={Archerclass} />
</Switch>
</Displayedserventclasscontainer>
</Router>
)
And any component used outside of the Switch will be displayed on all pages, which I think is what you are trying to achieve.
I use scss and styled-components together. Recently I don't know why I started to see a race situation over which styles get applied on the final render. Sometimes, usually, when the app is loaded for the first/second time, styles from scss gets applied and when I do a couple of hard refreshes my custom styles written with styled-components get applied. Do you have any idea why is this happening? I don't want to put it! important everywhere to fix it. I would like to understand it.
The below screenshot shows that _sidebar.scss overrode .sidebar styles I wrote.
after some hard refreshes:
after some refreshes, it is another way around:
Here is a component
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import SidebarLinks from './SidebarLinks';
import FormSelectPrinter from "../printer/FormSelectPrinter"
import sidebarData from "../data/";
import {ModalConsumer} from "../components/ModalContext";
import Modal from "../components/Modal";
import { createGlobalStyle } from "styled-components";
const GlobalSidebarStyle = createGlobalStyle`
.sidebar {
background-color: #303b4a;
padding-left: 0;
padding-right: 0;
padding-bottom:40px;
width: 240px;
}
.user__info {
background: #607D8B;
}
.user__info:hover {
background: #607D8B;
}
.user__name {
color: #fff;
}
.user__email {
color: #303b4a;
}
.dropdown-user-menu {
background: #607D8B;
position: relative;
width: 100%;
float: none;
}
.dropdown-select-language {
background: rgba(96, 125, 139, 0.6);
box-shadow: 0 4px 20px rgba(0,0,0,0.9);
right: -26px;
top: 53px;
user-select: none;
}
.dropdown-user-item:hover, .dropdown-user-item:focus {
color: black !important;
}
.dropdown-user-item {
color: white !important;
}
.navigation {
li {
a {
color: #adb5bd;
padding-left: 15px;
&.active {
color: white !important;
}
}
}
}
.navigation li:not(.navigation__active):not(.navigation__sub--active) a:hover {
background-color: rgba(0, 0, 0, 0.19);
color: white;
}
.id-green {
background-color: #73983F;
}
.language-text-color {
color: white !important;
}
.profile_image_style {
border-radius: 100%;
width: 80px;
height: 80px;
}
`
function Sidebar(props) {
const ModalSelectPrinter = ({onClose, ...otherProps}) => {
return (
<Modal>
<FormSelectPrinter onClose={onClose} md={12}></FormSelectPrinter>
</Modal>
)
};
return (
<>
<GlobalSidebarStyle />
<aside className={`sidebar ${props.sidebarToggled? 'toggled' : ''}`}>
<div className="scrollbar-inner">
<div style={{margin: '50px 0 30px 0'}} onClick={() => props.toggleUserInfo()}>
<div className={`user__info ${props.userInfoShown? 'show' : ''}`}>
<div style={{width: '100%', textAlign: 'center'}}>
<div className="user__name">{user.person === null ? user.name : user.person.full_name}</div>
<div className="user__email">{user.email}</div>
</div>
</div>
<div
className={`dropdown-menu dropdown-user-menu ${props.userInfoShown? 'show' : ''}`}>
<ModalConsumer>
{({showModal}) => (
<a className="dropdown-item dropdown-user-item" onClick = {()=>showModal(ModalSelectPrinter, {})}>Select</a>
)}
</ModalConsumer>
<a className="dropdown-item dropdown-user-item" onClick={() => props.logout()}>Log out</a>
</div>
</div>
<SidebarLinks sidebarData={sidebarData} toggleSidebar={props.toggleSidebar}></SidebarLinks>
</div>
</aside>
</>
)
}
export default Sidebar;
I have one large image on the top and three smaller images on the bottom of my page. I want to make it so when you hover the small image (it's also a link which goes to different place) the large image changes to this small image. So clearly explained, two images change/swap places. And when I unhover the large image changes back. I tried a couple solution but it didn't work so I'm in trouble, can you please help me?
I'm looking for CSS/Javascript-solution NOT JQUERY!
Thanks and sorry for bothering!
import React from "react";
import { Link } from "react-router-dom";
import "../screens/StyleName.css";
import { Card } from "react-bootstrap";
import Categories from "../components/Categories.json";
import { useLocation } from "react-router-dom";
// images:
import LargeImage from "../images/largeimage.jpg;
import SmallImage1 from "../images/small_image1.jpg";
import SmallImage2 from "../images/small_image2.jpg";
import SmallImage3 from "../images/small_image3.jpg";
import Placeholder from "../images/placeholder.jpg";
function FunctionName() {
let location = useLocation();
const ShowImage = (ImageName) => {
if (ImageName === "SmallImage1") {
return SmallImage1;
} else if (ImageName === "SmallImage2") {
return SmallImage2;
} else if (ImageName === "SmallImage3") {
return SmallImage3;
} else {
return Placeholder;
}
};
const AllCategories = () => {
return Categories.map((category, index) => {
const data = () => {
if (category.children) {
return { data: category.children };
} else {
return { data: undefined };
}
};
return (
<div key={index} className="category-card">
<Card style={{ border: "none" }}>
<Link
to={{
pathname: location.pathname + "/" + category.name,
state: data(),
}}
className="category-link link"
>
<div className="img__wrap">
<Card.Img
variant="top"
alt="card-img-top"
className="small-img-down img-responsive img__img"
src={ShowImage(category.name)}
/>
<p className="img__description">{category.name}</p>
</div>
</Link>
</Card>
</div>
);
});
};
return (
<div className="maincategory-top">
<div className="category-container">
<div className="col-sm-8">
<Link to="/product" className="category-link link">
<Card.Img
alt="card-img-top"
className="big-img img-responsive"
src={LargeImage}
/>
</Link>
<div className="row">{AllCategories()}</div>
</div>
</div>
</div>
);
}
export default FunctionName;
CSS:
.big-img {
display: block;
margin-left: auto;
margin-right: auto;
margin-bottom: 3%;
overflow: auto;
width: 470px;
height: 300px;
}
.category-container {
padding-left: 8%;
padding-bottom: 10%;
margin-top: 10%;
}
.card-title-main {
font-size: 10px;
letter-spacing: 1.2px;
font-weight: normal;
text-transform: uppercase;
}
a.category-link:link {
color: black;
background-color: transparent;
text-decoration: none;
}
a.category-link:visited {
color: black;
background-color: transparent;
text-decoration: none;
}
a.category-link:hover {
color: black;
background-color: transparent;
text-decoration: none;
}
a.category-link:active {
color: black;
background-color: transparent;
text-decoration: none;
}
.category2 {
margin-top: 1%;
text-align: center;
}
.small-img-down {
width: 120px;
height: 80px;
margin-right: 13px;
margin-bottom: 13px;
display: inline-block;
}
.small-img-down:hover {
transform: scale(0.9);
}
.category-card {
display: block;
margin-left: auto;
margin-right: auto;
}
.img__wrap:hover .img__description {
visibility: visible;
opacity: 1;
padding: 20px;
}
.img__description {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
text-transform: uppercase;
background: rgba(245, 245, 245, 0.363);
color: black;
letter-spacing: 1.2px;
text-align: center;
visibility: hidden;
font-size: 16px;
opacity: 0;
transition: opacity 0.2s, visibility 0.2s;
}
() => {
const default_large = "image_one"
const [largeImage, setLargeImage] = useState(default_large);
return(
<div>
<img
src={image_one}
onMouseEnter={() => setLargeImage("image_one")}
onMouseOut={() => setLargeImage(default_large)}
className={largeImage === "image_one" ? "large" : "small"}
/>
<img
src={image_two}
onMouseEnter={() => setLargeImage("image_two")}
onMouseOut={() => setLargeImage(default_large)}
className={largeImage === "image_two" ? "large" : "small"}
/>
<img
src={image_three}
onMouseEnter={() => setLargeImage("image_three")}
onMouseOut={() => setLargeImage(default_large)}
className={largeImage === "image_three" ? "large" : "small"}
/>
</div>
)
}
In your css.
img.large{
width: 500px
}
img.small{
width: 100px
}
Explanation:
Keep track of what image is large in your component state. Whenever an image is hovered on, update the state accordingly. After the hover event, return the state to its default state. The image will have the "large" class while its being hovered on, and when no image is being hovered on, the default large image will be large.
I'm building a react app using facebook's:
https://github.com/facebookincubator/create-react-app
along w SASS: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc
I'm at a point now where I need to add a dropdown menu to the header. Similar to the header icons on StackOverflow in the top right that open and close on click.
I know this sounds like a dumb question but what is the right way to do this? Do I need to add a UI Framework like a bootstrap for something like this? I have no need for all the bootstrap theming etc...
Thank you - and please be kind to the question given I'm a solo developer and could really use some help building a solid foundation on my app.
Thanks
Yes you can do this easily with just React:
class Hello extends React.Component {
render() {
return <div className="nav">
<Link />
<Link />
<Link />
</div>;
}
}
class Link extends React.Component {
state = {
open: false
}
handleClick = () => {
this.setState({ open: !this.state.open });
}
render () {
const { open } = this.state;
return (
<div className="link">
<span onClick={this.handleClick}>Click Me</span>
<div className={`menu ${open ? 'open' : ''}`}>
<ul>
<li>Test 1</li>
<li>Test 2</li>
<li>Test 3</li>
</ul>
</div>
</div>
)
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
.nav {
display: flex;
border-bottom: 1px solid gray;
background: white;
padding: 0 10px;
}
.link {
width: 100px;
border-right: 1px solid gray;
padding: 10px;
text-align: center;
position: relative;
cursor: pointer;
}
.menu {
opacity: 0;
position: absolute;
top: 40px; // same as your nav height
left: 0;
background: #ededed;
border: 1px solid gray;
padding: 10px;
text-align: center;
transition: all 1000ms ease;
}
.menu.open {
opacity: 1;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
you can use react-select like this :
var Select = require('react-select');
var options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
];
function logChange(val) {
console.log("Selected: " + JSON.stringify(val));
}
<Select
name="form-field-name"
value="one"
options={options}
onChange={logChange}
/>
https://github.com/JedWatson/react-select
also this library :
https://www.npmjs.com/package/react-dropdown
Seems like your project is still in his infancy. And that you willing to incorporate a library to your project. So I would definitely recommend you to choose a library right now.
With React you could create your own menu without much effort. But you will also need other components for the rest of your app. And the quality of your menu (and other components) will most likely be greater if you choose a library used by many (rather than your own). For "quality" I mean: UX design, HTML standards, API reusability, number of defects, etc.
If you think your app will be small and won't need an entire UI Framework, you might want to search for an isolated component for menu. Here is a list of navigation components (including the number of github stars of each project):
https://devarchy.com/react/topic/navigation
But in most cases I would choose an entire UI Framework instead: https://devarchy.com/react/topic/ui-framework
And here are some demos of the menu/nav/app-bar of some popular UI Frameworks:
https://ant.design/components/menu/
https://react-bootstrap.github.io/components.html#navs-dropdown
http://www.material-ui.com/#/components/app-bar
Custom dropdown
Dropdown.js
import React, { useState } from "react";
import { mdiMenuDown } from "#mdi/js";
import Icon from "#mdi/react";
export default function DropDown({ placeholder, content }) {
const [active, setactive] = useState(0);
const [value, setvalue] = useState(0);
return (
<div className={active ? "dropdown_wrapper active" : "dropdown_wrapper"}>
<span
onClick={() => {
setactive(active ? 0 : 1);
}}
>
{value ? value : placeholder} <Icon path={mdiMenuDown} />
</span>
<div className="drop_down">
<ul>
{content &&
content.map((item, key) => {
return (
<li
onClick={() => {
setvalue(item);
setactive(0);
}}
key={key}
>
{item}
</li>
);
})}
</ul>
</div>
</div>
);}
dropdown.css
.dropdown_wrapper {
position: relative;
margin-left: 100px;
cursor: pointer;
}
.dropdown_wrapper span {
padding: 12px;
border: 1px solid #a8aaac;
border-radius: 6px;
background-color: #ffffff;
display: flex;
color: #3d3e3f;
font-size: 16px;
letter-spacing: 0;
line-height: 26px;
justify-content: space-between;
text-transform: capitalize;
}
.dropdown_wrapper span svg {
width: 20px;
margin-left: 80px;
fill: #fbb800;
transition: 0.5s ease all;
}
.dropdown_wrapper.active span svg {
transform: rotate(180deg);
transition: 0.5s ease all;
}
.dropdown_wrapper .drop_down {
background-color: #fff;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.2);
position: absolute;
top: 53px;
width: 100%;
z-index: 9;
border-radius: 6px;
border: 1px solid #a8aaac;
height: 0px;
opacity: 0;
overflow: hidden;
transition: 0.5s ease all;
}
.dropdown_wrapper.active .drop_down {
height: fit-content;
opacity: 1;
transition: 0.5s ease all;
}
.dropdown_wrapper .drop_down ul {
list-style: none;
padding-left: 0;
margin: 0;
padding: 10px;
}
.dropdown_wrapper .drop_down ul li {
padding: 10px 0px;
color: #3d3e3f;
font-size: 16px;
letter-spacing: 0;
line-height: 26px;
text-transform: capitalize;
cursor: pointer;
font-weight: 300;
}
.dropdown_wrapper .drop_down ul li:hover {
color: #faab1e;
transition: 0.5s ease all;
}
parent.js
<DropDown placeholder="select a type" content={["breakfast", "lunch", "dinner", "Snacks"]} />