I'm importing this component into NewComponent.jsx
import OptionsMenu from "../../components/OptionsMenu/OptionsMenu";
where it's rendered as such:
<OptionsMenu
options={[
{
icon: "trash-alt",
action: () => this.toggleDeleteModal(index),
title: "Delete",
},
]}
/>
The options menu component uses a file called styles.js which has a colour set too:
export const OptionsMenuDropDown = styled.div`
position: absolute;
top: -40px;
left: -200%;
color: #0F4379;
So it's usage would be
<OptionsMenuDropDown>
<ol>
{options.map((option, index) => {
return (
<li>
<button className="options-btn" key={index} onClick={option.action}>
<p >{option.title}</p>
</button>
</li>
);
})}
</ol>
</OptionsMenuDropDown>
Is it possible to change this colour when its being used in NewComponent.jsx ? So that I can override it with another colour?
I cannot use a separate .css file for NewComponent.jsx but can use a styles.js. There is also a global css file too
You can pass a prop into your styled component, like the color.
const OptionsMenu = ({color}) => {
return (
<OptionsMenuDropDown color="color">
<ol>
{options.map((option, index) => {
return (
<li>
<button className="options-btn" key={index} onClick={option.action}>
<p >{option.title}</p>
</button>
</li>
);
})}
</ol>
</OptionsMenuDropDown>
)
}
Then in your styles.js.
export const OptionsMenuDropDown = styled.div`
position: absolute;
top: -40px;
left: -200%;
color: ${props => props.color};
Then you can use it in you NewComponent passing another color as a prop.
const NewComponent = () => {
<OptionsMenu color="#fff" />
}
Related
I have a button navigation and when you click on a button, the active class is added. My goal is for the active class to be added to the button clicked, but remove that class of active on all other buttons if present. The 'About' button will have a class of active on page load.
Not sure how to translate this to React, in JavaScript on click I would remove the class from all the elements in a loop and add a class to the target clicked if it did not already have the active class.
Code Sandbox - https://codesandbox.io/s/toggle-active-on-class-clicked-remove-from-the-rest-r467l1?file=/src/App.js
export default function Header() {
const [active, setActive] = useState(true);
const toggleColor = function (e) {
// on load, 'About' button has active class
// when clicking another menu item add active class, remove active from the rest of buttons
console.log(e.target);
};
return (
<header className="header-img-container">
<nav>
<ul>
<li>
<button onClick={toggleColor} className={active ? "active" : ""}>
About
</button>
</li>
<li>
<button onClick={toggleColor}>Skills</button>
</li>
<li>
<button onClick={toggleColor}>Projects</button>
</li>
<li>
<button onClick={toggleColor}>Words</button>
</li>
</ul>
</nav>
</header>
);
}
There are so many ways to solve that problem. You can try this if it's meet your requirements.
import "./styles.css";
import { useState } from "react";
const list = ["About", "Skills", "Projects", "Words"];
export default function Header() {
const [activeLink, setActiveLink] = useState("About");
return (
<header className="header-img-container">
<nav>
<ul>
{list.map((item) => (
<li key={item}>
<button
onClick={() => setActiveLink(item)}
className={activeLink === item ? "active" : ""}
>
{item}
</button>
</li>
))}
</ul>
</nav>
</header>
);
}
Create a state like this
const [active, setActive] = useState({About: true, Skills: false, Projects: false, Words: false})
А change local parameter to add a class to element. For example
<li>
<button onClick={() => {
setActive({...active, About: false, Skills: true, Projects: false,
Words: false })
}}>Skills</button>
</li>
There are many possible approaches, here is a basic example that uses an object type active state to store the value for each list item.
const [active, setActive] = useState({ About: true })
The list data is stored in an array so it can be mapped in the JSX part of the component.
const itemList = ["About", "Skills", "Projects", "Words"]
While index is not an ideal key it is used here just for example purpose.
{
itemList.map((item, index) => (
<li key={index}>
<button
onClick={() => toggleColor(item)}
className={active[item] ? "active" : ""}
>
{item}
</button>
</li>
));
}
toggleColor sets value for active, and it specify that active should always be in the format of {About: true}, {Skills: true} and such. The !!! covers the case when certain keys are not existing in the object.
const toggleColor = function (item) {
setActive((prev) => {
return { [item]: !!!prev[item] };
});
};
Below is the full example, it runs in the snippet for convenience.
function Header() {
const [active, setActive] = React.useState({ About: true });
const itemList = ["About", "Skills", "Projects", "Words"];
const toggleColor = function (item) {
// on load, 'About' button has active class
// when clicking another menu item add active class, remove active from the rest of buttons
setActive((prev) => {
return { [item]: !!!prev[item] };
});
};
return (
<header className="header-img-container">
<nav>
<ul>
{itemList.map((item, index) => (
<li key={index}>
<button
onClick={() => toggleColor(item)}
className={active[item] ? "active" : ""}
>
{item}
</button>
</li>
))}
</ul>
</nav>
</header>
);
}
const App = () => {
return (
<div>
<Header />
</div>
);
};
ReactDOM.render(<App />, document.querySelector("#root"));
.App {
font-family: sans-serif;
text-align: center;
}
button {
padding: 6px;
}
.active {
border: 1px solid pink;
color: hotpink;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>
I am trying to achieve two things:
(1) each time I click on the red arrow icon in the sidebar, I want the sidebar to collapse or open. From the below video, you'd see that the active and inactive states are already there. However, the sidebar doesn't collapse on inactive.
(2) each time I click on the Content menu, which is a drowndown menu, it doesn't open the submenu. Also, from the below video, you'd notice that the active and inactive states are already there. However, the dropdown still doesn't open on active.
Below is the video that clearly shows the error:
https://www.loom.com/share/6e0488101cee4c5b9bac7ded782b8807
Docs.js Page
import React from "react";
import { Helmet } from "react-helmet";
import SideMenu from "../docs/SideMenu";
const Docs = () => {
return (
<div className="">
<Helmet>
<title>Docs :: MyApp</title>
<meta name="description" content="MyApp" />
</Helmet>
<SideMenu />
</div >
)
};
export default Docs
SideMenu.js Component
import React, { useState } from "react";
import { Helmet } from "react-helmet";
import * as Icon from "react-bootstrap-icons";
import MenuItems from "./MenuItems";
const SideMenu = () => {
const [inActive, setInActive] = useState(false)
return (
<div className="">
<div className={`side-menu ${inActive ? "inActive" : ""}`}>
<Helmet>
<title>Docs :: MyApp</title>
<meta name="description" content="MyApp" />
</Helmet>
<div className="top-section">
<div className="logo">
<img src="/assets/media/logos/naked.png" alt="MyApp" />
</div>
<div onClick={() => setInActive(!inActive)} className="toggle-back">
{inActive ? (<Icon.ArrowLeftSquareFill />) : (<Icon.ArrowRightSquareFill />)}
</div>
</div>
<div className="search-bar">
<button className="search-bar-btn">
<Icon.Search />
</button>
<input type="text" placeholder="search" />
</div>
<div className="divider"></div>
<div className="main-menu">
<ul>
{menuItems.map((menuItem, index) => (
<MenuItems
key={index}
name={menuItem.name}
to={menuItem.to}
subMenu={menuItem.subMenu || []} />
))}
{/*<li>
<a className="menu-item">
<Icon.ArrowRightSquareFill className="menu-icon" />
<span>Dashboard</span>
</a>
</li>
<MenuItems
name={"Content"}
subMenu={[
{ name: 'Courses' },
{ name: 'Videos' },
]}
/>
<li>
<a className="menu-item">
<Icon.ArrowRightSquareFill className="menu-icon" />
<span>Support</span>
</a>
</li>*/}
</ul>
</div>
<div className="side-menu-footer">
<div className="avatar">
<img src="/assets/media/avatars/aa/brooks_lloyd.png" alt="MyApp" />
</div>
<div className="user-info">
<div className="font-size-h6">Title</div>
<div className="font-size-sm">Subtitle</div>
</div>
</div>
</div>
</div>
);
};
export default SideMenu
const menuItems = [
{ name: "Dashboard", to: "/" },
{ name: "Content", to: "/", subMenu: [{ name: "Courses" }, { name: "Videos" }], },
{ name: "Design", to: "/" },
];
MenuItems.js Component
import React, { useState } from "react";
import * as Icon from "react-bootstrap-icons";
const MenuItems = (props) => {
const { name, subMenu } = props;
const [expand, setExpand] = useState(false);
return (
<div className="">
<li>
<a onClick={() => setExpand(!expand)} className="menu-item">
<Icon.ArrowRightSquareFill className="menu-icon" />
<span>{name}</span>
</a>
{
subMenu && subMenu.length > 0 ? (
<ul className={`sub-menu ${expand ? "active" : ""}`}>
{subMenu.map((menu, index) =>
<li key={index}>
<a className="sub-menu">
<Icon.ArrowRightSquareFill className="menu-icon" />
{menu.name}
</a>
</li>
)}
</ul>) : null}
</li>
</div>
);
};
export default MenuItems
Docs.css File that contains the suspected errors, which are the side-menu and sub-menu lines:
.side-menu {
position: fixed;
background: #000;
width: 300px;
height: 100%;
box-sizing: border-box;
padding: 30px 20px;
transition: width .2s ease-in;
}
.side-menu.inactive {
width: 80px;
}
.side-menu .main-menu .sub-menu {
color: #333;
margin-left: 20px;
border-left: 1px solid #666;
box-sizing: border-box;
padding-left: 30px;
max-height: 0;
overflow: hidden;
transition: max-height .2s ease-in;
}
.side-menu .main-menu .sub-menu.active {
max-height: 200px;
}
I've just implemented the react material ui carousel, and it was pretty straightforward, the only thing i didn't catch, is how to hide buttons and show them only on over.
I noticed the props navButtonsAlwaysVisible and set it to false but it isn't enough.
Should i implement my own logic for that, or maybe I'm just missing something?
here's the component code:
import styles from '../../styles/Testimonial.module.scss'
import Image from 'next/image'
import Carousel from 'react-material-ui-carousel'
const Testimonial = _ => {
const items = [
{
imageUrl: "/png/image0.webp",
feedback: "feedback0",
name: "name0",
location: "location0"
},
{
imageUrl: "/png/image1.jpeg",
feedback: "feedback1",
name: "name1",
location: "location1"
}
]
return (
<div id="customers" className={`section ${styles.testimonial}`}>
<h2 className={`title ${styles.title}`}>Clientes Felizes</h2>
<span className={"separator"}> </span>
<Carousel
className={styles.carousel}
autoPlay={true}
stopAutoPlayOnHover={true}
interval={5000}
animation={"slide"}
swipe={true}
navButtonsAlwaysVisible={false}
navButtonsProps={{
style: {
backgroundColor: "#8f34eb",
opacity: 0.4
}
}}
>
{
items.map( (item, i) => <Item key={i} item={item} /> )
}
</Carousel>
</div>
)
}
function Item(props)
{
return (
<article className={styles.testimonial__card}>
<div className={styles.testimonial__photo_container}>
<Image
className={styles.testimonial__photo}
src={props.item.imageUrl}
alt="Testimonial"
width={312}
height={300}
/>
</div>
<p className={styles.testimonial__copy}>{props.item.feedback}</p>
<span className={styles.testimonial__name}>{props.item.name}</span>
<span className={styles.testimonial__city}>{props.item.location}</span>
</article>
)
}
export default Testimonial;
there's a prop called navButtonsAlwaysInvisible
navButtonsAlwaysInvisible={true}
You can try using Custom CSS for your purpose. Based on the current rendered markup,
.jss6 {
opacity: 0;
transition: all ease 1000ms; /* So that it does not disappear quickly */
}
You can define the hover for the parent so that it displays only when the parent container is hovered on:
.jss1.Testimonial_carousel__3rny3:hover .jss6 {
opacity: 1;
}
This is how it works now:
I have a Navbar with tabs, and I want to make a function called onClick that gets the event, and adds a class to that tab "active". But, when I click another tab, it should remove a class from the previous tab and add it to that one.
Sample of my code:
const [clickedTab, setClickedTab] = useState(true);
function Click() {
if (clickedTab === true) {
console.log(clickedTab);
tab.classList.add("active");
}
else {
console.log("Error!");
}
}
In React use the model (via useState() in this case) to make changes to the view.
Set the activeId of the tab in the state, and if the tab's id is equal to activeId pass set it's active to true. The tab itself can add/remove the className.
const { useState } = React;
const Tab = ({ id, active, setActive }) => (
<li
className={`tab ${active ? 'active' : ''}`}
onClick={() => setActive(id)}
>
{id}
</li>
);
const Example = ({ tabs }) => {
const [activeId, setActive] = useState();
return (
<ul className="tabs">
{tabs.map(id => (
<Tab
key={id}
id={id}
setActive={setActive}
active={id === activeId}
/>
))}
</ul>
);
}
const tabs = [1, 2, 3, 4];
ReactDOM.render(
<Example tabs={tabs} />,
root
);
.tabs {
display: flex;
list-style: none;
}
.tab {
height: 1em;
width: 2em;
border: 1px solid red;
text-align: center;
cursor: pointer;
}
.active {
background: red;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
Here is a simple example so you can get the idea; we hold current active element id in a state then based on that we decide what class name it should have; no need to use classList's add or remove
function Header () {
const [active, setActive] = React.useState();
return (
<header>
<ul>
<li
className={active === 1? "red":"blue"}
onClick={()=>setActive(1)}
>a</li>
<li
className={active === 2? "red":"blue"}
onClick={()=>setActive(2)}
>b</li>
<li
className={active === 3? "red":"blue"}
onClick={()=>setActive(3)}
>c</li>
</ul>
</header>
);
}
ReactDOM.render( <Header />, app );
.red{background:red}.blue{background:blue}li{color:#fff;width:30px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
I'm trying to use emotion.
My .js code is:
import React from 'react';
import { css } from '#emotion/core';
export const Menu = () => (
<>
<nav
css={css`
position: absolute;
color: white;
`}
>
<h1
css={css`
color: white;
`}
>
Title
</h1>
<ul>
<li>Proyectos</li>
<li>Blog</li>
<li>Acerca</li>
<li>Contacto</li>
</ul>
</nav>
</>
);
export default Menu;
When inspecting the element, I get this instead:
You have tried to stringify object returned from css function. It isn't supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop).
Use JSX Pragma with jsx function from '#emotion/react'. This allow use css prop.
Docs: https://emotion.sh/docs/css-prop#jsx-pragma
/** #jsx jsx */
import { jsx } from '#emotion/react'
import { css } from '#emotion/core'
const App = () => (
<nav
css={css`
position: absolute;
color: white;
`}
>
<h1
css={css`
color: white;
`}
>
Title
</h1>
<ul>
<li>Proyectos</li>
<li>Blog</li>
<li>Acerca</li>
<li>Contacto</li>
</ul>
</nav>
)