Add Modal Component To Card component in React - reactjs

I have created two different components, one for a card and one for a modal. What I would like to do now is to connect them together so that when I click the button on the card component, I would like the modal to open up on the screen. I have tried all that I can but can't seem to get it right.
Here is the card compenent:
import img from './112803.jpg';
import GitHub from './github-white.png';
import Website from './website-white.png';
import ModalButton from './ModalButton.js'
function Card(props) {
return (
<div className="card">
<div className="cardBody">
<div className="imageOverlay">
<img className="imageOverlayImg" src={img} alt="landscape" />
<div className="imageOverlayDescription">
<a href={props.gitHub} target="_blank" rel="noopener noreferrer">
<img src={GitHub} alt="GitHub Icon" />
</a>
<a href={props.liveSite} target="_blank" rel="noopener noreferrer">
<img src={Website} alt="liveSite Icon" />
</a>
</div>
</div>
<h2 className="cardTitle">{props.heading}</h2>
<p className="cardDescription">{props.description}</p>
</div>
<button className="cardButton">More Information</button>
</div>
);
}
export default Card;
And here is the modal component:
const Modal =(props)=>{
return(
<>
{props.showModal ? (
<div className="background">
<div className='modalWrapper' showModal={props.showModal}>
<img clasName="modalImg" src={require('./deals.jpg').default} alt="A Landscape" width="100%" height="100%"/>
<div className="modalContent">
<h1>{props.heading}</h1>
<p>{props.description}</p>
<p>{props.madeBy}</p>
<div className="buttonLayout">
<button className="innerModalButton">View Code</button>
<button className="innerModalButton">Live Site</button>
</div>
</div>
<button className="closeModalButton" aria-label="Close modal" onClick={()=>
props.setShowModal(prev => !prev)}>Close</button>
</div>
</div>
) : null}
</>
);
}
And here is some of the logic that the modal needs in order to pop up
const [showModal,setShowModal] = useState(false);
const openModal = () =>{
setShowModal(prev => !prev)
I am still a bit of a beginner and I'm not too sure how to get the project done. Any help would be greatly appreciated. Thank you.

Just add a state in Card pass pass it into Modal:
const [showModal,setShowModal] = useState(false);
...
<Modal
showModal={showModal}
setShowModal={setShowModal}
//...another props to display content
/>

From my understanding of what is going on, it looks like your modal button isn't doing anything. I would suggest you add an onClick method to it.
<button className="cardButton" onClick={()=> setShowModal(true)}> More Information</button>
Also like the answer above, pass the state from the card to the Modal
That could do it.
Let me know if it helped.

Related

the voiceover does not automatically read the "aria-labelledby" contained in my modal when it is displayed on the screen

I am trying to make a modal with accessibility. Basically, the modal gets a child and this child will be the content of the modal:
<div
id="modal"
role="dialog"
aria-labelledby="modal-label"
aria-describedby="modal-desc"
tabIndex={0}
className="modal"
>
{*/ {children} */}
<div className="flexContainer">
<div id="modal-desc">
<div>hey</div>
<div>
<div>This is the description</div>
<div>I am a button</div>
</div>
</div>
<div>
<div id="modal-label">This is the title</div>
</div>
</div>
</div>
When the modal opens, the voiceover reads the texts as it is in the gif, but I don't know why it doesn't read the aria-labelledby. My idea is that I can pass any child to my modal and the voiceover reads everything that is contained in aria-labelledby and in aria-describedby.
how can I make the voiceover read "aria-labelledby" automatically?
this is my live code
const [openModal, setOpenModal] = useState(false);
const Modal = ({ children }) => {
useEffect(() => {
document.querySelector("#modal")?.focus();
}, []);
return (
<div
id="modal"
role="dialog"
aria-labelledby="modal-label"
aria-describedby="modal-desc"
tabIndex={0}
className="modal"
>
{children}
</div>
);
};
const ModalContent = () => {
return (
<div className="flexContainer">
<div id="modal-desc">
<div>hey</div>
<div>
<div>This is the description</div>
<div>I am a button</div>
</div>
</div>
<div>
<div id="modal-label">This is the title</div>
</div>
</div>
);
};
return (
<>
<button
aria-hidden="true"
onClick={() => {
setOpenModal(true);
}}
>
open modal
</button>
{openModal && (
<Modal>
<ModalContent />
</Modal>
)}
</>
);
There's nothing wrong with the way you're using aria-labelledby, however it may be that the content of your modal (#modal-desc) is being added after the modal container (#modal), so the #modal-label ID is not immediately available in the DOM when the modal first appears. Sometimes this can cause problems for screen readers when content (particularly content that is linked to aria-labelledby or aria-describedby) is added dynamically to the DOM.
A better way to ensure that your modal label is announced is to include it in the aria-label attribute in your dialog container, e.g.:
<div id="modal" role="dialog" aria-label="This is the title" aria-describedby="modal-desc" tabIndex="0" class="modal">
As an aside, you have aria-hidden="true" on your "open modal" button. You should remove this because it hides the button from screen readers.

related to React js (props) css inline style

I want to more than one cards in different background color what i do ?
eg:
import React from "react";
import reactDom from "react-dom";
const BgColor=(props)=>{
return(
<>
<div className="main_div">
<div className="cards" >
<div className="card-side front" >
<div><span>C</span>opy<span>C</span>ode</div>
</div>
<div className="card-side back">
<div><i className="fas fa-copy fs-3" /><br />{props.code}</div>
</div>
</div>
</div>
</>
)
}
export default BgColor;
by pass value in app.js
and so on.....
please help me how to pass value inside the app.js
with this example is hard to to help you. Indeed, we don't know what your props object contains.
Let's assume your props contains
{
name: "toto",
code: "myCode"
}
In order to change background color based on props, you have multiples choices.
You can use dynamics classNames based on your props:
const BgColor=(props)=>{
return(
<>
<div className="main_div">
<div className="cards" >
<div className={`${props.name} card-side front`} >
<div><span>C</span>opy<span>C</span>ode</div>
</div>
<div className="card-side back">
<div><i className="fas fa-copy fs-3" /><br />{props.code}</div>
</div>
</div>
</div>
</>
)
}
See the <div className={${props.name} card-side front} > line. Go to css or scss file for this component and add a class selector inside of it.
In our example, it will be
.toto {
background: red
}
The second option is to inject directly the css inside your div.
Let's assume you send the desired background color inside your propos:
{
backgroundColor: "red",
code: "myCode"
}
In order to that, you have to do this
const BgColor=(props)=>{
return(
<>
<div className="main_div">
<div className="cards" >
<div className="card-side front" style={{backgroundColor: props.backgroundColor}}>
<div><span>C</span>opy<span>C</span>ode</div>
</div>
<div className="card-side back">
<div><i className="fas fa-copy fs-3" /><br />{props.code}</div>
</div>
</div>
</div>
</>
)
}
If you want to know more about css in React, you can check:
https://reactjs.org/docs/faq-styling.html, React.js inline style best practices, https://create-react-app.dev/docs/adding-a-stylesheet/
UPDATE
You can send an array of colors like <BgColor colors={["red", "blue"]} /> then in your BgColor component, you can map on your props like:
const BgColor=({colors})=>{
return (
<div className="main_div">
<div className="cards">
{colors.map((color, index) => {
return (
<div
className="card-side front"
style={{ backgroundColor: color }}
key={index}
>
<div>
<span>C</span>opy<span>C</span>ode
</div>
</div>
);
})}
</div>
</div>
);
}

React Js Multiple Modal

Hi i'm trying to learn react and i was tryign to make multiple modal but the same desgine and everything but different content inside it how?
import './Works.css';
import React, { useState } from 'react'
import Modal from '../Modal/Modal'
function Works(props){
const [isOpen, setIsOpen] = useState(false)
return(
<div>
<div className={props.NameClass}>
<h1>{props.icon}</h1>
<h1>{props.title}</h1>
<p >simple pargraph</p>
<button className="button_more" onClick={() => setIsOpen(true)}><i className="fas fa-caret-right"></i></button>
</div>
<Modal open={isOpen} title="hi" onClose={() => setIsOpen(false)}>
</Modal>
</div>
)
}
export default Works
and if you look at <Modal open={isOpen} title="here i wanna different title" onClose={() => setIsOpen(false)}>
and here the App.js calling the file on top multiple times but i wanna for example if someone click on the second project it change the title to for example "hi you're in the second modal!"
<div class="Div-Projects">
<Works NameClass="First_Project" icon="💳" title="first" />
<Works NameClass="Second_Project" icon="🎓" title="second" />
<Works NameClass="Third_Project" icon="👩🏻‍💻" title="third" />
</div>
and here the modal code!
import './Modal.css'
function Modal({open , title, onClose}){
if(!open) return null
return(
<div className="popup">
<div className="content">
<h1>{title}</h1>
<div className="p">
<p>login system for students attendees with an arduino and python it shows how fast and stable for doing the job.login system for students attendees with an arduino and python it shows how fast and stable for doing the job.login system for students attendees with an arduino and python it shows how fast and stable for doing the job.</p>
</div>
<div className="buttons">
<button className="dismiss" onClick={onClose}>Dismiss!</button>
<button className="github" onClick={() => window.open( 'https://github.com/Majiedo/Login_System')}><i className="fab fa-github"></i></button>
<button className="code"><i className="fas fa-code"></i></button>
</div>
</div>
</div>
)
}
export default Modal
Why don't you pass Works props to Modal component? Like this:
function Works(props){
const [isOpen, setIsOpen] = useState(false)
return(
<div>
<div className={props.NameClass}>
<h1>{props.icon}</h1>
<h1>{props.title}</h1>
<p >simple pargraph</p>
<button className="button_more" onClick={() => setIsOpen(true)}><i className="fas fa-caret-right"></i></button>
</div>
<Modal open={isOpen} title={`hi you're in the ${props.title} modal!`} onClose={() => setIsOpen(false)}/>
</div>
)
}
You need to pass in title {props.title}
change it:
<Modal open={isOpen} title="hi" onClose={() => setIsOpen(false)}>
</Modal>
On this:
<Modal open={isOpen} title={`hi you're in the ${props.title}`} onClose={() => setIsOpen(false)}/>

align items next to each using bootstrap

i have this images
i have loaded them from api and i created another component that will print them. my problem is that i have about 50 images and i want each 3 to be on one row with the title under them and the next one will hold 3 new but i don't really know bootstrap and can't seem to solve this problem.
postItem.js
import React from 'react';
function PostItem ({key,src,thumbnailUrl,onClick,title}) {
return (
<div>
<div key={key}>
<img src={src} thumbnailUrl={thumbnailUrl} onClick={onClick}></img>
<div>{title}</div>
</div>
</div>
)}
export default PostItem;
post.js:
<div><h3>Posts</h3></div>
<div>
<div>{newPhotosLocally.map(picture =>
<PostItem
key={picture.id}
src={picture.thumbnailUrl}
thumbnailUrl={picture.thumbnailUrl}
onClick={() => showPicture(picture.url,picture.id)}
title={picture.title}/>
// <div key={picture.id}>
// <img src={picture.thumbnailUrl} thumbnailUrl={picture.thumbnailUrl} onClick={() => showPicture(picture.url,picture.id)}></img>
// <div>{picture.title}</div>
// </div>
)}</div>
</div>
As you mentioned that you have already included bootstrap in your project, you can use col class to specify the width for each image.
You can read about grid system of bootstrap here: GRID SYSTEM
Your postItem.js file should look like this:
import React from 'react';
function PostItem ({key,src,thumbnailUrl,onClick,title}) {
return (
<div class="container-fluid text-center">
<div class="row">
<div class="col-4" key={key}>
<img src={src} thumbnailUrl={thumbnailUrl} onClick={onClick}></img>
<div>{title}</div>
</div>
<div class="col-4" key={key}>
<img src={src} thumbnailUrl={thumbnailUrl} onClick={onClick}></img>
<div>{title}</div>
</div>
<div class="col-4" key={key}>
<img src={src} thumbnailUrl={thumbnailUrl} onClick={onClick}></img>
<div>{title}</div>
</div>
</div>
</div>
)}

How to show button while hover over box using react?

I am working on a project, it is an online shop in react.
I would like to make "Quick view" and "Add to cart" buttons visible only while hovering over the product box they're in. Also, they should be clickable. Code of the ProductBox below`
const ProductBox = ({ name, price, promo, stars }) => (
<div className={styles.root}>
<div className={styles.photo}>
{promo && <div className={styles.sale}>{promo}</div>}
<div className={styles.buttons}>
<Button variant='small'>Quick View</Button>
<Button variant='small'>
<FontAwesomeIcon icon={faShoppingBasket}></FontAwesomeIcon> ADD TO CART
</Button>
</div>
</div>
<div className={styles.content}>
<h5>{name}</h5>
<div className={styles.stars}>
{[1, 2, 3, 4, 5].map(i => (
<a key={i} href='#'>
{i <= stars ? (
<FontAwesomeIcon icon={faStar}>{i} stars</FontAwesomeIcon>
) : (
<FontAwesomeIcon icon={farStar}>{i} stars</FontAwesomeIcon>
)}
</a>
))}
</div>
</div>
<div className={styles.line}></div>
<div className={styles.actions}>
<div className={styles.outlines}>
<Button variant='outline'>
<FontAwesomeIcon icon={faHeart}>Favorite</FontAwesomeIcon>
</Button>
<Button variant='outline'>
<FontAwesomeIcon icon={faExchangeAlt}>Add to compare</FontAwesomeIcon>
</Button>
</div>
<div className={styles.price}>
<Button noHover variant='small'>
$ {price}
</Button>
</div>
</div>
</div>
);
Please follow the below code:
import React, {useState} from "react";
export default function ShowButtonHover() {
const [style, setStyle] = useState({display: 'none'});
return (
<div className="App">
<h2>Hidden Button in the box. Move mouse in the box</h2>
<div style={{border: '1px solid gray', width: 300, height: 300, padding: 10, margin: 100}}
onMouseEnter={e => {
setStyle({display: 'block'});
}}
onMouseLeave={e => {
setStyle({display: 'none'})
}}
>
<button style={style}>Click</button>
</div>
</div>
);
}
EDIT: made a codesandbox to make it easier https://codesandbox.io/s/stckovw-hideshow-hs3mh
A way to achieve this can be through these steps:
Add onMouseEnter and onMouseLeave handlers to the component you want to trigger the rendering of the buttons, so ProductBox in your case
Give the default class of your buttons a property of display = none
Switch the display to block for example when the event handlers are triggered.
If you are keeping a stateless component for your implementation:
const [display, setDisplay]=useState('notdisplayed');, with notdisplayed the default class with display=none
<div className={display}> on the components you want to hide/show
Call setDisplay in the onMouseEnter and onMouseLeave definition

Resources