React - Modal expands div in footer div not on main screen - reactjs

New to coding, trying to get a modal to work. It is not opening the way I expected it to.
The component is currently loaded within the footer div of my site. And when the button is toggled it simply hides or shows a div within the footer. I want it to appear in the centre of the webpage as a modal.
import React, {useState} from 'react';
import './policy.css'
export default function Policy() {
const [modal, setModal] = useState(false);
const toggleModal = () => {
setModal(!modal);
};
if(modal) {
document.body.classList.add('active-modal')
} else {
document.body.classList.remove('active-modal')
}
return (
<>
<div>
<button onClick={toggleModal} className='btn-modal'>
<p>Privacy Policy</p>
</button>
</div>
{modal && (
<div className="modal">
<div onClick={toggleModal} className="overlay"></div>
<div className="modal-content">
<h2>Privacy Policy</h2>
<p>This is the privacy policy</p>
<button className='close-modal' onClick={toggleModal}>Close</button>
</div>
</div>
)}
</>
);
}

The simplest way to achieve a modal effect is to use some CSS.
You could try a very crude style like (from MUI Modal docs):
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "lightgrey",
border: "2px solid #000",
boxShadow: 24,
padding: 4,
};
Then apply it to your modal:
<div className="modal" style={style}>

Related

bottom container needs to come above keyboard when we click on any input field in react js

Here is my bottom container now I want that whenever the user clicks on an input field this container goes above the keyboard. I have the user scrollIntoView to do this but it shifted the entire page upwards. I want that only the container goes above the keyboard. I want to do this on website.
import React, {useRef} from 'react'
function App() {
const ref = useRef(false);
return (
<div style = {{position: 'fixed', left: '0px', bottom:'0px', backgroundColor: 'red', overflow:'auto', height:'50%'}} >
<div>
<div> Enter your name</div>
<input
type ='text'
onChange ={()=>
ref?.current?.scrollIntoView()
}
/>
<div style ={{position: 'fixed', left: '0px', bottom:'0px' , backgroundColor: 'green', height:'5%'}} ref={ref} >
our Bottom container
</div>
</div>
</div>
);
}
export default App;

Shoiwng menu while hovering on table row in reactjs

I am stuck in a scenario and scenario is that I have a table of product and I want to show menu of sub product's whenever I hover on a particular row-but not able to do it-Anyone please help-
You can create a state variable with useState and use it to show the menu in sub-product.
For example,
import React, { useState } from "react";
export default function ShowLabelHover() {
const [visibleMenu, setVisibleMenu] = useState({ display: "none" });
const style = {
border: "1px solid gray",
width: 200,
height: 50,
padding: 10,
margin: 100
};
return (
<div className="App">
<div
style={style}
onMouseEnter={(e) => {
setVisibleMenu({ display: "block" });
}}
onMouseLeave={(e) => {
setVisibleMenu({ display: "none" });
}}
>
<label style={visibleMenu}>Here is some text!</label>
</div>
</div>
);
}

How can i hover in React using useState

I wanna toggle a class when hovering on a Container by changing the opacity from 0 to 1, I've used onmouseEnter and onMouseLeave Event to toggle the class, but when I console hover state I see that is changing from true to false when I hover but the class "Show" is not changing.
What do you think ?
<--Components-->
import React,{useState} from 'react';
import './MyWork.css';
import {Visibility, GitHub } from "#material-ui/icons";
const SingleProject = ({src, title}) => {
const [hover, isHover] = useState(false);
const showIcons = isHover ? "Show" : "";
return (
<div className="card-container" onMouseEnter={()=> isHover(true)} onMouseLeave={()=> isHover(false)}>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${showIcons}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
<--- Css--->
.card-container {
height: 314px;
width: 500px;
cursor: pointer;
position : relative;
}
.Info {
position: absolute;
height: 100%;
width: 100%;
top:0;
left:0;
display:flex;
justify-content:center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.Info.Show {
opacity: 1;
}
When assigning the value to showIcons, you need to use hover instead of isHover which is the setter function for that state.
Additionally, I recommend naming the setter function setHover to avoid confusion and be more semantic. You can also add conditional Show class like this, which is more concise:
iconst SingleProject = ({src, title}) => {
const [hover, setHover] = useState(false);
return (
<div
className="card-container"
onMouseEnter={()=> setHover(true)}
onMouseLeave={()=> setHover(false)}
>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${hover ? "Show" : ""}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
You are using the setter instead of the state itself on your condition. Change isHover with hover like below:
const showIcons = hover ? "Show" : "";

how can you detect if the position clicked is correct?

I'm trying to build a find waldo and to do that, I need to assign a position in where the character is located. To do this, I've thought of assigning the position of the X and Y with e.pageX and e.PageY, the problem is that the image is very big so yo need to scroll to see all the image.
So the position changes each time I scroll. I've been thinking a way of checking if the character clicked is correct but I can't seem to find a way to do that... If anyone could help me please I woild really appreciate it.
Here is the code:
import React, {useState} from 'react'
import mainImage from '../img/marioBrosMain.jpg'
import '../main.css'
import Box from '../pages/box.js'
function Main() {
const [style, setStyle] = useState();
const [hidden, setHidden] = useState(true)
let Characters;
const imageClick = (x, y) => {
const newStyle = {
position: "absolute",
zIndex: 2,
borderRadius: "2px solid red",
border: "4px solid red",
height: "50px",
paddingLeft: "10px",
left: `${x}px`,
top: `${y}px`
}
setHidden(false)
return newStyle
}
if (!hidden) {
Characters = (
<>
<div className="hello">
<div>
<button>Star</button>
</div>
<div>
<button>Mario</button>
</div>
<div>
<button>Yoshi</button>
</div>
</div>
</>
);
}
return (
<div id="frame">
<div id="mainImage" style = {style}>
{Characters}
</div>
<img src={mainImage} className="marioBros____image" onClick={(e) => {setStyle(imageClick(e.pageX, e.pageY)); console.log(e.pageX)}} />
</div>
)
}
export default Main

Why my react-bootstrap Accordion is not working on small devices?

I have a simple Accordion in one of my components.
function CustomToggle({eventKey}) {
const [children, setChildren] = useState('Mais filtros 🠗')
const decoratedOnClick = useAccordionToggle(eventKey, () =>
setChildren(children === 'Mais filtros 🠗' ? 'Menos filtros 🠕' : 'Mais filtros 🠗')
)
return (
<div className="text-center">
<div className="tag align-center" onClick={decoratedOnClick}>
{children}
</div>
</div>
)
}
...
<Accordion>
<CustomToggle eventKey="0" />
<Accordion.Collapse eventKey="0">
<QueryForm
baseEndpoint={this.props.baseEndpoint}
tagsInitialValues={this.state.searchParams.tags}
textInitialValue={this.state.searchParams.description}
setSearchParams={this.setSearchParams}
/>
</Accordion.Collapse>
</Accordion>
It works perfectly on larger breakpoints, but, for smaller devices, the QueryForm shows in the opposite direction and stays on top of the page's content.
Check the sandbox: https://codesandbox.io/s/0y8cm
(click on 'Mais filtros' to trigger the accordion and see the problematic breakpoint when the navbar toggle appears)
What am I doing wrong?
The default of Accordion react component it doesn't use absolute position for define the position of the accordion content. I'm not sure how you customize position: absolute. Then the first way if you consider don't need to use the position: absolute. You can remove it at:
collapsing {
position: absolute !important;
z-index: 3;
width: 100%;
top: 75px;
}
.collapse.show {
display: block;
position: absolute;
z-index: 3;
width: 100%;
top: 75px;
}
The second way, if you intend to do something with position: absolute in mobile, you should pick a container of the form and add position: relative then your form will render base on the position of that container.
<div style={{ position: "relative" }}>
<Accordion>
<CustomToggle eventKey="0" />
<Accordion.Collapse eventKey="0">
<QueryForm
baseEndpoint={this.props.baseEndpoint}
tagsInitialValues={this.state.searchParams.tags}
textInitialValue={this.state.searchParams.description}
setSearchParams={this.setSearchParams}
/>
</Accordion.Collapse>
</Accordion>
</div>
There is some issue in your Navbar.css. Not sure why you use position to be absolute. I commented out those, and it works now.
.collapsing {
/* position: absolute !important; */
/* z-index: 3; */
width: 100%;
/* top: 75px; */
}
.collapse.show {
display: block;
/* position: absolute; */
/* z-index: 3; */
width: 100%;
/* top: 75px; */
}
https://codesandbox.io/s/relaxed-dust-2yimw?file=/src/components/common/Navbar.css:736-984
Do you run the Accordian on small device?
here is my code. I hope it's will help you.
import React, {useState} from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Accordion from '#material-ui/core/Accordion';
import AccordionSummary from '#material-ui/core/AccordionSummary';
import AccordionDetails from '#material-ui/core/AccordionDetails';
import Typography from '#material-ui/core/Typography';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import PropTypes from 'prop-types';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
heading: {
fontSize: theme.typography.pxToRem(1),
fontWeight: theme.typography.fontWeightRegular,
},
}));
const Accordian = ({
title,
data,
onclick,
shownName
}) =>{
const classes = useStyles();
let content;
const [subtitle, setSubtitle] = useState("");
const [expand, setExpand] = useState(true);
const liClick = (e) => {
setSubtitle(e.target.getAttribute('data'));
onclick(e);
setExpand(!expand);
}
const clickExpand = (e) =>{
setExpand(!expand);
}
content = data.map((value, key)=>{
return (
<li
className="list-group-item"
key={data[key][shownName]+"_"+key}
name={data[key][shownName]}
data={data[key][shownName]}
onClick={liClick}
>
{data[key].mark?(<img src={data[key].mark} align="left" className="mark_sign" alt="mark"/>):''}
{data[key][shownName]}
<i className="fa fa-angle-right" align="right"/>
</li>
);
});
return (
<div className={classes.root}>
<div className="container">
<Accordion
defaultExpanded={true}
expanded={expand}
style={{
borderBottom:'1px',
borderBottomColor:'white',
borderBottomStyle:'solid'
}}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography
className={classes.heading}
style={{fontSize:'14px', textAlign:'left'}}
onClick={clickExpand}
>
<span className="Name" style={{ float:'left'}}>{title}{' '}</span>
<span style={{fontSize:'18px', color:'#007bff',width:'100%',top:'10px',left:'0', textAlign:'center', position:'absolute'}}>{' '}{subtitle}</span>
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
<span
className="list-group list-group-flush"
align="center"
>
{content}
</span>
</Typography>
</AccordionDetails>
</Accordion>
</div>
</div>
);
}
Accordian.propTypes = {
shownName: PropTypes.string.isRequired,
data: PropTypes.array.isRequired,
onclick: PropTypes.func.isRequired
};
export default Accordian;
Yesterday I fix the this problem. So I share this code.
Please check agian.

Resources