I'm doing an app, and i have a modal window, and i want to close the modal window when i click on the black background, and the way i did it works, the problem, is that i have white container in the center of the modal window, and i need to click stuff there, and when i do it, it closes the whole window, even though the onClick event is on the ModalHero that is the container that has the black background.
Just let me show you the code...
import React from "react";
import { ModalHero, ContainSettings } from "./ModalSettingsStyled";
const Modal = ({ setProfile }) => {
return (
<ModalHero onClick={() => setProfile(false)}>
<ContainSettings></ContainSettings>
</ModalHero>
);
};
export default Modal;
When i click on ContainSettings it closes the window, but i don't want that to happen.
Let me show you the css ( i'm using styled components )
import styles from "styled-components";
export const ModalHero = styles.section`
width: 100%;
height: 100vh;
background: rgba(0,0,0, .5);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
`;
export const ContainSettings = styles.div`
width: 45%;
height: 40vh;
border-radius: .5rem;
background: white;
`;
This is how it looks
What can i do so when i click the black background it will close the window, but when i click on the white container it won't
Thanks for your time !
You can put an Event.stopPropagation() onClick={(e) => e.stopPropagation()} on your ContainSettings
<ContainSettings onClick={(e) => e.stopPropagation()}>
Here a live example:
https://codesandbox.io/s/so-67143988-jmc0k?file=/src/Modal.js
Related
Im making a container with 3 cards. Each card (brown-ish color in example) has a header with title (sand-buiscuit color) and content (blue one).
What I want to acheive is when the cards are closed (click on header in example), the content (blue) is transitioning to height 0, and so the only visible part is header.
Also when the card is open I want to show the available content but only then, when there is enough available space in container (green).
When 3 cards are open, they have the same height (expand evenly in container), and remaining content (blue) is scrolled.
Is it possible to make?
I prepared a demo codesandbox
I made a small code example using styled-components (just because i like it), you can easily change it to regular react components with css, but this demonstrates the idea.
I created 3 boxes, each box has a default height(40px) and after clicking (which opens it) its height is set to: 100%.
Wrapping all of this boxes with flex container does the trick.
import styled from 'styled-components';
import React, { useState } from 'react';
const MyComponent = () => {
return (
<Container>
<BoxContainer height={100} number={1} />
<BoxContainer height={100} number={2} />
<BoxContainer number={3} />
</Container>
);
};
export default MyComponent;
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
width: 200px;
height: 400px;
overflow: hidden;
border: 1px solid black;
background-color: blue;
`;
const BoxContainer = ({ number, height = '100' }) => {
const [open, setOpen] = useState(false);
return (
<Box style={{ height: open ? '100%' : '40px' }} onClick={() => setOpen(!open)}>
Box: {number}
{open && <p>Content</p>}
</Box>
);
};
const Box = styled.div`
width: 100%;
overflow: scroll;
background-color: #00b8a2;
border: 1px solid red;
`;
sandbox example here: https://codesandbox.io/s/boxes-fill-container-evenly-when-opened-btlvb
I am trying to add functionality to close my modal by allowing a user to click anywhere outside of the modal box to trigger a close event. I can achieve this by using an onClick function on my modal background. However since the modal is itself a child of the background this function is being run when the actual modal is clicked as well.
This is the structure with the content omitted.
<ModalBackground modalDisplay={modalOpen} data-testid="modal-background" onClick={closeModal}>
<ModalContainer
role="dialog"
data-testid="modal"
modalDisplay={modalOpen}
ref={modalRef}
aria-labelledby={modalHeaderId}
aria-describedby={modalBodyId}
>
</ModalContainer>
</ModalBackground>
My styles are as follows
const ModalContainer = styled.div`
border: 1px solid ${basic[300]};
border-radius: 4px;
width: 29rem;
position: fixed;
background-color: ${basic[100]};
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
${(props) =>
props.modalDisplay ? `visibility: visible;` : "visibility: hidden"}
`;
const ModalBackground = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
${(props) =>
props.modalDisplay ? `visibility: visible;` : "visibility: hidden"}
`;
I can whip up a jsfiddle if desired but I am hoping there is a straightforward solution.
I found a way to solve this problem by adding this JS after the modal where I can test if the parent or child was clicked before changing the styles:
document.getElementById('ModalBackground').addEventListener("click", function(e) { if(e.target == this) closeModal('ModalBackground'); });
In you case, you would need to edit your closeModal function to have this test included.
I am designing a sidebar for my react project and I have the sidebar which is functioning correctly as expected. As you will see that I have also created a button that will basically open the sidebar from left to right and close it from right to left. But I was not able to make the button functional. Help would be appreciated. Thanks in advance.
[This is what I am getting in the output][1]
[1]: https://i.stack.imgur.com/qnOHz.png
This is the file in which I have the sidebar
import React, { Component } from 'react';
import {NavLink} from 'react-router-dom'
import './TableStyle.css'
class HomePage extends Component {
constructor(props){
super(props);
this.state = {
visible: false
}
}
toggleSidebar(){
this.setState.visible = !this.state.visible
}
render() {
return (
<div id = "sidebar">
<div class = "toggle-btn" onClick = {this.toggleSidebar()}>
<span></span>
<span></span>
<span></span>
<ul>
<NavLink to = "/" style={{color: "white"}}>Home</NavLink>
<p></p>
<NavLink to = "/data" style={{color: "white"}}>Show all entries</NavLink>
</ul>
</div>
</div>
This is TableStyle.css
* {
margin: 0px;
padding: 0px;
font-family: sans-serif;
}
#sidebar {
position: fixed;
width: 200px;
height: 100%;
background: rgb(58, 68, 77);
}
/* #sidebar.active{
left: 0px;
} */
#sidebar ul{
color: rgb(240, 243, 245);
list-style: none;
padding: 15px 10px;
border-bottom: 1px solid rgba(100,100,100,0.3);
transition: all 500ms linear;
}
#sidebar.active{
left: 0px;
}
#sidebar.toggle-btn {
position: absolute;
left: 230px;
top: 30px;
}
#sidebar .toggle-btn span {
display: block;
width: 30px;
height: 3px;
background: white;
margin: 5px 0px;
}
Try using the React Hook useState instead, you don't need an internal state in this case, here is what I would've done:
import React, { Component, useState } from 'react';
import { NavLink } from 'react-router-dom'
import './TableStyle.css'
class HomePage extends Component {
const [visible, setIsVisible] = useState(false);
render() {
return (
<div id="sidebar">
<div class="toggle-btn" onClick={setIsVisible(!visible)}>
<span></span>
<span></span>
<span></span>
<ul>
<NavLink to = "/" style={{color: "white"}}>Home</NavLink>
<p></p>
<NavLink to = "/data" style={{color: "white"}}>Show all entries</NavLink>
</ul>
</div>
</div>
In this way, the button will toggle the visible value from false to true and viceversa. This happens on
<div class="toggle-btn" onClick={setIsVisible(!visible)}>
Where onClick toggles the visible value.
And then use the visible value for example in the following:
<div id="sidebar" class={visible ? "open-sidebar-class" : "close-sidebar-class"}>
The "open-sidebar-class" : "close-sidebar-class" is where you would put the class you want to trigger in the sidebar when the menu opens or closes.
Try then doing this example in TableStyle.css to see if it works, if it does, then just type in the css attributes you want instead to trigger in the sidebar whenever you click the button.
...
.open-sidebar-class {
background-color:green;
}
.close-sidebar-class {
background-color:red;
}
...
Your problem is re-rendering HomePage each time you click on the button, so it resets visibility to false as it executes the component script again. I can't tell why you are re-rendering from the snippet (and please reformat to usual indentation and I couldn't get it to run in a sandbox bc unclosed brackets), but you can work around by passing the sidebar visibility as a prop to the HomePage component.
I'm trying to show the icons in the aside. Below is the styled-components code and the way in which its logic was organized but the icons are not being shown by default. a curious behavior is that if I write anything directly next to the icon component it start to display it but in different sizes.
MenuBar Component
index.js
import React from 'react';
import { Home } from '#styled-icons/material-rounded/Home'
import { Search } from '#styled-icons/icomoon/Search'
import { Lightbulb } from '#styled-icons/fa-solid/Lightbulb'
import { Grid } from '#styled-icons/boxicons-solid/Grid'
import { ToTop } from '#styled-icons/boxicons-solid/ToTop'
import * as S from './styled'
const MenuBar = () => (
<S.MenuBarWrapper>
<S.MenuBarGroup>
<S.MenuBarLink to="/" title="Back to Home">
<S.MenuBarItem><Home /></S.MenuBarItem>
</S.MenuBarLink>
<S.MenuBarLink to="/search/" title="Search">
<S.MenuBarItem><Search /></S.MenuBarItem>
</S.MenuBarLink>
</S.MenuBarGroup>
<S.MenuBarGroup>
<S.MenuBarItem title="Change Theme"><Lightbulb /></S.MenuBarItem>
<S.MenuBarItem title="Change Visualization"><Grid /></S.MenuBarItem>
<S.MenuBarItem title="Go to Top"><ToTop /></S.MenuBarItem>
</S.MenuBarGroup>
</S.MenuBarWrapper>
)
export default MenuBar
styled.js
import styled from 'styled-components'
import { Link } from 'gatsby'
export const MenuBarWrapper = styled.aside`
align-items: center;
background: #192734;
border-left: 1px solid #38444d;
display: flex;
flex-direction: column;
height: 100vh;
justify-content: space-between;
padding: 0.8rem 0;
position: fixed;
right: 0;
width: 3.75rem;
`
export const MenuBarGroup = styled.div`
display: flex;
flex-direction: column;
`
export const MenuBarLink = styled (Link)`
display: block;
`
export const MenuBarItem = styled.span`
display:block;
color: #8899a6;
cursor: pointer;
height: 3rem;
padding: 1.1rem;
`
MenuBar aside without showing icons
When i type some text near the component:
MenuBar aside showing icons
I recommend you to use material icon library. (Not material ui icon) . Very big library and has props for changing size by em size and fix your problem.
developers!
I have tried to create a simple Modal Window with React.
But my window still not appeared!
So, my code have two parts: JS-part and CSS-part.
I used "Modal" keyword, constructor and render(). All my code was written in CodePen area, so I'm able to see the result. But still something missing. What is it?
It will be mobile application. So, should I use keyword "Native" somewhere?
import "./modal.scss";
class Modal extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps) {
return !I.is(this.props.data, nextProps.data);
}
render() {
let isOpen = this.props.data.get("isOpen");
return (
<div className={`flex middle center modal ${isOpen ? "open" : ""}`}>
{isOpen ?
(<div className={`row modal-content ${this.props.size || ""}`}>
<div className="col-12 middle modal-title">{this.props.title}</div>
<div className="col-12 modal-body">
{this.props.body}
</div>
<div className="col-12 middle modal-footer">{this.props.footer}</div>
</div>) : null
}
</div>);
}
}
export default Modal;
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10000;
padding: 2rem;
background-color: rgba(0, 0, 0, 0.55);
.modal-content {
background-color: white;
max-height: 80%;
height: 80%;
.modal-title {
padding: 0 2.25rem;
height: 5rem;
max-height: 5rem;
text-transform: uppercase;
font-size: 1.8rem;
}
.modal-body {
height: calc(100% - 16rem);
overflow-y: scroll;
padding: 0 2rem;
}
.modal-footer {
height: 5rem;
max-height: 5rem;
padding: 0 2.25rem;
}
}
}
See also a fragment from CodePen:
enter image description here
import Modal from "react-native-modal";
render () {
return (
<View>
<Modal isVisible={true}>
<View style={{ flex: 1 }}>
<Text>I am the modal content!</Text>
</View>
</Modal>
</View>
)
}
See also https://github.com/react-native-community/react-native-modal
I think what you're trying to do is make a mobile application. The best way to do that would be to use React React Native instead of React
Check this out:
https://github.com/react-community/create-react-native-app
Once you're started showing a modal on a screen is quite simple.
https://facebook.github.io/react-native/docs/modal#docsNav
If this is your first time, it would be best to follow the getting started guide on React Native's website. Its helpful. There are no divs, but inLine styling can still be used.
https://facebook.github.io/react-native/docs/getting-started
Hope this helps