I am using a bootstrap modal for my application. It works fine in the beginning, but once I open the menu bar and close it, modal does not open anymore nor the backdrop does not go away even though I click it.
I have screenshots for better understanding.
1.landing page
2.testing modal(working)
3.open side menu bar
4.after closing the side menu, try opening the modal again(not working)
To open the menu bar, I use transform: translateX() on body tag so technically the whole body moves side to side to show the menu.
If I comment out the transform: translateX(), modal works fine even after I click the menu bar(it obviously does not show the menu, but other css properties work the same except transform).
So I found out transforming property causes the problem with the modal, but I don't understand why and how to fix it.
EDITTED ( code added ):
import 'App.css';
class App extends Component {
constructor(props) {
super(props);
this.menu_bar = false;
}
toggleMenu = () => {
const app = document.querySelector('.App');
if( this.menu_bar ){
app.style.transform = 'translateX(0)';
app.classList.remove('coverApp');
this.menu_bar = false;
}else {
app.style.transform = 'translateX(300px)';
app.classList.add('coverApp');
this.menu_bar = true;
}
}
hideMenu = (e) => {
const app = document.querySelector('.App');
if( e.target.classList.contains('coverApp') ){
app.style.transform = 'translate(0)';
app.classList.remove('coverApp');
this.menu_bar = false;
}
}
render() {
return (
<div className="App" onClick={this.hideMenu}>
<Navbar toggleMenu={this.toggleMenu}/>
<LeftMenuBar toggleMenu={this.toggleMenu}/>
<Route path="/" exact component={HomePage}/>
</div>
)
}
}
function Navbar(props) {
const { toggleMenu } = props;
return (
<nav className="Navbar">
<span>
<div id="nav-toggle" onClick={toggleMenu} >☰</div>
...
</span>
</nav>
)
}
function LeftMenuBar(props) {
const { toggleMenu } = props;
return (
<main className="LeftMenuBar">
<div className="content">
<div className="controller">
<p>ENGLISH</p>
<div className="btn-close" onClick={toggleMenu}>CLOSE</div>
...
</div>
</div>
</main>
)
}
class HomePage extends Component {
render() {
return (
<main className="HomePage">
<button type="button" id="modal-btn" className="btn btn-primary" data-toggle="modal" data-target="#home_modal" aria-label="close">
LETS START!
</button>
<div className="HomeModal">
<div id="home_modal" className="modal" tabIndex="-1" role="dialog" aria-labelledby="home_modal">
<div className="modal-dialog" role="document" style={{marginTop: '150px', maxWidth: '750px'}}>
<div className="modal-content">
<div className="modal-body" style={{backgroundColor: 'white'}}>...</div>
</div>
</div>
</div>
</div>
</main>
)
}
}
CSS
body {
overflow: hidden;
}
.App {
transition: transform 0.5s;
}
.coverApp::before {
content: '';
opacity: 1;
position: absolute;
width: 100vw;
height: 100vh;
left: 0;
top: 0;
z-index: 300;
background-color: rgba(0, 0, 0, .75);
transition: all 0.5s ease-in-out;
}
.LeftNavbar {
position: fixed;
background: rgba(50, 50, 50);
color: #f1f1f1;
width: 300px;
height: 100vh;
top: 0;
left: -300px;
border-right: solid 0.2px lightgray;
}
#modal-btn {
position: absolute;
top: 350px;
left: 500px;
}
.HomeModal {
position: absolute;
top: 350px;
left: 700px;
}
Related
I am trying to write a useState() Hook, and perhaps add useEffect() to solve active state on two buttons. It is Delivery buttons that needs the first button-delivery to be active using CSS change, and if clicked on second button, PickUp, it should change CSS UI to stay active.
And yes if it is anyhow possible i want to use Hooks.
Is there any possible way to have it done on this way?
const Header = props => {
const [isActive, setIsActive] = useState(false);
function changeButtons () {
setIsActive = (!isActive)
};
return (
<Fragment>
<header className={classes.header}>
<div className={classes.logo} onClick={reload}>
<div >
Foodzilla
</div>
</div>
<div className={classes.delivery}>
<div
className={isActive ? classes.deliveryAction : classes.deliveryChoice}
onChange={changeButtons}
>Delivery</div>
<div className={classes.or}>or</div>
<div
className={isActive ? classes.pickUpAction : classes.pickUpChoice}
onChange={changeButtons}
>Pick Up</div>
</div>
Okay, so I did a mockup of what you are trying to do (I think :D). Here is a link to the working solution: https://codesandbox.io/s/quiet-mountain-68e10k?file=/src/styles.css:59-775.
The code is also below. There is definitely some refactoring that can be done, but I wanted to at least get you started on the right path.
Quick Summary:
Blue is Cicked (takes precedence over hover and default when active).
Green is Hovered (goes back to default when outside the div).
Red is Default (if not clicked or hovered, show red).
import "./styles.css";
import React, { useState } from "react";
export default function App() {
const [isDeliveryClicked, setIsDeliveryClicked] = useState(false);
const [isPickupClicked, setIsPickupClicked] = useState(false);
const [isDeliveryHovered, setIsDeliveryHovered] = useState(false);
const [isPickupHovered, setIsPickupHovered] = useState(false);
const handleClick = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryClicked(true);
setIsDeliveryHovered(false);
if (isDeliveryClicked === true) {
setIsDeliveryClicked(false);
setIsDeliveryHovered(true)
}
} else if (e.target.className.includes("pickup")) {
setIsPickupClicked(true);
setIsPickupHovered(false);
if (isPickupClicked === true) {
setIsPickupClicked(false);
setIsPickupHovered(true)
}
}
};
const handleOnMouseOver = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryHovered(true);
} else if (e.target.className.includes("pickup")) {
setIsPickupHovered(true);
}
};
const handleOnMouseLeave = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryHovered(false);
} else if (e.target.className.includes("pickup")) {
setIsPickupHovered(false);
}
};
const handleClassStyler = (buttonType) => {
if (buttonType === 'delivery') {
if (isDeliveryClicked === true) {
return "deliveryClicked";
} else if (isDeliveryHovered === true && isDeliveryClicked === false) {
return "deliveryHovered";
} else if (isDeliveryClicked === false && isDeliveryHovered === false) {
return "delivery";
}
} else if (buttonType === 'pickup'){
if (isPickupClicked === true) {
return "pickupClicked";
} else if (isPickupHovered === true && isPickupClicked === false) {
return "pickupHovered";
} else if (isPickupClicked === false && isPickupHovered === false) {
return "pickup";
}
}
};
return (
<div className="App">
<div
onMouseOver={handleOnMouseOver}
onMouseLeave={handleOnMouseLeave}
onClick={handleClick}
className={handleClassStyler('delivery)}
>
Delivery
</div>
<div
onMouseOver={handleOnMouseOver}
onMouseLeave={handleOnMouseLeave}
onClick={handleClick}
className={handlePickupClassStyler('pickup')}
>
Pick Up
</div>
</div>
);
}
The CSS I used for above is:
.delivery {
width: 100px;
height: 100px;
background-color: red;
border: solid black 5px;
margin: 5px;
}
.deliveryClicked {
width: 100px;
height: 100px;
background-color: blue;
border: solid black 5px;
margin: 5px;
}
.deliveryHovered {
width: 100px;
height: 100px;
background-color: green;
border: solid black 5px;
margin: 5px;
}
.pickup {
width: 100px;
height: 100px;
background-color: red;
border: solid black 5px;
margin: 5px;
}
.pickupClicked {
width: 100px;
height: 100px;
background-color: blue;
border: solid black 5px;
margin: 5px;
}
.pickupHovered {
width: 100px;
height: 100px;
background-color: green;
border: solid black 5px;
margin: 5px;
}
Well,
After reading all the input (which was incredibly helpful to get my logic straight) i have come with an idea and some refactoring:
However, as almost close to a solution i still need to solve my default state. And i am stuck again.
Default state should be Delivery, and the (button) should have active CSS as well.
Also, when i add CSS .deliveryChoice:hover {} it does not respond. My guess is that, as it is a child component the header don't respond as it reads no inside buttons.
Right now, they are both off.
My Header component:
const Header = props => {
return (
<Fragment>
<header className={classes.header}>
<div className={classes.logo} onClick={reload}>
<div >
Foodzilla
</div>
</div>
<div className={classes.delivery}>
<DeliveryButton
className={classes.deliveryChoice}
/>
</div>
<div>
<div className={classes.deliveryAdress}>
Delivery to:
</div>
</div>
<div className={classes.deliveryTime}>
<div >
Choose time: Now
</div>
</div>
<HeaderCartButton onClick={props.onShowCart} />
</header>
<div className={classes['main-image']}>
<img src={mealsImg} />
</div>
</Fragment>
And my DeliveryButton:
const deliveryChoice = [{ name: 'Delivery' }, { name: 'PickUp' }]
const DeliveryButton = () => {
const [active, setActive] = useState(false);
return deliveryChoice.map((data, k) => (
<div
key={k}
className={`deliveryChoice ${active === k ?
classes.deliveryAction : ''}`}
onClick={() => setActive(k)}
>
{data.name}
</div>
));
};
And CSS for the Button:
.deliveryChoice {
}
.deliveryAction {
background-color: #ffffff;
border-color: #ffffff;
display: flex;
font-size: 13px;
justify-content: space-around;
width: 4rem;
height: 1.8rem;
cursor: pointer;
color: rgb(0, 0, 0);
align-items: center;
border-radius: 20px;
/* padding-left: 0.5rem; */
}
I'm trying to add and remove active class when I click on different panels that triggers a transition, so if I click on different panels it works, as in it triggers the transition and then it ends it when other panel gets clicked, but if I want to click on a panel that was already opened and closed it won't trigger it again on the first click adn that's not good UX.
I'm writing it in React and I am a beginner so maybe I'm not doing something right.
You can see the code below, I hope I gave all the right information.
componentDidMount() {
ReactDom.findDOMNode(this).addEventListener("transitionend", (e) => {
if (
e.propertyName.includes("flex") &&
e.target.classList.contains("open")
) {
e.target.classList.add("open-active");
}
});
ReactDom.findDOMNode(this).addEventListener("click", (e) => {
const elems = document.querySelector(".open-active");
if (elems !== null) {
elems.classList.remove("open-active", "open", "opac");
}
e.target.className = "open-active";
console.log(e);
});
}
render() {
const { index, top, bottom, image, open, onClick } = this.props;
const style = {
backgroundImage: `url(${image})`,
};
const openValue = open ? "open opac" : "";
return (
<div
className={`panel ${openValue}`}
style={style}
onClick={() => {
onClick(index);
}}
>
</div>
And the CSS
.panel > * {
margin: 0;
width: 100%;
transition: transform 0.5s;
flex: 1 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
.panel > *:first-child {
transform: translateY(-100%);
}
.panel.open-active > *:first-child {
transform: translateY(0);
}
.panel > *:last-child {
transform: translateY(100%);
}
.panel.open-active > *:last-child {
transform: translateY(0);
}
.panel p:nth-child(2) {
font-size: 4em;
}
.panel.open {
font-size: 16px;
flex: 5;
}
Hi you can follow this example:
import React, {useState} from "react";
import './styles/style.css'
export default function ShowHideExample() {
const [cssClass, setCssClass] = useState('hide');
return (
<div className="App">
<h2>Show or Hide div</h2>
<button onClick={() => {
(cssClass === 'hide')? setCssClass('show') : setCssClass('hide');
}}>Click me to show or hide the div
</button>
<div className={cssClass}>
<h1>This is dynamically shown</h1>
</div>
</div>
);
}
Here is the style.css file
.show{
display: block;
background: dodgerblue;
padding:20px;
}
.hide{
display: none;
}
I am running sample application in react-native. I have 2 buttons i.e., forward and backward. How to write the functionality for below mentioned 2 points.
1. When i click forward button then screenshot is shown below.
2. When i click backward button then screenshot is shown below.
I wrote this in React.js, you could port it
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
imageIndex: 2
}
this.setIndex = this.setIndex.bind(this)
}
setIndex(index) {
this.setState(Object.assign({}, this.state, {
imageIndex: index
}));
}
render() {
const { imageIndex } = this.state
let imgClasses = [
"ph bg-green",
"ph bg-blue",
"ph bg-green",
"ph bg-red"
]
return (
<div className="container">
{ imgClasses.map((img, i) =>
<div onClick={ () => this.setIndex(i) }
className={`${img}${ imageIndex == i ? " active" : ""}`}
style = {{
top: 60 * i,
left: 60 * i
}}>
</div>
) }
</div>
)
}
}
ReactDOM.render( <App /> , document.getElementById('app'));
.container {
position: relative;
}
.ph {
width: 100px;
height: 100px;
margin: 4px;
position: absolute;
border: 1px #fff solid
}
.ph.active {
z-index: 10;
}
.bg-green {
background: #8BC34A;
}
.bg-blue {
background: #03A9F4;
}
.bg-red {
background: #E91E63;
}
<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="app"></div>
I have created on modal using HTMl and CSS in react but, modal is not working as expected when deployed on environment as I have set z-index of modal to be higher
But there are other component on page who has also z-index and as those component appears before modal component in html page order.
Model doesn't appear on top as expected.
IS there any way in react, so that we can override all existing z-index and modal will work as expected.
I am providing CSS code for modal overlay and modal
.modal-overlay{
position: fixed;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
z-index: 5;
background-color: rgba(0,0,0,0.3);
overflow: scroll;
}
.modal{
display: flex;
flex-direction: column;
flex-basis: auto;
background-color: #fff;
max-width: 375px;
margin: 0px auto;
}
This method uses React Portal. U should have element with id="modal-root" in ur index html file. Every time u call a modal, the modal will come inside modal-root, Hence there will be no problem of z-index as u r rendering the Modal at the topmost div
Create a file Modal.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
const modalRoot = document.getElementById('modal-root');
class Modal extends Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount() {
modalRoot.appendChild(this.el);
console.log('Modal did mount');
}
componentWillUnmount() {
console.log('Modal will unmount');
modalRoot.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el,
);
}
}
export default Modal;
Create actual modal code
import React from 'react';
const ImageContainer = props => (
<div className="modal d-block full-screen-popup" tabIndex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h6 className="modal-title text-center bold">Title</h6>
<button type="button" className="close" onClick={props.onClose}>
<span className="icon-close" />
</button>
</div>
<div className="modal-body p-0">
<div className="imageBody text-center">
<img className="img-fluid" src={props.imgSrc} />
</div>
</div>
</div>
</div>
</div>
);
export default ImageContainer;
Its CSS should be
.full-screen-popup {
background-color: rgba(0,0,0,.62);
}
.d-block {
display: block!important;
}
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
display: none;
outline: 0;
}
Then in any js file, Import the Modal, and pass the actual modal component.
renderImageModal = () => {
if (this.state.showImageModal) {
return (
<Modal>
<ImageContainer onClose={this.handleImageModalClose} imgSrc={this.state.link} />
</Modal>);
}
return null;
}
handleModalOpenClick = () => {
this.setState({
showImageModal: true,
});
}
handleImageModalClose = () => {
this.setState({
showImageModal: false,
});
}
render(){
return(
<button onclick={this.handleModalOpenClick}>Open Modal</button>
{this.renderImageModal()})
}
The best way to create modal using ReactJS is to use Portals.
You can check the docs for portals here in the ReactJS docs or here the particular Modal example on codepen.
I have a some popup block or modal window as you like. And I want that it will close after I press on button. Button will be visible after checkboox will be true. Help me pls. May be I have to add something to css, or JS code is incorrect.
Code is below.
class ModalWindow extends React.Component {
constructor() {
super();
this.state = {
open: false,
checked: false
};
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
this.setState({
checked: !this.state.checked
})
}
hide() {
this.setState({
open: false,
});
}
show() {
this.setState({
open: true,
});
}
componentDidMount() {
this.show();
}
render() {
const buttonContent = this.state.checked ? <div className={s.showButton}>
<button onClick={() => this.hide()} className={s.closeBtn}>Confirm yes yes</button>
</div> : null;
return (
<div className={this.state.open ? 'show':'hide'}>
<div className={s.modal}>
<h2 className={s.modalText}>Some text in block</h2>
<label>I want to confirm</label>
<input type="checkbox" checked={this.state.checked} onChange={this.handleChange}/>
{buttonContent}
</div>
</div>
);
}
}
export default withStyles(s)(ModalWindow);
.modal {
background:#fff;
width: 350px;
height: 200px;
margin: 5% auto;
padding: 5px 20px;
position: relative;
border: 2px solid #0000ee;
}
.hide {
display:none
}
.modalText {
font-size: 18px;
color: #000000;
}
label {
margin:0 15px 0 0;
}
.closeBtn {
display: block;
position: absolute;
bottom: 5px;
width: 150px;
height:50px;
margin:0 0 0 100px;
outline: none;
color: #555;
border: none;
background: #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
With react you have another way to do hiding and showing of elements. You just render it or you don't.
So instead of setting the state inside the modal dialog to show or hide the modal dialog you should have a property outside of it which decides if this dialog is rendered. Your React App should look something like this:
class ComponentWithModalDialog extends React.Component {
render() {
const {showModal} = this.props;
if(showModal) {
return <ModalWindow />
}
else {
return <div>
other content
</div>
}
}
}