React, CSS: How to make corresponding modal window open for each card - reactjs

Let me explain the situation. Currently I am doing a project to practice SCSS and React. It is a website dedicated to soccer team. The problem is that I am creating a custom modal window using CSS and HTML. What I want is that whenever I click the button "see pics" a modal window related to this card should open, while in my case all modal windows open at once.
All modal windows open at once stacked one on each other. Like that.
There are four modal windows like that overall, but only the top modal shows.
The HTML structure of these modal windows is the following:
They have got the same classes and ids.
In React part I have a component called PopUp, which gets information from db.json as props.
import React from 'react';
import Button from './button-round-dark';
const generateAdditionalInfo = ({info}) => {
if (info) {
return info.map((item) => {
const addInfo = item.additionalInfo;
console.log(addInfo);
return (
<div className="popup" id="popup">
<div className="popup__content" key={addInfo.id}>
<div className="popup__left">
<img className="popup__img" src={`../../${process.env.PUBLIC_URL}/images/additionalInfoPics/${addInfo.images[0]}`}/>
<img className="popup__img" src={`../../${process.env.PUBLIC_URL}/images/additionalInfoPics/${addInfo.images[1]}`}/>
</div>
<div className="popup__right">
x
<h2 className="heading-secondary u-margin-bottom-small">{addInfo.title}</h2>
<p className="popup__description">{addInfo.description}</p>
</div>
</div>
</div>
)
})
}
}
const PopUp = (props) => {
return (
<div>
{generateAdditionalInfo(props)}
</div>
)
}
export default PopUp;
db.json
"legendaryTeam":[
{
"id":"p1",
"name": "buffon",
"image":"buffon.jpg",
"years":"2001-2018",
"number":"18",
"position":"goalkeeper",
"physicalFeatures":{
"weight":"86",
"height":"194",
"speed":"7",
"power":"250"
},
"additionalInfo":{
"id":"1",
"images":["buffon_1.jpg","buffon_2.jpg"],
"title":"Buffon title",
"description":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Etiam dignissim diam quis enim lobortis scelerisque. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Lorem sed risus ultricies tristique nulla aliquet enim. Ultrices in iaculis nunc sed augue lacus viverra vitae congue."
}
},
{
"id":"p2",
"name": "Ravanelli",
"image":"ravanelli.jpg",
"years":"1992-1996",
"number":"10",
"position":"forward",
"physicalFeatures":{
"weight":"75",
"height":"176",
"speed":"9",
"power":"300"
},
"additionalInfo":{
"id":"2",
"images":["ravanelli_1.jpg","ravanelli_2.jpg"],
"title":"Ravanelli title",
"description":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Etiam dignissim diam quis enim lobortis scelerisque. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Lorem sed risus ultricies tristique nulla aliquet enim. Ultrices in iaculis nunc sed augue lacus viverra vitae congue."
}
}
Please pay attention to additionalInfo object, it is where information goes to PopUp component.
Custom CSS code for modal window looks like this.
.popup {
height: 100vh;
width:100%;
position:fixed;
top:0;
left:0;
background-color: rgba($color-black,0.8);
z-index:99999;
opacity: 0;
visibility: hidden;
transition:all .3s;
&:target {
opacity: 1;
visibility: visible;
}
&__content {
#include centrify;
width:75%;
background-color: $color-white;
box-shadow: 0 2rem 4rem rgba($color-black, .2);
border-radius: 3px;
display: table;
overflow: hidden;
}
&__left {
width:33.33333333%;
display: table-cell;
}
&__right {
width:66.666666666%;
display: table-cell;
vertical-align: middle;
padding: 3rem 5rem;
}
&__img {
display: block;
width:100%;
}
&__description {
font-size: 1.4rem;
margin-bottom: 4rem;
}
}
Modal window open with help of target selector. Now I am scratching head over how to make implement what I want. Please help me out. Do you have any ideas?
By the way other modal windows look like this. But they are lower in stack so they are not shown.
If you want to tinker with my project click here
To run react see picture below
To run db.json you need to install it globally
$ npm install -g json-server
And then run it, see pic below
To run SCSS see pic below

Your problem is not in your description, you bind the ButtonRoundDark to all of the modal. You need to add onClick event to your 'see pics' button. After click, fetch the data, show the modal.

Related

React store data in a variable from API

I am trying to store some of my data in a const variable. Like I am getting FAQ section data from an API call. Like this one, I have my data in restaurant.faq and there can be multiple data so I map through it and it is working perfectly. Suppose Now I have two questions and two answers and I am getting it perfectly.
{restaurant.faq?.map((f) => (
<ListGroup.Item key={f.id}>
Question - <strong>{f.question}</strong>
<br />
Answer - <strong>{f.answer}</strong>
</ListGroup.Item>
))}
But I want to pass the same question and answer from this restaurant.faq in a const variable
Like this in rows [{question, answer}] section. How Can I do this?
const data = {
title: "FAQ",
rows: [
{
question: "Lorem ipsum dolor sit amet,",
answer: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sed tempor sem. Aenean vel turpis feugiat,
ultricies metus at, consequat velit. Curabitur est nibh, varius in tellus nec, mattis pulvinar metus.
In maximus cursus lorem, nec laoreet velit eleifend vel. Ut aliquet mauris tortor, sed egestas libero interdum vitae.
Fusce sed commodo purus, at tempus turpis.`,
},
{
question: "Nunc maximus, magna at ultricies elementum",
answer:
"Nunc maximus, magna at ultricies elementum, risus turpis vulputate quam, vitae convallis ex tortor sed dolor.",
},
],
};
Update how to do the same with this one?
{restaurant.menu?.map((men) => (
<ListGroup.Item key={men.id}>
<Image src={men.image} alt={men.name} style={{height:'250px', width:'1800px'}} fluid />
</ListGroup.Item>
))}
const images = [
{
original: 'https://picsum.photos/id/1018/1000/600/',
},
{
original: 'https://picsum.photos/id/1015/1000/600/',
},
{
original: 'https://picsum.photos/id/1019/1000/600/',
},
];
You can do like this
const data = {
title: "FAQ",
rows: restaurant.faq?.map(({ question, answer}) => (
{ question,
answer
})
)

how to change the position of Checkbox in sweetalert 2

I'm looking for a way to find if it is possible to change the position of the checkbox in sweetalert 2 from the center to the upper position? I used this code:
(async () => {
const { value: accept } = await Swal.fire({
title: 'Terms and conditions',
input: 'checkbox',
inputValue: 1,
inputPlaceholder:
'Yes, I agree to receive an email, including educational materials, product and company announcements, and community even information, from T&C. I can unsubscribe at any time. I would like to opt into receiving marketing communications as outlined above.',
confirmButtonText:
'Continue <i class="fa fa-arrow-right"></i>',
inputValidator: (result) => {
return !result && 'You need to agree with T&C'
}
})
if (accept) {
Swal.fire('You agreed with T&C :)')
}
})()
The result of this code is this:
I would like to change the checkbox from the center to the position of the word "Yes".
Use the customClass param to achieve the custom placement for the input:
Swal.fire({
input: 'checkbox',
inputPlaceholder: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
customClass: {
input: 'top-checkbox'
}
})
.top-checkbox input {
align-self: flex-start;
margin: 3px 10px 0 0 !important;
}
<script src="https://cdn.jsdelivr.net/npm/sweetalert2#11"></script>

Next.JS - Gist's embedded in markdown rendered via dangerouslySetInnerHTML only show after full page load, not React route load

I have a series of blog posts stored in MD files, some of these contain multiple Gist embeds in the form of script tags.
The MD contents are rendered to the page via dangerouslySetInnerHTML, and all is fine when the page is navigated to directly. However when the app's routing is used and a full page refresh doesn't happen the script tag is included in the markup, but not executed.
The following example is using the default Next.JS blog example here: https://github.com/vercel/next-learn-starter/tree/master/basics-final.
Markdown:
---
title: "Example of GIST embedding"
date: "2020-02-20"
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut id arcu at arcu pretium porta. Nam feugiat est ut lectus imperdiet venenatis. Ut tempus vitae lectus id vestibulum. Sed tristique est metus. Ut pretium malesuada risus. Maecenas eget diam tristique, sagittis velit ac, efficitur nisi. Quisque lectus lorem, vehicula at mi vitae, dapibus volutpat augue. Sed dignissim pharetra ligula a efficitur. In ultrices imperdiet libero. Quisque ornare erat eu elit ullamcorper faucibus. Maecenas mattis sem a mauris posuere iaculis.
<script src="https://gist.github.com/robearlam/aec15c65aaffbd5ec00a826c5cbe57ad.js"></script>
Etiam sed interdum ligula, nec tincidunt justo. Aliquam erat volutpat. Fusce in scelerisque nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis lectus at ligula mollis dapibus. Praesent condimentum metus fringilla, commodo enim non, fringilla dui. Vivamus nec ligula lacinia ante semper rhoncus eu sed nisi. In ac dolor vel lorem tincidunt lacinia. Praesent quis mattis mi, at finibus velit. Etiam auctor, magna fermentum tincidunt interdum, nulla augue porttitor enim, ac lobortis felis eros id dui. Suspendisse dignissim, dui sit amet pulvinar iaculis, nisi tellus rhoncus dolor, eu gravida risus massa accumsan magna.
Page
import Layout from '../../components/layout'
import { getAllPostIds, getPostData } from '../../lib/posts'
import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
export default function Post({ postData }) {
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</article>
</Layout>
)
}
export async function getStaticPaths() {
const paths = getAllPostIds()
return {
paths,
fallback: false
}
}
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id)
return {
props: {
postData
}
}
}
Lib function
export async function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents)
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.process(matterResult.content)
const contentHtml = processedContent.toString()
// Combine the data with the id and contentHtml
return {
id,
contentHtml,
...matterResult.data
}
I also have a repo showing the issue here: https://github.com/robearlam/gist-embedding-issue
Cheers!
I ran into this same problem, I found this post to be very helpful.
Basically, you create a custom code block that formats your code tags inline.
It has you use <ReactMarkdown> component to render your markdown (instead of remark) and then you use the react-syntax-highlighter library in your custom code block component.
When rendering your markdown use:
import CodeBlock from "../../components/codeblock"
<ReactMarkdown components={CodeBlock}>{your markdown data here}</ReactMarkdown>
Importing your custom codeblock component for the markdown processor.
Tom's custom code block example below:
// components/codeblock.js
import React from "react"
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
import {dracula} from 'react-syntax-highlighter/dist/cjs/styles/prism';
const CodeBlock = {
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
style={dracula}
language={match[1]}
PreTag="div" {...props}>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}
export default CodeBlock

How to show show more and show less link if text size is more than specified pixel in angularjs?

I want to show show more text only if the p tag is more than 40px height and if the text expands on click of show more, it should change to show less. So how can I check the condo if the text size is more than 40px ? Kindly help.
<p class="expandable" ng-class={expanded:show}>long text-------</p>
<a ng-if="!show" ng-click="show=true">show more</a>
<a ng-if="show" ng-click="show=false">show less</a>
CSS:
.expandable {
line-height:40px;
Overflow:hidden;
}
.expanded{
line-height:auto;
}
Hi referer this https://plnkr.co/edit/gfQmrD1mRvF81QXp7C8C?p=preview
HTML
<p class="expandable hideContent" ng-class=showclass> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
ghjgjgjkghkk jkhkj
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.-</p>
<div class="show-more">
{{showtest}}
</div>
JS
$scope.showtest = 'ShowLess';
$scope.showmore = function(_logout) {
if($scope.showtest == 'ShowMore')
{
$scope.showtest = 'ShowLess';
$scope.showclass = 'hideContent';
}
else
{
$scope.showtest = 'ShowMore';
$scope.showclass = 'showContent';
}
}
using the Line-height i implement the class
CSS
/* Put your css in here */
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
.showContent{
height: auto;
}

How to make a responsive banner?

How to make a responsive image banner that has image and text layers with absolute positions? My client wants the banner along with the layered text and images to scale down when the screen goes smaller (Please refer to the screenshot below). I am not looking for a slider, this is just a simple banner with layers. My client has different banners(with layers) on every page, their website used to be non-responsive and now they want to make it responsive. CSS Media queries will probably not work here since I have to define a new font size and image width for every pixel change on the screen which I believe is time consuming.
As you can see, the banner along with the layered texts and images scales down as the screen goes smaller
Link to my fiddle: https://jsfiddle.net/ophLk9pz/1/
HTML:
<div class = "banner">
<img src = "http://i.imgur.com/yfGOPkH.jpg" />
<img src = "http://www.dummymag.com//media/img/dummy-logo.png" class = "layer-image">
<h1>Sample Banner Text</h1>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.</p>
</div>
CSS:
.banner { width: 1440px; position: relative; }
.banner img { z-index: -1; }
.banner h1 {position: absolute; bottom: 30px; left: 10px; }
.banner p {position: absolute; top: 150px; left: 10px; }
.banner .layer-image { position: absolute; top: 0; left: 150px; z-index: 2; }
Any help or ideas would be greatly appreciated, thanks in advance!
You can try to use viewport percentage units on the texts:
https://drafts.csswg.org/css-values/#viewport-relative-lengths
h1 { font-size: 8vw }
And images can be scaled like so:
img {
height: auto;
width:100%;
}
If you need fancier scaling methods (contain, cover etc) i believe you need to have the image as a background-image

Resources