Here's what I've have so far - Full working view https://codesandbox.io/s/hungry-elbakyan-v3h96
Accordion component:
const Accordion = ({ data }) => {
return (
<div className={"wrapper"}>
<ul className={"accordionList"}>
{data.map((item) => {
return (
<li className={"accordionListItem"} key={item.title}>
<AccordionItem {...item} />
</li>
);
})}
</ul>
</div>
);
};
const AccordionItem = ({ content, title }) => {
const [state, setState] = useState({
isOpened: false
});
return (
<div
className={cn("accordionItem", state.isOpened && "opened")}
onClick={() => setState({ isOpened: !state.isOpened })}
>
<div className={"lineItem"}>
<h3 className={"title"}>{title}</h3>
<span className={"icon"} />
</div>
<div className={"inner"}>
<div className={"content"}>
<p className={"paragraph"}>{content}</p>
</div>
</div>
</div>
);
};
When I click on the accordion item nothing happens. I can see the content appears in inspect and the state changes as expected but it doesn't slide down. Did I miss something in my css or component?
Here is what I was able to achieve. You may not like it completely(animations). But things seems sorted
https://codesandbox.io/s/relaxed-babbage-2zt4f?file=/src/styles.css
props name was not right for accordion body
and styles need to be changes once the accordion is in open state.
You need to add or remove the className inner when state.isOpen so you can see your content
Related
I am creating a Next js site mcqs and answer.
Initially only questions are rendered with the title and options.
There is a button to show the answer of given question but when button is clicked it is changing the state of all elements in the map function instead of element that is clicked.
export default function Chapter({ chapter }) {
const [right, setRight] = useState(false)
function handleOnClick() {
setRight(!right)
}
<main className='main_q'>
<h1>{chapter.items[0].name}</h1>
{chapter.items[0].questions.items.map((question, index) => {
return (
<div key={question.id} className='question_container'>
<div className='question_q_t'>
<div className='question_q'>Q</div>
<div className='question_t'>
<Markdown>{question.title}</Markdown>
</div>
</div>
<div className='option_container'>
<div className='option_a_o'>
<div className='option_a'>A</div>
<div className='option_o'>
<Markdown>{question.optionA}</Markdown>
</div>
</div>
<div className='option_a_o'>
<div className='option_a'>B</div>
<div className='option_o'>
<Markdown>{question.optionB}</Markdown>
</div>
</div>
<div className='option_a_o'>
<div className='option_a'>C</div>
<div className='option_o'>
<Markdown>{question.optionC}</Markdown>
</div>
</div>
<div className='option_a_o'>
<div className='option_a'>D</div>
<div className='option_o'>
<Markdown>{question.optionD}</Markdown>
</div>
</div>
</div>
<a
className='solution_link'
target='_blank'
href={`/${question.chapter.subject.category.slug}/${question.chapter.subject.slug}/${question.chapter.slug}/${question.id}`}
>
See Solution
</a>
<button onClick={handleOnClick}>Answer</button>
{right && <div>{question.rightAnswer}</div>}
</div>
)
})}
</main>
}
Put each question div into its own component, and make a right state in that component:
const Question = ({ question }) => {
const [right, setRight] = useState(false)
return (
<div key={question.id} className='question_container'>
// etc
Or make an array of right states in the parent:
export default function Chapter({ chapter }) {
const qs = chapter.items[0].questions.items;
const [rights, setRights] = useState(qs.map(q => false));
const makeHandleClick = (i) => {
setRights(
rights.map((r, j) => j === i ? r : !r)
);
};
// ...
<button onClick={makeHandleClick(i)}>Answer</button>
{rights[i] && <div>{question.rightAnswer}</div>}
this is my code i'm trying to add a class on click to a clicked div but i have more than 1 div have the same classname so when i click to any
div the toggle class added to all divs not the one which i clicked what i want to know how can i specify the div which i want to add toggle class to it
Code:
const [isActive, setActive] = useState(false);
const toggleClass = () => {
setActive(!isActive)
console.log('sad')
}
return (
<div className="command_wrapper">
<div className="command_list">
{
Commands.map((item, index) => {
return (
<div className="command" >
<div className="command_face" onClick={toggleClass}>
<h1>{item.Command}</h1>
<p>{item.Description}</p>
</div>
<div className={isActive ? "command_body" : "disapper"}>
<div className="command_usage">
<h1>Usage</h1>
<p>{item.Usage}</p>
</div>
<div className="command_required">
<h1>Required Permissions</h1>
<p>{item.premissions}</p>
</div>
</div>
</div>
)
})
}
</div>
</div>
```
You can pass the item inside toggle function and verify if item passed is activated or just save the item clicked.
const [itemActive, setItemActive] = useState();
const toggleClass = (item) => {
setItemActive(item)
}
return (
<div className="command_wrapper">
<div className="command_list">
{
Commands.map((item, index) => {
return (
<div className="command" >
<div className="command_face" onClick={() => toggleClass(item)}>
<h1>{item.Command}</h1>
<p>{item.Description}</p>
</div>
<div className={item === itemActive ? "command_body" : "disapper"}>
<div className="command_usage">
<h1>Usage</h1>
<p>{item.Usage}</p>
</div>
<div className="command_required">
<h1>Required Permissions</h1>
<p>{item.premissions}</p>
</div>
</div>
</div>
)
})
}
</div>
</div>
```
If item has any unique property, you can save just then, like an ID or name. I think it will be better.
/*const [isActive, setActive] = useState(false);
const toggleClass = () => {
setActive(!isActive)
console.log('sad')
}*/
function handleClick(el){
//toggle the class which indicates selection ex. 'active'
el.classList.toggle('active');
//other stuff todo
}
return (
<div className="command_wrapper">
<div className="command_list">
{
Commands.map((item, index) => {
return (
<div className="command" >
//destruct event objet{event.target}
<div onClick={({target})=>handleClick(target)}>
<h1>{item.Command}</h1>
<p>{item.Description}</p>
</div>
....
...
</div>
)
})
}
</div>
</div>
I want add active class to click element but it is toogle. How can i fixed it?
const PodcastTab = () => {
const [tabOpened, setTabOpened] = useState(false);
return <div>
<div>
<span className={classNames('my-podcast',{'active':tabOpened})} onClick={()=>{setTabOpened(!tabOpened)}}>My Podcast</span>
<span className={classNames('podcasts-stats',{'active':!tabOpened})} onClick={()=>{setTabOpened(!tabOpened)}}>Podcast's Stats</span>
<div className="my-podcast-tab">
<Podcast />
</div>
<div className="podcasts-stats-tab">
<Podcast imgURL="https://i.picsum.photos/id/144/75/75.jpg?hmac=9kweqWXv0sL19dFj1CaMKxbH3kQMIuFFbHy2hWhKJ4w" status="x" title="y"/>
</div>
</div>
</div>;
}
You can use the following className:
className={classNames('podcasts-stats',{tabOpened ? 'active' : ''})}
I have a PLUS button that open a Materialize CSS Modal in React :
Plus button
import React from "react";
const AddBtn = ({ tooltipMessage, hrefDescription }) => {
const hrefAddBtn = "#" + hrefDescription;
return (
<div className="fixed-action-btn">
<a
href={hrefAddBtn}
data-position="left"
data-tooltip={tooltipMessage}
className="btn-floating btn-large blue darken-2 modal-trigger tooltipped"
>
<i className="large material-icons">add</i>
</a>
</div>
);
};
export default AddBtn;
And the Modal :
const CreditModal = ({ closeModal }) => {
return (
<Fragment>
<div id="add-balance" className="modal" style={modalStyle}>
..... A lot of code goes here
<div>
</Fragment>
);
}
Both of them inside a component :
const AddCredit = ({........}) => {
return (
<div className="container">
{someBoolean === true? (
<Fragment>
<AddBtn tooltipMessage="Add Credit" hrefDescription="add-balance" />
<CreditModal closeModal={closeModalAndOpenIFrame} />
</Fragment>
) : (
<Fragment>
// Show some other Component
</Fragment>
)}
</div>
)
}
When I close the frame using a button the modal closes but the overlay remains , it looks like this :
<div class="modal-overlay" style="z-index: 1002; display: block; opacity: 0.5;"></div>
It's not my doing , probably it comes from the modal and remains , and the only way to get rid of this is clicking on the overlay , and I don't want that.
How can we remove this overlay programmatically ?
on close button click function make the class display none
for example
$("button").click(function(){
$(".modal-overlay").css("display","none");
});
I am using foundation for css. When an icon is clicked to add persona, a modal should appear. How can i open a modal without using jquery?
Here is my code
export default class Campaign extends Component {
state = {
adsShow: false,
personasShow: false
};
handlePersonasClick = () =>
this.setState({ personasShow: !this.state.personasShow });
renderCampaigns = () => {
return campaigns.map((campaign, i) => {
return (
<Collapsible
key={campaign.name}
trigger={this.campaignTitle(campaign)}
classParentString="campaignsCollapse">
<div className="Ads">
<span className="cmpTitle">Ads</span>
<span className="editCampaign">
<FaPlusCircle onClick={this.handleClick} />
</span>
</div>
<div className="AdsList">
{this.state.adsShow
? <CreateNewAd
personasClick={this.handlePersonasClick}
personasShow={this.state.personasShow}
/>
: null}
{this.renderAdLists(campaign.ads)}
</div>
</Collapsible>
);
});
};
render() {
return (
<div style={{ padding: '10px 20px' }}>
<h3>Campaigns</h3>
<div className="campaignsContainer">
{this.renderCampaigns()}
</div>
</div>
);
}
}
const CreateNewAd = props => {
return (
<Collapsible trigger={adsTitle()} classParentString="adsCollapse" open>
<p>
Personas
{' '}
<span><FaPlusCircle onClick={props.personasClick} /></span>
{props.personasShow ? <Personas /> : null}
</p>
</Collapsible>
);
};
export const Personas = () => {
return (
<div
id="myModal"
className="reveal-modal"
data-reveal
aria-labelledby="modalTitle"
aria-hidden="true"
ref={modal => {
this.modal = modal;
}}
role="dialog">
<h2 id="modalTitle">Awesome. I have it.</h2>
<a className="close-reveal-modal" aria-label="Close">×</a>
</div>
);
};
the following code snippet is on the CreateNewAd component which is a child component of Campaign Component. When FaPlusCircle icon is clicked a modal should appear. How can i do that when following top to bottom approach and without using jquery ?
UPDATE
have created a sandbox. here is the link https://codesandbox.io/s/qx9Pv1lry . You have to click on magazine print. An accordion menu shows up. After that click on click text that is aside Ads text. There you will see open modal text. Where clicking should open a modal which is what the question is about.