Map is only displaying one item in it - reactjs

I am trying to display the items in the array, but only one item is being displayed. I have tried changing id, although it didnt work.
import React, { useState } from 'react';
import Note from './noteItself';
const NoteItems=[
{id:1, message:'asdf',title:'New Note'},
{id:2, message:'asdf',title:'e'}
]
const NoteDisplay = () => {
return (
<div className="note-container">
{NoteItems.map((items)=><Note items={items}/>)}
</div>
)
}
export default NoteDisplay;
import React from 'react';
const Note = ({items}) => {
console.log(items);
return (
<div className="note-box">
<h1 className="note-title">{items.title}</h1>
</div>
)
}
export default Note;
css
.note-container { display: flex; }
.note-box { flex-direction: row; flex-grow: 1; height: 181px; width: 181px; border-radius: 20px; position: absolute; left: 22.09%; right: 65.94%; top: 26.58%; bottom: 54.99%; background: #ffffff; box-shadow: 0px 3px 16px rgba(0, 0, 0, 0.09); border-radius: 20px; }

Since you have absolute positioning on the note-box class, all the items are going to get rendered on top of each other. You will want to remove all of your absolute positioning (position: absolute; left: 22.09%; right: 65.94%; top: 26.58%; bottom: 54.99%;) to let flexbox arrange your items.

Related

Mapped buttons that have opacity of 0 are showing, and are overlapping when resizing the window

I've successfully mapped over text and have styled it with transition effects when going from one slide to the next as you can see here:
Following a similar concept with buttons isn't working. There should only be one button active per slide like you see here:
I want the buttons to have the same effect as the text, but I'm getting behaviors like you see here:
As you can see, there is no transition effect on the button when clicking to the second slide, and it also appears in a lower spot.
And lastly, when resizing the window, buttons are overlapping like you see here:
Don't know what to try next.
Here's the ImageSlider component:
import { useState } from "react";
import { SliderData } from "../data";
import { categories } from "../data";
import ShopNowButtonActive from "./ShopNowButtonActive";
import { IoIosArrowBack } from "react-icons/io";
import { IoIosArrowForward } from "react-icons/io";
import "./ImageSlider.css";
import ShopNowButton from "./ShopNowButton";
const ImageSlider = ({ slides }) => {
const [current, setCurrent] = useState(0);
const length = slides.length;
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
return (
<div className="slider">
<IoIosArrowBack className="left-arrow" onClick={prevSlide} />
{SliderData.map((slide, index) => (
<div key={slide.id}>
<img
src={slide.img}
alt=""
className={index === current ? "slide active" : "slide"}
/>
<div className="info-container">
<div className={index === current ? "title active" : "title"}>
{slide.title}
</div>
<div className={index === current ? "desc active" : "desc"}>
{slide.desc}
</div>
{categories.map((item, index) =>
index === current ? (
<ShopNowButtonActive item={item} />
) : (
<ShopNowButton item={item} />
)
)}
</div>
</div>
))}
<IoIosArrowForward className="right-arrow" onClick={nextSlide} />
</div>
);
};
export default ImageSlider;
The css file:
.slider {
height: 90vh;
margin-bottom: 0.5rem;
}
.left-arrow {
position: absolute;
top: 45%;
left: 32px;
font-size: 2rem;
cursor: pointer;
opacity: 0.5;
z-index: 1;
}
.slide.active {
opacity: 1;
width: 100%;
height: 88%;
object-fit: cover;
object-position: center;
-webkit-clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
}
.slide {
opacity: 0;
transition: 500ms opacity ease-in-out;
width: 100%;
height: 88%;
object-fit: cover;
object-position: center;
position: absolute;
-webkit-clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
}
.info-container {
display: flex;
flex-direction: column;
width: 40%;
height: 100%;
position: absolute;
top: 45%;
right: 30px;
}
.title.active {
opacity: 1;
transition-delay: 700ms;
font-size: 4rem;
}
.title {
opacity: 0;
transition: 200ms opacity ease-in-out;
font-size: 4rem;
}
.desc.active {
opacity: 1;
padding-top: 1.5em;
transition-delay: 700ms;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 3px;
}
.desc {
opacity: 0;
padding-top: 1.5em;
transition: 200ms opacity ease-in-out;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 3px;
}
.right-arrow {
position: absolute;
top: 45%;
right: 32px;
font-size: 2rem;
cursor: pointer;
opacity: 0.5;
z-index: 1;
}
The ShopNowButtonActive component:
import React from "react";
import styled from "styled-components/macro";
import { Link } from "react-router-dom";
const ButtonActive = styled.button`
opacity: 1;
padding: 0.5rem;
margin-top: 2.5rem;
width: 8rem;
font-size: 20px;
background-color: transparent;
cursor: pointer;
transition-delay: 700ms;
`;
const ShopNowButtonActive = ({ item }) => {
return (
<Link to={`/products/${item.cat}`}>
<ButtonActive>SHOP NOW</ButtonActive>
</Link>
);
};
export default ShopNowButtonActive;
And finally, the ShopNowButton component:
import React from "react";
import styled from "styled-components/macro";
import { Link } from "react-router-dom";
const Button = styled.button`
opacity: 0;
/* display: none; */
padding: 0.5rem;
margin-top: 2.5rem;
width: 8rem;
font-size: 20px;
background-color: transparent;
cursor: pointer;
transition: 200ms opacity ease-in-out;
`;
const ShopNowButton = ({ item }) => {
return (
<Link to={`/products/${item.cat}`}>
<Button>SHOP NOW</Button>
</Link>
);
};
export default ShopNowButton;
(Sorry for the use of both an external css file and styled components.)
Any suggestions?
I have recreated the above scenario using some static data. I have modified some of the css. It is working as expected. I also observed that the only major difference between ShopNowButton and ShopNowButtonActive was opacity property which hides the element. The reason you are observing 2 buttons because they were all there in the dom actually.(They were not hiding properly due to which we are observing more shop now buttons and every time we click on next icon the corresponding button is being displayed. Basically all the buttons are there on the page itself.)
Please find the sandbox url below.
https://codesandbox.io/s/stackoverflow-6u05e7?file=/src/ImageSlider/ImageSlider.js

By using styled components, how can I add some opacity to a background color that comes from an external prop?

This is my code, below it you will find the question
import { printIntrospectionSchema } from 'graphql';
import React, { useContext, useState } from 'react';
import styled from 'styled-components';
import { Context } from '../../../Context/Context';
// DATA
function DurationIntervalSelection() {
const tabsData = [
{
text: 'Duration',
},
{
text: 'Interval',
},
];
// STATE
const [selectedIndex, setselectedIndex] = useState(0);
const { selected } = useContext(Context);
console.log(selected.color, 'selected color');
// FUNCTION
const handleIndexSelection = (index) => {
setselectedIndex(index);
};
return (
<Container>
<TabsContainer backgroundColor={selected.backgroundColor}>
<Indicator
backgroundColor={selected.color}
style={{
left: `${selectedIndex * 50}%`,
}}
/>
{tabsData.map((tab, index) => {
return (
<Tab
style={{
color: selectedIndex === index ? 'white' : 'black',
}}
onClick={() => handleIndexSelection(index)}
key={tab.text}
>
<p style={{ zIndex: 100 }}>{tab.text}</p>
</Tab>
);
})}
</TabsContainer>
</Container>
);
}
const Container = styled.div`
margin-top: 10px;
border: 1px solid #f2f2f7;
border-radius: 10px;
box-sizing: border-box;
padding: 10px 0;
`;
const Indicator = styled.div`
width: 50%;
position: absolute;
/* z-index: -1; */
height: 100%;
border-radius: 20px;
cursor: pointer;
transition: all 0.3s;
background-color: ${(props) => props.backgroundColor};
`;
const TabsContainer = styled.div`
display: flex;
width: 100%;
justify-content: space-between;
position: relative;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
border-radius: 20px;
overflow: hidden;
background-color: ${(props) => props.backgroundColor};
`;
const Tab = styled.div`
display: flex;
width: 50%;
justify-content: center;
cursor: pointer;
align-items: center;
padding: 10px;
`;
export default DurationIntervalSelection;
As you can see from the above code i pass backgroundColor as a prop that takes some color from a React state.
<TabsContainer backgroundColor={selected.backgroundColor}>
And in the styled component I do:
background-color: ${(props) => props.backgroundColor};
But my question is, since i need to follow a design made by a colleague, how do i add opacity to the above background color without affecting the opacity of the whole div: TabsContainer. I mean, if i add on the TabsContainer -> opacity: 0.3 - for instance the whole TabsContainer div will be affected by the opacity, including the Tab div, while what I want is just to change opacity on the color itself so i do not affect any child. I hope it makes sense. Is there a way?
Okay if your hex value comes from your backend, you can either create your own javascript function that converts hex to rgba or you can use a library like polished. They have a function named rgba that converts a hex string and adds an alpha value to it
import { rgba } from 'polished'
const div = styled.div`
background: ${(props) => rgba(props.backgroundColor, 0.3)};
`
Or you can apply it directly to the prop
<TabsContainer backgroundColor={rgba(selected.backgroundColor, 0.3)}>
Example CodeSandbox.
Since the data from the backend where right but I could not find a solution I have realised that I could have added to
<TabsContainer backgroundColor="rgba(255,255,255, 0.5)">
A background color on the white notes with opacity so to emphasise the color behind it in a lighter way

Custom arrow Swiper Slider + Next.js + Sass

I'm using the slider swiper in a project developed in Next.JS and I'm using Sass to do the styling. But when I'm going to use the swiper classes, as mandated by the documentation, to style the arrows, it doesn't work.
I need the arrows to be outside the component, not overlapping.
CSS
.swiper-button-next,
.swiper-button-prev {
background: red;
position: absolute;
top: 50%;
width: calc(var(--swiper-navigation-size) / 44 * 27);
height: var(--swiper-navigation-size);
margin-top: calc(0px - (var(--swiper-navigation-size) / 2));
z-index: 10;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--swiper-navigation-color, var(--swiper-theme-color));
}
.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
opacity: 0.35;
cursor: auto;
pointer-events: none;
}
.swiper-button-next:after,
.swiper-button-prev:after {
background: red;
font-family: swiper-icons;
font-size: var(--swiper-navigation-size);
text-transform: none !important;
letter-spacing: 0;
text-transform: none;
font-variant: initial;
line-height: 1;
}
.swiper-button-prev,
.swiper-container-rtl .swiper-button-next {
left: 10px;
right: auto;
}
.swiper-button-prev:after,
.swiper-container-rtl .swiper-button-next:after {
content: "prev";
color: #000;
}
.swiper-button-next,
.swiper-container-rtl .swiper-button-prev {
right: 10px;
left: auto;
}
.swiper-button-next:after,
.swiper-container-rtl .swiper-button-prev:after {
content: "next";
}
.swiper-button-next.swiper-button-white,
.swiper-button-prev.swiper-button-white {
--swiper-navigation-color: #ffffff;
}
.swiper-button-next.swiper-button-black,
.swiper-button-prev.swiper-button-black {
--swiper-navigation-color: #000000;
}
.swiper-button-lock {
display: none;
}
I've tried changing the styles, but nothing reflects on the component. If I change styles by browser it works normally.
Changing the basic arrows styles is pretty simple - take a look at the following codesandbox: https://codesandbox.io/s/stoic-shaw-q35wq?file=/src/styles.scss
.swiper-button-prev, .swiper-button-next {
top: 45%;
width: 40px;
height: 40px;
background: #fff;
border: 1px solid gray;
border-radius: 50%;
color: blue;
font-weight: 700;
outline: 0;
transition: background-color .2s ease, color .2s ease;
&::after {
font-size: 16px;
}
}
.swiper-button-prev {
&:after {
position: relative;
left: -1px;
}
}
.swiper-button-next {
&:after {
position: relative;
left: 1px;
}
}
.swiper-button-prev, .swiper-container-rtl .swiper-button-next {
left: 10px;
right: auto;
}
.swiper-button-next, .swiper-container-rtl .swiper-button-prev {
right: 10px;
left: auto;
}
.swiper-button-prev.swiper-button-disabled, .swiper-button-next.swiper-button-disabled {
opacity: 0;
cursor: auto;
pointer-events: none;
}
Moving the arrows outside, however, is a bit more tricky. In the example above I've used a little CSS tricks (negative margin and corresponding padding) and some overflows to get it working but it might not be enough for your use case.
You would have to create your own next/previous elements:
import React from "react";
import { Navigation, Pagination, Scrollbar, A11y, Controller } from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
// Import Swiper styles
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import "swiper/css/scrollbar";
import "./styles.scss";
const image = "https://source.unsplash.com/featured/300x201";
export default function App() {
const images = new Array(6).fill({ url: image });
const [swiper, setSwiper] = React.useState();
const prevRef = React.useRef();
const nextRef = React.useRef();
React.useEffect(() => {
if (swiper) {
console.log("Swiper instance:", swiper);
swiper.params.navigation.prevEl = prevRef.current;
swiper.params.navigation.nextEl = nextRef.current;
swiper.navigation.init();
swiper.navigation.update();
}
}, [swiper]);
return (
<div className="App">
<div className="carousel-container">
<div className="swiper-button" ref={prevRef}>
prev
</div>
<Swiper
modules={[Navigation, Pagination, Scrollbar, A11y, Controller]}
className="external-buttons"
spaceBetween={24}
slidesPerView={1}
navigation={{
prevEl: prevRef?.current,
nextEl: nextRef?.current
}}
updateOnWindowResize
observer
observeParents
initialSlide={2}
onSwiper={setSwiper}
>
{images.map((image, index) => (
<SwiperSlide key={index}>
<img
height="200"
width="300"
alt="img"
className="image"
src={image.url}
/>
</SwiperSlide>
))}
</Swiper>
<div className="swiper-button" ref={nextRef}>
next
</div>
</div>
</div>
);
}
Complete example - https://codesandbox.io/s/prod-darkness-o483y?file=/src/App.js
Important - the examples are using Swiper v7
Here is the best way to add custom arrows:
import React, { useRef } from "react";
// For Typescript
// import SwiperCore from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
const SliderComponent = () => {
const swiperRef = useRef();
// For Typescript!
// const swiperRef = useRef<SwiperCore>();
const sliderSettings = {
440: {
slidesPerView: 1,
spaceBetween: 30,
},
680: {
slidesPerView: 2,
spaceBetween: 30,
},
1024: {
slidesPerView: 3,
spaceBetween: 30,
},
};
return (
<div>
<button onClick={() => swiperRef.current?.slidePrev()}>Prev</button>
<Swiper
slidesPerView={3}
breakpoints={sliderSettings}
onBeforeInit={(swiper) => {
swiperRef.current = swiper;
}}
>
<SwiperSlide>
Slide 1
</SwiperSlide>
<SwiperSlide>
Slide 2
</SwiperSlide>
<SwiperSlide>
Slide 3
</SwiperSlide>
<SwiperSlide>
Slide 4
</SwiperSlide>
<SwiperSlide>
Slide 5
</SwiperSlide>
</Swiper>
<button onClick={() => swiperRef.current?.slideNext()}>Next</button>
</div>
);
};
export default SliderComponent;
hamza liaqat's answer is correct, but for typescript you need to add
import { Swiper as SwiperCore } from 'swiper/types';

Modal is displayed below the items

I have come into a strange issue that has stopped me for a few hours. I have created a MERN app in which I have a page that I introduce members of a team. I also have a modal for each member triggered by click on member. The problem is that when I create a new member, the modals related to previous members is displayed behind the latter added members. I will attach pictures to more clearly demonstrate what happens.
enter image description here
enter image description here
Here is how I have defined the modal:
const Modal = ({ closeModal, children }) => {
const closeIcon = () => (
<FontAwesome
name='times'
onClick={closeModal}
className='modal-font-awesome'
/>
)
return (
<div id='overlay'>
<div className='content'>
{closeIcon()}
{children}
</div>
</div>
)
}
Here is my scss code for styling the modal:
#overlay {
position: fixed;
display: block;
overflow: hidden;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.content {
margin: 120px auto;
background-color: white;
border-radius: 0.25rem;
width: 70vw;
padding: 2rem;
position: relative;
border-left: 5px solid rgb(37, 153, 124);
}
Do you have any suggestions about what is happening?
Thank you in advance.

pseudo styled component h2 not showing in html

I'm currently trying to create an animation on an H2, using the pseudos ::before and after. But the ::before and ::after are not showing in my HTML.
What am I doing wrong here? Looking at styled components docs this should just work. I'm aware of the weird animation function. But this does not have any influence in the before after. I already completely removed it but it still doesn't render.
import React from 'react'
import styled, { keyframes, css } from 'styled-components'
import PropTypes from 'prop-types'
const Wrapper = styled.h2`
position: relative;
font-size: 1.5rem;
color: #ffffff;
font-weight: 600;
text-align: center;
text-transform: uppercase;
letter-spacing: 0.01em;
transform: scale3d(1,1,1);
opacity: 1;
&::before, &::after{
content: ${(props) => props.text};
position: absolute;
top: 0;
left: 0;
right: 0;
overflow: hidden;
background: #333333;
color: #ffffff;
clip: rect(0, 900px, 0, 0);
}
&::before {
left: 7px;
text-shadow: 1px 0 green;
animation: ${glitchEffect} 3s infinite linear alternate-reverse;
}
&::after {
left: 3px;
text-shadow: -1px 0 red;
animation: ${glitchEffect} 2s infinite linear alternate-reverse;
}
`
const glitchEffect = keyframes`
${setInterval(createAnimation, 200)}
`
function createAnimation(){
const single = `clip: rect(${(Math.floor(Math.random() * 100 + 1))}px, 9999px, ${(Math.floor(Math.random() * 100 + 1))}px, 0);`
return css`${single}`
}
export default function Glitch({ text }){
return (
<Wrapper text={text}>{text}</Wrapper>
)
}
Glitch.propTypes = {
text: PropTypes.string.isRequired
}
A few things:
content: ${(props) => props.text}; wouldn't work, you need to add double quotes around the text like so content: "${(props) => props.text}";
The second issue is setInterval(createAnimation, 200). This will return an integer (a handle to the interval that you've just created). This will be needed to clear the interval once you're done with the animation for example.
If what you want to do is to generate a some keyframes, then you need to call createAnimation manually like so
import React from "react";
import styled, { keyframes, css } from "styled-components";
const glitchEffect = keyframes`
from {
${createAnimation()}
}
to {
${createAnimation()}
}
`;
const Wrapper = styled.h2`
position: relative;
font-size: 1.5rem;
color: #ffffff;
font-weight: 600;
text-align: center;
text-transform: uppercase;
letter-spacing: 0.01em;
transform: scale3d(1, 1, 1);
opacity: 1;
> .before,
> .after {
position: absolute;
top: 0;
left: 0;
right: 0;
overflow: hidden;
background: #333333;
color: #ffffff;
clip: rect(0, 900px, 0, 0);
}
> .before {
left: 7px;
text-shadow: 1px 0 green;
animation: ${glitchEffect} 3s infinite linear alternate-reverse;
}
> .after {
left: 3px;
text-shadow: -1px 0 red;
animation: ${glitchEffect} 2s infinite linear alternate-reverse;
}
`;
function createAnimation() {
const single = `clip: rect(${Math.floor(
Math.random() * 100 + 1
)}px, 9999px, ${Math.floor(Math.random() * 100 + 1)}px, 0);`;
return css`
${single}
`;
}
export default function Glitch({ text }) {
return (
<Wrapper>
<div className="before">{text}</div>
{text}
<div className="after">{text}</div>
</Wrapper>
);
}
If you want to generate random animation, then you'll need to create the interval from Glitch
// First transform your "animation: ${glitchEffect} 3s infinite linear alternate-reverse;"
// into a "transition: text-shadow 500ms linear;"
// Since we're manually changing its value
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
const Wrapper = styled.h2`
position: relative;
font-size: 1.5rem;
color: #ffffff;
font-weight: 600;
text-align: center;
text-transform: uppercase;
letter-spacing: 0.01em;
transform: scale3d(1, 1, 1);
opacity: 1;
> .before,
> .after {
position: absolute;
top: 0;
left: 0;
right: 0;
overflow: hidden;
background: #333333;
color: #ffffff;
}
> .before {
left: 7px;
text-shadow: 1px 0 green;
transition: clip 300ms linear;
}
> .after {
left: 3px;
text-shadow: -1px 0 red;
transition: clip 200ms linear;
}
`;
function createAnimation() {
return {
clip: `rect(${Math.floor(Math.random() * 100 + 1)}px, 9999px, ${Math.floor(
Math.random() * 100 + 1
)}px, 0)`
};
}
export default function Glitch({ text }) {
const [glitchEffect, setGlitchEffect] = useState(createAnimation());
useEffect(() => {
const interval = setInterval(() => setGlitchEffect(createAnimation()), 500);
return () => {
clearInterval(interval);
};
}, []);
// now pass glitchEffect to a "style" prop to your pseudo elements
// See https://stackoverflow.com/a/28269950/3877913
return (
<Wrapper>
<div className="before" style={glitchEffect}>
{text}
</div>
{text}
<div className="after" style={glitchEffect}>
{text}
</div>
</Wrapper>
);
}

Resources