I am developing a website using react. I want to add a divider for all sections. But I can't set its position at bottom 0. It seems like this:
I am using some wrappers. And maybe it's the reason.
I want to add a divider to the "work" section. Here are the files:
work.jsx:
import React, { useState, useEffect } from 'react';
import { AiFillEye, AiFillGithub } from 'react-icons/ai';
import { motion } from 'framer-motion';
import { AppWrap, MotionWrap } from '../../wrapper';
import { urlFor, client } from '../../client';
import './Work.scss';
function Work() {
const [activeFilter, setActiveFilter] = useState('All');
const [animateCard, setAnimateCard] = useState({ y:0, opacity: 1 });
const [works, setWorks] = useState([]);
const [filterWork, setFilterWork] = useState([]);
useEffect(() => {
const query = '*[_type == "works"]'
client.fetch(query).then((data) => {
setWorks(data);
setFilterWork(data);
})
}, [])
const handleWorkFilter = (item) => {
setActiveFilter(item);
setAnimateCard([{ y:100, opacity:0 }])
setTimeout (() => {
setAnimateCard([{ y:0, opacity: 1}])
if(item === 'All') {
setFilterWork(works)
} else {
setFilterWork(works.filter((work) => work.tags.includes(item)))
}
},500)
}
return (
<>
<h2 className="head-text-green">MY PROJECTS</h2>
<div className='app__work-filter'>
{['UI/UX', 'REACT JS', 'HTML', 'JAVACRIPT', 'CSS', 'SCSS', 'ALL'].map((item, index) =>
<div
className={`app__work-filter-item app__flex p-text-green ${activeFilter === item ? "item-active" : ""}`}
key={index}
onClick={() => handleWorkFilter(item)}
>
{item}
</div>
)}
</div>
<motion.div
animate = {animateCard}
transition = {{ duration: 0.5, delayChildren: 0.5 }}
className = 'app__work-portfolio'
>
{filterWork.map((work, index) =>
<div className='app__work-item app__flex' key={index}>
<div className='app__work-img app__flex'>
<img src={urlFor(work.imgUrl)} alt={work.name} />
<motion.div
whileHover={{ opacity: [0,1]}}
transition={{ duration: 0.25, ease: 'easeInOut', staggerChildren: 0.5 }}
className='app__work-hover app__flex'
>
<a href={work.projectLink} target='_blank' rel='noreferrer'>
<motion.div
whileInView={{ scale: [0, 1]}}
whileHover={{ scale: [1, 0.9]}}
transition={{ duration: 0.25 }}
className='app__flex'
>
<AiFillEye />
</motion.div>
</a>
<a href={work.codeLink} target='_blank' rel='noreferrer'>
<motion.div
whileInView={{ scale: [0, 1]}}
whileHover={{ scale: [1, 0.9]}}
transition={{ duration: 0.25 }}
className='app__flex'
>
<AiFillGithub />
</motion.div>
</a>
</motion.div>
</div>
<div className='app__work-content app__flex'>
<h4 className='bold-text-green'>{work.title}</h4>
<p className='p-text' style={{marginTop: 10}}>{work.description}</p>
<div className='app__work-tag app__flex'>
<p className='p-text'>{work.tags[0]}</p>
</div>
</div>
</div>
)}
</motion.div>
<div class="custom-shape-divider-bottom-1657991521">
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
<path d="M602.45,3.86h0S572.9,116.24,281.94,120H923C632,116.24,602.45,3.86,602.45,3.86Z" class="shape-fill"></path>
</svg>
</div>
</>
)
}
export default AppWrap(
MotionWrap(Work, 'app__works'),
'work',
'app__grey1bg'
);
work.scss:
.app__works {
flex: 1;
width: 100%;
flex-direction: column;
}
.app__work-filter {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin: 4rem 0 2rem;
.app__work-filter-item {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
background-color: #fff;
font-weight: 800;
cursor: pointer;
transition: all 0.3s ease;
margin: 0.5rem;
&:hover {
background-color: var(--secondary-color);
color: #fff;
}
#media screen and (min-width: 2000px) {
padding: 1rem 2rem;
border-radius: 0.85rem;
}
}
.item-active {
background-color: var(--secondary-color);
color: #fff;
}
}
.app__work-portfolio {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.app__work-item{
width: 270px;
flex-direction: column;
margin: 2rem;
padding: 1rem;
border-radius: 0.5rem;
background-color: #fff;
color: #000;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
box-shadow: 0 0 25px rgba(0,0,0,0.2);
}
#media screen and (min-width: 2000px) {
width: 470px;
padding: 1.25rem;
border-radius: 0.75rem;
}
#media screen and (max-width: 300px) {
width: 100%;
margin: 1rem;
}
}
}
.app__work-img {
width: 100%;
height: 230px;
position: relative;
img {
width: 100%;
height: 100%;
border-radius: 0.5rem;
object-fit: cover;
}
#media screen and (min-width: 2000px) {
height: 350px;
}
}
.app__work-hover {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
border-radius: 0.5rem;
opacity: 0;
transition: all 0.3s ease;
div {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: rgba(0,0,0,0.5);
color: white;
margin: 1rem;
font-family: var(--font-base);
font-weight: 800;
cursor: pointer;
transition: all 0.3s ease;
svg {
width: 50%;
height: 50%;
color: var(--white-color);
}
}
}
.app__work-content {
padding: 0.5rem;
width: 100%;
position: relative;
flex-direction: column;
h4 {
margin-top: 1rem;
line-height: 1.5;
}
.app__work-tag {
position: absolute;
padding: 0.5rem 1rem;
border-radius: 10px;
background-color: #fff;
top: -25px;
}
}
.custom-shape-divider-bottom-1657991521 {
position: relative;
bottom: 0;
left: 0;
width: 100%;
overflow: hidden;
line-height: 0;
}
.custom-shape-divider-bottom-1657991521 svg {
position: relative;
display: block;
width: calc(100% + 1.3px);
height: 58px;
}
.custom-shape-divider-bottom-1657991521 .shape-fill {
fill: #BDD2B6;
}
appWrap.js (it use NavigationDots.jsx with classname="app__navigation" and SocialMedia.jsx with class name= "app__social" ):
import { color } from '#mui/system';
import React from 'react';
import { NavigationDots, SocialMedia } from '../components';
const AppWrap = (Component, idName, classNames) => function HOC() {
return (
<div id={idName} className={`app__container ${classNames}`}>
<SocialMedia />
<div className='app__wrapper app__flex'>
<Component />
<div className='copyright'>
<p className='p-text'>#2022 AYGEN</p>
<p className='p-text'>All rights reserved</p>
</div>
</div>
<NavigationDots active={idName} />
</div>
)
}
export default AppWrap;
MotionWrap.js:
import React from 'react';
import { motion } from 'framer-motion';
const MotionWrap = (Component, classNames) => function HOC() {
return (
<motion.div
whileInView={{ y: [100, 50, 0], opacity: [0, 0, 1] }}
transition={{ duration: 0.5 }}
className={`${classNames} app__flex`}
>
<Component />
</motion.div>
)
}
export default MotionWrap
a part of app.scss file:
.app__social {
display: flex;
justify-content: flex-end;
align-items: center;
flex-direction: column;
padding: 1rem;
position: initial;
div {
z-index: 5;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: rgb(255, 255, 255);
margin: 0.25rem 0;
border: 1px solid var(--lightGray-color);
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease-in-out;
svg {
width: 15px;
height: 15px;
color: var(--green5-color);
}
&:hover {
background-color: var(--secondary-color);
border-color: var(--secondary-color);
svg {
color: var(--white-color);
}
}
#media screen and (min-width: 2000px) {
width: 70px;
height: 70px;
margin: 0.5rem 0;
svg {
width: 30px;
height: 30px;
}
}
}
#media screen and (max-width: 600px) {
justify-content: center;
}
}
.app__navigation {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 1rem;
.app__navigation-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #cbcbcb;
margin: 0.5rem;
transition: background-color 0.2s ease-in-out;
z-index: 5;
&:hover {
background-color: var(--secondary-color);
}
#media screen and (min-width: 2000px) {
width: 20px;
height: 20px;
}
}
}
#media screen and (max-width: 500px) {
.app__navigation,
.app__social {
display: none;
}
.copyright {
padding: 2rem;
}
}
I don't know if any other file is necessary to solve. Thanks in advance.
import { color } from "#mui/system";
import React from "react";
import { NavigationDots, SocialMedia } from "../components";
const AppWrap = (Component, idName, classNames) =>
function HOC() {
return (
<div id={idName} className={`app__container ${classNames}`}>
<SocialMedia />
<div className="app__wrapper app__flex">
<Component />
<div className="copyright">
<p className="p-text">#2022 AYGEN</p>
<p className="p-text">All rights reserved</p>
</div>
<div class="custom-shape-divider-bottom-1657991521">
<svg
data-name="Layer 1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1200 120"
preserveAspectRatio="none"
>
<path
d="M602.45,3.86h0S572.9,116.24,281.94,120H923C632,116.24,602.45,3.86,602.45,3.86Z"
class="shape-fill"
></path>
</svg>
</div>
</div>
<NavigationDots active={idName} />
</div>
);
};
export default AppWrap;
Related
In my nextjs project everything works fine in desktop but in mobile (chorme) text is displayed sometimes and sometimes text is invisible. Here are the images Desktop Mobile-text-shown Mobile-text-not-shown
/* index.js */
import Head from "next/head";
import React from "react";
import MainContainer from "../components/Maincontainer";
import BookHoliday from "../components/BookHoliday";
export default function Home() {
return (
<>
<Head>
<title>Tourister</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<MainContainer />
<BookHoliday/>
<div className="test">
<h2>Just For Test</h2>
<p>
lorem400
</p>
</div>
</>
);
}
/* MainContainer.js */
import React, { useEffect, useRef } from "react";
import { FaAngleLeft, FaAngleRight } from "react-icons/fa";
import Navbar from "./Navbar";
import Header from "./Header";
import SideBar from "./SideBar";
import Image from "next/legacy/image";
function showAnimation() {
var count = 2;
let myInterval = null;
function runInterval() {
myInterval = setInterval(() => {
if (count === 3) {
document.getElementById("bg-3").style.opacity = "0";
document.getElementById("circle3").classList.remove("circle-ani");
document
.getElementById("small-circle3")
.classList.remove("small-circle-ani");
document.getElementById("bg-1").style.opacity = "1";
document.getElementById("circle1").classList.add("circle-ani");
document
.getElementById("small-circle1")
.classList.add("small-circle-ani");
count = 1;
} else if (count === 2) {
document.getElementById("bg-2").style.opacity = "0";
document.getElementById("circle2").classList.remove("circle-ani");
document
.getElementById("small-circle2")
.classList.remove("small-circle-ani");
document.getElementById("bg-3").style.opacity = "1";
document.getElementById("circle3").classList.add("circle-ani");
document
.getElementById("small-circle3")
.classList.add("small-circle-ani");
count = 3;
} else if (count === 1) {
document.getElementById("bg-1").style.opacity = "0";
document.getElementById("circle1").classList.remove("circle-ani");
document
.getElementById("small-circle1")
.classList.remove("small-circle-ani");
document.getElementById("bg-2").style.opacity = "1";
document.getElementById("circle2").classList.add("circle-ani");
document
.getElementById("small-circle2")
.classList.add("small-circle-ani");
count = 2;
}
}, 3000);
}
runInterval();
document.getElementById("circle1").addEventListener("click", () => {
changeBg("bg-1");
});
document.getElementById("circle2").addEventListener("click", () => {
changeBg("bg-2");
});
document.getElementById("circle3").addEventListener("click", () => {
changeBg("bg-3");
});
document.getElementById("left").addEventListener("click", () => {
changeBg("left");
});
document.getElementById("right").addEventListener("click", () => {
changeBg("right");
});
function changeBg(data) {
if (data === "bg-1") {
clearInterval(myInterval);
document.getElementById(`bg-${count}`).style.opacity = "0";
document.getElementById(`circle${count}`).classList.remove("circle-ani");
document
.getElementById(`small-circle${count}`)
.classList.remove("small-circle-ani");
document.getElementById("bg-1").style.opacity = "1";
document.getElementById("circle1").classList.add("circle-ani");
document
.getElementById("small-circle1")
.classList.add("small-circle-ani");
count = 1;
setTimeout(() => {
runInterval();
});
}
if (data === "bg-2") {
clearInterval(myInterval);
document.getElementById(`bg-${count}`).style.opacity = "0";
document.getElementById(`circle${count}`).classList.remove("circle-ani");
document
.getElementById(`small-circle${count}`)
.classList.remove("small-circle-ani");
document.getElementById("bg-2").style.opacity = "1";
document.getElementById("circle2").classList.add("circle-ani");
document
.getElementById("small-circle2")
.classList.add("small-circle-ani");
count = 2;
setTimeout(() => {
runInterval();
});
}
if (data === "bg-3") {
clearInterval(myInterval);
document.getElementById(`bg-${count}`).style.opacity = "0";
document.getElementById(`circle${count}`).classList.remove("circle-ani");
document
.getElementById(`small-circle${count}`)
.classList.remove("small-circle-ani");
document.getElementById("bg-3").style.opacity = "1";
document.getElementById("circle3").classList.add("circle-ani");
document
.getElementById("small-circle3")
.classList.add("small-circle-ani");
count = 3;
setTimeout(() => {
runInterval();
});
}
if (data === "left") {
clearInterval(myInterval);
if (count === 3) {
document.getElementById("bg-3").style.opacity = "0";
document.getElementById("circle3").classList.remove("circle-ani");
document
.getElementById("small-circle3")
.classList.remove("small-circle-ani");
document.getElementById("bg-2").style.opacity = "1";
document.getElementById("circle2").classList.add("circle-ani");
document
.getElementById("small-circle2")
.classList.add("small-circle-ani");
count = 2;
setTimeout(() => {
runInterval();
});
} else if (count === 2) {
document.getElementById("bg-2").style.opacity = "0";
document.getElementById("circle2").classList.remove("circle-ani");
document
.getElementById("small-circle2")
.classList.remove("small-circle-ani");
document.getElementById("bg-1").style.opacity = "1";
document.getElementById("circle1").classList.add("circle-ani");
document
.getElementById("small-circle1")
.classList.add("small-circle-ani");
count = 1;
setTimeout(() => {
runInterval();
});
} else if (count === 1) {
document.getElementById("bg-1").style.opacity = "0";
document.getElementById("circle1").classList.remove("circle-ani");
document
.getElementById("small-circle1")
.classList.remove("small-circle-ani");
document.getElementById("bg-3").style.opacity = "1";
document.getElementById("circle3").classList.add("circle-ani");
document
.getElementById("small-circle3")
.classList.add("small-circle-ani");
count = 3;
setTimeout(() => {
runInterval();
});
}
}
if (data === "right") {
clearInterval(myInterval);
if (count === 3) {
document.getElementById("bg-3").style.opacity = "0";
document.getElementById("circle3").classList.remove("circle-ani");
document
.getElementById("small-circle3")
.classList.remove("small-circle-ani");
document.getElementById("bg-1").style.opacity = "1";
document.getElementById("circle1").classList.add("circle-ani");
document
.getElementById("small-circle1")
.classList.add("small-circle-ani");
count = 1;
setTimeout(() => {
runInterval();
});
} else if (count === 2) {
document.getElementById("bg-2").style.opacity = "0";
document.getElementById("circle2").classList.remove("circle-ani");
document
.getElementById("small-circle2")
.classList.remove("small-circle-ani");
document.getElementById("bg-3").style.opacity = "1";
document.getElementById("circle3").classList.add("circle-ani");
document
.getElementById("small-circle3")
.classList.add("small-circle-ani");
count = 3;
setTimeout(() => {
runInterval();
});
} else if (count === 1) {
document.getElementById("bg-1").style.opacity = "0";
document.getElementById("circle1").classList.remove("circle-ani");
document
.getElementById("small-circle1")
.classList.remove("small-circle-ani");
document.getElementById("bg-2").style.opacity = "1";
document.getElementById("circle2").classList.add("circle-ani");
document
.getElementById("small-circle2")
.classList.add("small-circle-ani");
count = 2;
setTimeout(() => {
runInterval();
});
}
}
}
}
const Maincontainer = () => {
const dataFetchedRef = useRef(false);
useEffect(() => {
if (dataFetchedRef.current) return;
dataFetchedRef.current = true;
showAnimation();
}, []);
return (
<div id="nav-head">
<Image
layout="fill"
objectFit="cover"
src="/london.jpg"
className="bg"
id="bg-1"
/>
<Image
layout="fill"
objectFit="cover"
src="/rome.jpg"
className="bg"
id="bg-2"
/>
<Image
layout="fill"
objectFit="cover"
src="/paris.jpg"
className="bg"
id="bg-3"
/>
<div className="nav-head-container">
<SideBar />
<Navbar />
<Header />
<div className="circle-list">
<div className="circle" id="circle1">
<div className="small-circle" id="small-circle1"></div>
</div>
<div className="circle circle-ani" id="circle2">
<div
className="small-circle small-circle-ani"
id="small-circle2"
></div>
</div>
<div className="circle" id="circle3">
<div className="small-circle" id="small-circle3"></div>
</div>
</div>
<FaAngleLeft
className="left-arrow"
id="left"
color="#fff"
fontSize={20}
/>
<FaAngleRight
className="right-arrow"
id="right"
color="#fff"
fontSize={20}
/>
</div>
</div>
);
};
export default Maincontainer;
/* BookHoliday.js */
import React, { useState } from "react";
import Datetime from "react-datetime";
import "react-datetime/css/react-datetime.css";
import { AiFillCalendar, AiOutlineSearch } from "react-icons/ai";
import moment from "moment";
const BookHoliday = () => {
var yesterday = moment().subtract(1, "day");
const [arrivalDate, setArrivalDate] = useState(null);
const [departureDate, setDepartureDate] = useState(null);
var Arrivalvalid = function (current) {
return current.isAfter(yesterday);
};
var Departurevalid = function (current) {
if (arrivalDate !== null) {
return current >= arrivalDate;
} else {
return current.isAfter(yesterday);
}
};
return (
<div className="book-holiday">
<h2>Book Holiday Now!</h2>
<form className="form-container">
<div className="input-container">
<input
type="search"
name="search"
id="search"
placeholder="Search Your Destination"
/>
<div className="icon" id="search-icon">
{" "}
<AiOutlineSearch color="#bd7457" fontSize={20} />
</div>
</div>
<div className="input-container">
<Datetime
timeFormat={false}
dateFormat="DD MMM YYYY"
isValidDate={Arrivalvalid}
value={arrivalDate}
onChange={(e) => {
setArrivalDate(e);
if (departureDate !== null && e > departureDate) {
setDepartureDate(e);
}
}}
inputProps={{ placeholder: "Arrival", readOnly: true }}
/>{" "}
<div className="icon pointer" id="a-icon">
{" "}
<AiFillCalendar color="#bd7457" fontSize={20} />
</div>
</div>
<div className="input-container">
<Datetime
timeFormat={false}
dateFormat="DD MMM YYYY"
isValidDate={Departurevalid}
value={departureDate}
onChange={(e) => {
setDepartureDate(e);
}}
inputProps={{ placeholder: "Departure", readOnly: true }}
/>{" "}
<div className="icon pointer" id="d-icon">
{" "}
<AiFillCalendar color="#bd7457" fontSize={20} />
</div>
</div>
<button id="search-btn">Search</button>
</form>
</div>
);
};
export default BookHoliday;
/* globals.css */
#import url("https://fonts.googleapis.com/css2?family=Ubuntu&display=swap");
#import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");
#import url("https://fonts.googleapis.com/css2?family=Lobster&family=Ubuntu&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
font-family: "Montserrat";
}
#nav-head {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.nav-head-container {
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
width: 100%;
height: 100%;
}
#bg-1,
#bg-3 {
opacity: 0;
}
.bg {
transition: 0.6s;
}
.left-arrow {
position: absolute;
left: 10px;
top: 50%;
border: 1px solid white;
border-radius: 4px;
cursor: pointer;
}
.right-arrow {
position: absolute;
right: 10px;
top: 50%;
border: 1px solid white;
border-radius: 4px;
cursor: pointer;
}
.circle-list {
position: absolute;
bottom: 10px;
left: 0;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.circle {
width: 20px;
height: 20px;
border-radius: 20px;
background-color: gray;
opacity: 0.5;
margin: 0px 10px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.circle-ani {
border: 2px solid white;
background-color: transparent;
opacity: 1;
}
.small-circle {
width: 6px;
height: 6px;
border-radius: 6px;
}
.small-circle-ani {
background-color: white;
}
.navbar {
height: 75px;
display: flex;
justify-content: center;
align-items: center;
}
.logo {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.navbar .navlink {
display: flex;
flex: 4;
justify-content: space-evenly;
align-items: center;
}
.link {
text-decoration: none;
color: white;
transition: 0.6s;
}
.navlink li {
list-style: none;
}
.cta {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
}
.cta-button {
border: none;
background-color: transparent;
color: white;
cursor: pointer;
padding: 10px;
border-bottom: 1px solid white;
transition: 0.6s;
}
#ham {
position: relative;
display: none;
height: 24px;
width: 24px;
margin-left: 10px;
cursor: pointer;
}
#header {
width: 100%;
height: calc(100vh - 75px);
display: flex;
color: white;
flex-direction: column;
justify-content: center;
}
#header h2 {
font-size: 4rem;
padding: 0px 10% 10px;
}
#header p {
padding: 0px 10% 20px;
line-height: 25px;
}
#header-btn {
padding: 10px 20px;
background-color: #bd7457;
color: white;
border: 1px solid #bd7457;
width: 180px;
margin-left: 10%;
border-radius: 6px;
transition: 0.6s;
}
#sidebar {
position: fixed;
bottom: 0;
left: 0;
width: 200px;
height: 100%;
background-color: black;
color: white;
z-index: 5;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
transform: translateX(-200px);
transition: 0.6s;
}
#cross {
position: absolute;
right: 10px;
top: 10px;
width: 14px;
height: 14px;
cursor: pointer;
}
.sidelink {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
width: 100%;
height: 226px;
}
.sidelink .link {
font-size: 1.4rem;
}
.side-cta {
height: 56px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
#side-button {
padding: 10px 20px;
border: none;
background-color: transparent;
border: 1px solid white;
border-radius: 6px;
cursor: pointer;
color: white;
transition: 0.6s;
}
.book-holiday {
background-color: rgb(245, 245, 245);
padding: 30px 0px;
max-height: 9999px;
}
.book-holiday h2 {
font-size: 2rem;
text-align: center;
margin-bottom: 20px;
}
.form-control,
#search {
width: 250px;
padding: 10px 20px;
outline: none;
}
.form-container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#search-btn {
background-color: #bd7457;
border: 1px solid #bd7457;
color: white;
padding: 10px 20px;
transition: 0.6s;
margin: 10px 0px 20px;
}
.input-container {
display: flex;
position: relative;
margin: 10px 0px;
}
.icon {
position: absolute;
right: 0px;
top: 0px;
padding: 7px 10px;
}
.test {
background-color: rgb(255, 235, 205);
padding: 30px 0px;
max-height: 9999px;
}
.test h2 {
margin-bottom: 20px;
text-align: center;
font-size: 2rem;
}
/* This is for react date-time library */
.rdtDay {
color: #bd7457 !important;
}
.rdtDisabled {
color: #999999 !important;
}
.rdtOld {
color: #999999 !important;
}
.rdtNew {
color: black !important;
}
.rdtActive,
.rdtActive:hover {
background-color: #bd7457 !important;
color: white !important;
}
.rdtPicker td.rdtToday:before {
border-bottom-color: #bd7457 !important;
}
#media (hover: hover) {
.cta-button:hover {
border-color: #bd7457;
color: #bd7457;
}
.navlink li .link:hover {
color: #bd7457;
}
#side-button:hover {
color: #bd7457;
border-color: #bd7457;
}
#header-btn:hover,
#search-btn:hover {
border: 1px solid #bd7457;
background-color: transparent;
color: #bd7457;
}
}
#media (hover: none) {
.cta-button:active {
border-bottom: none;
color: #bd7457;
}
.navlink li .link:active {
color: #bd7457;
}
#side-button:active {
color: #bd7457;
border-color: #bd7457;
}
#header-btn:active,
#search-btn:active {
border: 1px solid #bd7457;
color: #bd7457;
background-color: transparent;
}
}
#media (max-width: 768px) {
.logo {
justify-content: flex-end;
margin-right: 30px;
}
#ham {
display: flex;
}
.navbar .navlink,
.cta {
display: none;
}
.navbar {
height: 40px;
align-items: flex-end;
}
#header {
height: calc(100vh -40px);
}
#header h2 {
font-size: 3rem;
}
}
#media (max-width: 540px) {
#header h2 {
font-size: 2.6rem;
}
}
#media (max-height: 414px) {
.sidelink .link {
font-size: 1.2rem;
}
#header h2 {
font-size: 2.4rem;
padding-bottom: 5px;
}
#header p {
padding-bottom: 10px;
}
}
I have tried almost everything, earlier I thought it was because of changing the background images using setInterval or due to react-date-time library, so I made a static background image, removed that date-time library and even removed the background image, but it didn't solve the problem. I am able to click the text when it is invisible, but when i refresh the page it appears.
Please help, I'm just learning how to make Cards using react js. below is the script. when I run it, the position of the card that should be on the right side is still on the left.
how to get div.card to be on the right side?
What's wrong with my code?
1. Services.jsx
import React from 'react'
import './Services.css'
import HeartEmoji from "../../img/heartemoji.png";
import Glasses from "../../img/glasses.png";
import Humble from "../../img/humble.png";
import Resume from './resume.pdf';
import Card from '../Card/Card';
import { themeContext } from '../../Context';
import { useContext } from 'react';
import { motion } from 'framer-motion';
const Services = () => {
const transition = {duration : 2, type: 'spring'}
const theme = useContext(themeContext);
const darkMode = theme.state.darkMode;
return (
<div className="services" id='Services'>
{/* left side */}
<div className="awesome">
<span style={{color: darkMode? 'white': ''}}>My Awesome</span>
<span>services</span>
<spane>
Lorem ispum is simpley dumy text of printing of printing Lorem
<br />
ispum is simpley dummy text of printing
</spane>
<a href={Resume} download>
<button className="button s-button">Download CV</button>
</a>
<div className="blur s-blur1" style={{ background: "#ABF1FF94" }}></div>
</div>
{/* right side */}
<div className="cards">
{/* first card */}
<motion.div
whileInView={{left: '14rem'}}
initial={{left: '25rem'}}
transition={transition}
style={{left: '14rem'}}
>
<Card
emoji = {HeartEmoji}
heading = {'Design'}
detail = {"Figma, Sketch, Photoshop, Adobe, Adobe xd"}
/>
</motion.div>
{/* second card */}
<motion.div
whileInView={{left: '14rem'}}
initial={{left: '25rem'}}
transition={transition}
style={{ top: "54rem", left: "10rem" }}
>
<Card
emoji={Glasses}
heading={"Developer"}
detail={"Html, Css, JavaScript, React"}
/>
</motion.div>
{/* 3rd card */}
<motion.div
whileInView={{left: '14rem'}}
initial={{left: '25rem'}}
transition={transition}
style={{ top: "60rem", left: "14rem" }}
>
<Card
emoji={Humble}
heading={"UI/UX"}
detail={
"Lorem ispum dummy text are usually use in section where baalabalalala thank you"
}
/>
</motion.div>
<div className="blur s-blur2" style={{ background: "var(--purple)"}}></div>
</div>
</div>
)
}
export default Services
2. Card.jsx
import React from 'react'
import './Card.css'
const Card = ({emoji, heading, detail}) => {
return (
<div className="card">
<img src={emoji} alt="" />
<span>{heading}</span>
<span>{detail}</span>
<button className="c-button">LEARN MORE</button>
</div>
)
}
export default Card
3. Services.css
.services {
padding: 0 3rem 0 3rem;
display: flex;
height: 90vh;
margin-bottom: 8rem;
margin-top: 9rem;
margin-bottom: 13rem;
}
.awesome{
display: flex;
flex-direction: column;
position: relative;
}
.awesome > :nth-child(1) {
color: var(--black);
font-size: 2.5rem;
font-weight: bold;
}
.awesome > :nth-child(2) {
color: var(--orange);
font-size: 2.5rem;
font-weight: bold;
}
.awesome > :nth-child(3) {
color: var(--gray);
font-size: 14px;
margin-top: 1rem;
}
.s-button{
width: 10rem;
height: 2.5rem;
margin-top: 1rem;
}
.cards>{
position: relative;
}
.cards>*{
position: absolute;
}
/* blur */
.s-blur2 {
left: 14rem;
top: 8rem;
}
.s-blur1 {
top: 13rem;
left: -18rem;
}
#media screen and (max-width: 480px) {
.services{
margin-top: 0;
flex-direction: column;
gap: 5rem;
height: 66rem;
padding: 0;
}
.cards{
display: flex;
flex-direction: column;
gap: 17rem;
}
.cards>*{
position: static;
}
}
4. Card.css
.card {
width: 10rem;
height: 13rem;
position: absolute;
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
width: 10rem;
text-align: center;
background: rgba(255, 255, 255, 0.26);
border: 7px solid var(--orangeCard);
box-shadow: var(--boxShadow);
border-radius: 20px;
padding: 0px 26px 2rem 26px;
}
.card span:nth-of-type(2) {
color: var(--gray);
font-size: 16px;
}
.card > img {
transform: scale(0.6);
margin-bottom: -2rem;
}
.c-button {
background: #ffffff;
box-shadow: 0px 19px 60px rgba(0, 0, 0, 0.08);
border-radius: 7px;
border: none;
padding: 10px;
font-size: 16px;
color: #5290FD;
}
#media screen and (max-width: 480px) {
.card{
width: auto;
}
}
i help you to solve the problem, first of all, you can use display flex on your parent and justify content between or evenly, in case of this the parent class is "services", so the code css for className="services" is :
.services {
padding: 0 3rem 0 3rem;
display: flex;
justify-content: evenly;
align-items: center;
height: 90vh;
margin-bottom: 8rem;
margin-top: 9rem;
margin-bottom: 13rem;
}
i hope this can help you :)
I developed a website using react js. But some pages don't work correctly. For example, the work page has to work like the below. When hovering the image, it has to changed the opacity and show the anchor tags (work page) :
But when I open the website for the first time, the hover effects and anchor tags are not visible. However, they are still clickable. It seems like this when I hover :
Finally, the page crashes after a while when I scroll through other pages and come back. First, elements fade and then disappear. At the end, I only get blank page. I also added how the crush pages look like (the Work and Skills pages):
But, when I refresh the website, it fixes again.
I get these errors:
Work.jsx file:
import React, { useState, useEffect } from 'react';
import { AiFillEye, AiFillGithub } from 'react-icons/ai';
import { motion } from 'framer-motion';
import { AppWrap, MotionWrap } from '../../wrapper';
import { urlFor, client } from '../../client';
import './Work.scss';
function Work() {
const [activeFilter, setActiveFilter] = useState('All');
const [animateCard, setAnimateCard] = useState({ y:0, opacity: 1 });
const [works, setWorks] = useState([]);
const [filterWork, setFilterWork] = useState([]);
useEffect(() => {
const query = '*[_type == "works"]'
client.fetch(query).then((data) => {
setWorks(data);
setFilterWork(data);
})
}, [])
const handleWorkFilter = (item) => {
setActiveFilter(item);
setAnimateCard([{ y:100, opacity:0 }])
setTimeout (() => {
setAnimateCard([{ y:0, opacity: 1}])
if(item === 'All') {
setFilterWork(works)
} else {
setFilterWork(works.filter((work) => work.tags.includes(item)))
}
},500)
}
return (
<>
<h2 className="head-text">MY PROJECTS</h2>
<div className='app__work-filter'>
{['UI/UX', 'REACT JS', 'HTML', 'JAVACRIPT', 'CSS', 'SCSS', 'ALL'].map((item, index) =>
<div
className={`app__work-filter-item app__flex p-text ${activeFilter === item ? "item-active" : ""}`}
key={index}
onClick={() => handleWorkFilter(item)}
>
{item}
</div>
)}
</div>
<motion.div
animate = {animateCard}
transition = {{ duration: 0.5, delayChildren: 0.5 }}
className = 'app__work-portfolio'
>
{filterWork.map((work, index) =>
<div className='app__work-item app__flex' key={index}>
<div className='app__work-img app__flex'>
<img src={urlFor(work.imgUrl)} alt={work.name} />
<motion.div
whileHover={{ opacity: [0,1]}}
transition={{ duration: 0.25, ease: 'easeInOut', staggerChildren: 0.5 }}
className='app__work-hover app__flex'
>
<a href={work.projectLink} target='_blank' rel='noreferrer'>
<motion.div
whileInView={{ scale: [0, 1]}}
whileHover={{ scale: [1, 0.9]}}
transition={{ duration: 0.25 }}
className='app__flex'
>
<AiFillEye />
</motion.div>
</a>
<a href={work.codeLink} target='_blank' rel='noreferrer'>
<motion.div
whileInView={{ scale: [0, 1]}}
whileHover={{ scale: [1, 0.9]}}
transition={{ duration: 0.25 }}
className='app__flex'
>
<AiFillGithub />
</motion.div>
</a>
</motion.div>
</div>
<div className='app__work-content app__flex'>
<h4 className='bold-text'>{work.title}</h4>
<p className='p-text-dark app__work-desc'>{work.description}</p>
<div className='app__work-tag app__flex'>
<p className='p-text-dark'>{work.tags[0]}</p>
</div>
</div>
</div>
)}
</motion.div>
</>
)
}
export default AppWrap(
MotionWrap(Work, 'app__works'),
'work',
'app__lightbluebg'
);
Work.scss file:
.app__works {
flex: 1;
width: 100%;
flex-direction: column;
}
.app__work-filter {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin: 4rem 0 2rem;
.app__work-filter-item {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
background-color: var(--blue1-color);
font-weight: 800;
cursor: pointer;
transition: all 0.3s ease;
margin: 0.5rem;
&:hover {
background-color: var(--black-color);
color: #fff;
}
#media screen and (min-width: 2000px) {
padding: 1rem 2rem;
border-radius: 0.85rem;
}
}
.item-active {
background-color: var(--secondary-color);
color: #fff;
}
}
.app__work-portfolio {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.app__work-item{
width: 290px;
flex-direction: column;
margin: 2rem;
padding: 1rem;
border-radius: 0.5rem;
background-color: var(--blue1-color);
color: #000;
cursor: pointer;
transition: all 0.3s ease;
z-index: 0;
&:hover {
box-shadow: 0 0 25px rgba(0,0,0,0.2);
}
#media screen and (min-width: 2000px) {
width: 470px;
padding: 1.25rem;
border-radius: 0.75rem;
}
#media screen and (max-width: 300px) {
width: 100%;
margin: 1rem;
}
}
}
.app__work-img {
width: 100%;
height: 230px;
position: relative;
img {
width: 100%;
height: 100%;
border-radius: 0.5rem;
object-fit: cover;
}
#media screen and (min-width: 2000px) {
height: 350px;
}
}
.app__work-hover {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
border-radius: 0.5rem;
opacity: 0;
transition: all 0.3s ease;
div {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: rgba(0,0,0,0.5);
color: white;
margin: 1rem;
font-family: var(--font-base);
font-weight: 800;
cursor: pointer;
transition: all 0.3s ease;
svg {
width: 50%;
height: 50%;
color: var(--white-color);
}
}
}
.app__work-content {
padding: 0.5rem;
width: 100%;
position: relative;
flex-direction: column;
h4 {
margin-top: 1rem;
line-height: 1.5;
}
.app__work-desc {
margin-top: 10px;
height: 35px;
}
.app__work-tag {
position: absolute;
padding: 0.5rem 1rem;
border-radius: 10px;
background-color: var(--blue1-color);
top: -25px;
}
}
Skills.jsx file:
import React, { useState, useEffect } from 'react';
import ReactToolTip from 'react-tooltip';
import { motion } from 'framer-motion';
import { AppWrap, MotionWrap } from '../../wrapper';
import { urlFor, client } from '../../client';
import ReactDOM from "react-dom";
import './Skills.scss';
function Skills() {
const [skills, setSkills] = useState([])
const [experiences, setExperiences] = useState([])
useEffect(() => {
const query = '*[_type == "experiences"]';
const skillsQuery = '*[_type == "skills"]';
client.fetch(skillsQuery).then((data) => {
setSkills(data);
})
client.fetch(query).then((data) => {
setExperiences(data);
})
}, [])
return (
<>
<h2 className="head-text">SKILLS & EXPERIENCE</h2>
<div className='app__skills-container'>
<motion.div className='app__skills-list'>
{skills?.map((skill, index) => (
<motion.div
whileInView={{opacity: [0, 1]}}
transition={{duration: 0.5}}
className='app__skills-item app__flex'
key={skill.name}
>
<div className='app__flex' style={{ backgroundColor: skill.bgColor }}>
<img src={urlFor(skill.icon)} alt={skill.name}/>
</div>
<p className='p-text'>{skill.name}</p>
</motion.div>
))}
</motion.div>
<motion.div className='app__experiences-list'>
{experiences?.map((experience) => (
<motion.div
className='app__experiences-item'
key={experience.year}
>
<div className='app__experiences-year'>
<p className='bold-text'>{experience.year}</p>
</div>
<motion.div
className='app__experiences-works'
>
{experience.works.map((work) => (
<>
<motion.div
whileInView={{opacity: [0, 1]}}
transition={{duration: 0.5}}
className='app__experiences-work-item'
data-tip
data-for={work.name}
key={work.name}
>
<h4 className='bold-text'>{work.name}</h4>
<p className='p-text-dark'>{work.company}</p>
</motion.div>
<ReactToolTip
id = {work.name}
effect = 'solid'
arrowColor = '#fff'
className = 'skills-tooltip'
>
{work.desc}
</ReactToolTip>
</>
))}
</motion.div>
</motion.div>
))}
</motion.div>
</div>
</>
)
}
export default AppWrap(
MotionWrap(Skills, 'app__skills'),
'skills',
'app__darkbluebg'
);
Skills.scss file:
.app__skills {
flex: 1;
width: 100%;
flex-direction: column;
}
.app__skills-container {
width: 100%;
margin-top: 3rem;
display: flex;
flex-direction: row;
#media screen and (max-width: 900px) {
width: 100%;
flex-direction: column;
}
}
.app__skills-list {
flex: 1;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
margin-right: 5rem;
#media screen and (max-width: 900px) {
margin-right: 0;
justify-content: center;
align-items: center;
}
}
.app__skills-item {
flex-direction: column;
text-align: center;
margin: 1rem;
transition: all 0.3s ease-in-out;
div {
width: 90px;
height: 90px;
border-radius: 50%;
background-color: var(--blue1-color);
img {
width: 50%;
height: 50%;
}
&:hover {
box-shadow: 0 0 15px rgba(0,0,0,0.7);
}
}
#media screen and (min-width: 2000px) {
width: 150px;
height: 150px;
}
p {
font-weight: 500;
margin-top: 0.5rem;
}
#media screen and (min-width: 2000px) {
margin: 1rem 2rem;
p {
margin-top: 1rem;
}
}
}
.app__experiences-list {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
#media screen and (max-width: 900px) {
margin-top: 2rem;
}
}
.app__experiences-item {
width: 100%;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
margin: 1rem 0;
}
.app__experiences-works {
flex: 1;
.app__experiences-work-item {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
margin-bottom: 1rem;
cursor: pointer;
h4 {
font-weight: 500;
}
p {
font-size: 0.8rem;
margin-top: 5px;
}
}
}
.app__experiences-year {
margin-right: 2rem;
p {
font-weight: 800;
}
#media screen and (max-width: 450px) {
margin-right: 1rem;
}
}
.skills-tooltip {
max-width: 300px !important;
background-color: var(--white-color) !important;
box-shadow: 0 0 25px rgba(0, 0, 0, 0.1) !important;
border-radius: 5px !important;
padding: 1rem !important;
color: var(--gray-color) !important;
text-align: center !important;
line-height: 1.5 !important;
opacity: 1 !important;
#media screen and (min-width: 2000px) {
font-size: 1.75rem !important;
max-width: 500px !important;
line-height: 2 !important;
}
}
Appwrap.js file:
import { color } from '#mui/system';
import React from 'react';
import { NavigationDots, SocialMedia } from '../components';
const AppWrap = (Component, idName, classNames) => function HOC() {
return (
<div id={idName} className={`app__container ${classNames}`}>
<SocialMedia />
<div className='app__wrapper app__flex'>
<Component />
<div className='copyright'>
<p className='p-text'>#2022 AYGEN</p>
<p className='p-text'>All rights reserved</p>
</div>
</div>
<NavigationDots active={idName} />
</div>
)
}
export default AppWrap;
MotionWrap.js file:
import React from 'react';
import { motion } from 'framer-motion';
const MotionWrap = (Component, classNames) => function HOC() {
return (
<motion.div
whileInView={{ y: [100, 50, 0], opacity: [0, 0, 1] }}
transition={{ duration: 0.5 }}
className={`${classNames} app__flex`}
>
<Component />
</motion.div>
)
}
export default MotionWrap
I hope I can explain this clearly. Thanks in advance!
I am working on an audio player with Vue 3 and the Napster API.
Project details
I have made the vinyl spin with the help of a CSS keyframes-based animation and the isSpinning computed property.
I want the vinyl to stop spinning once the end of the current track is reached, which is why isSpinning has this "formula":
isSpinning() {
return this.isPlaying && !this.player.ended;
}
const musicApp = {
data() {
return {
player: new Audio(),
trackCount: 0,
tracks: [],
muted: false,
isPlaying: false
};
},
methods: {
async getTracks() {
try {
const response = await axios
.get(
"https://api.napster.com/v2.1/tracks/top?apikey=ZTk2YjY4MjMtMDAzYy00MTg4LWE2MjYtZDIzNjJmMmM0YTdm"
)
.catch((error) => {
console.log(error);
});
this.tracks = response;
this.tracks = response.data.tracks;
} catch (error) {
console.log(error);
}
},
nextTrack() {
if (this.trackCount < this.tracks.length - 1) {
this.trackCount++;
this.setPlayerSource();
this.playPause();
}
},
prevTrack() {
if (this.trackCount >= 1) {
this.trackCount--;
this.setPlayerSource();
this.playPause();
}
},
setPlayerSource() {
this.player.src = this.tracks[this.trackCount].previewURL;
},
playPause() {
if (this.player.paused) {
this.isPlaying = true;
this.player.play();
} else {
this.isPlaying = false;
this.player.pause();
}
},
toggleMute() {
this.player.muted = !this.player.muted;
this.muted = this.player.muted;
}
},
async created() {
await this.getTracks();
this.setPlayerSource();
},
computed: {
isSpinning() {
return this.isPlaying && !this.player.ended;
}
}
};
Vue.createApp(musicApp).mount("#audioPlayer");
html,
body {
margin: 0;
padding: 0;
font-size: 16px;
}
body * {
box-sizing: border-box;
font-family: "Montserrat", sans-serif;
}
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.player-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #2998ff;
background-image: linear-gradient(62deg, #2998ff 0%, #5966eb 100%);
}
#audioPlayer {
width: 300px;
height: 300px;
border-radius: 8px;
position: relative;
overflow: hidden;
background-color: #00ca81;
background-image: linear-gradient(160deg, #00ca81 0%, #ffffff 100%);
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
display: flex;
flex-direction: column;
align-items: center;
}
.volume {
color: #ff0057;
opacity: 0.9;
display: inline-block;
width: 20px;
font-size: 20px;
position: absolute;
top: 5px;
right: 6px;
cursor: pointer;
}
.album {
width: 100%;
flex: 1;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.album-items {
padding: 0 10px;
text-align: center;
}
.cover {
width: 150px;
height: 150px;
margin: auto;
box-shadow: 0px 5px 12px 0px rgba(0, 0, 0, 0.17);
border-radius: 50%;
background: url("https://w7.pngwing.com/pngs/710/955/png-transparent-vinyl-record-artwork-phonograph-record-compact-disc-lp-record-disc-jockey-symbol-miscellaneous-classical-music-sound.png") center top transparent;
background-size: cover;
}
.cover.spinning {
webkit-animation: spin 6s linear infinite;
/* Safari */
animation: spin 6s linear infinite;
}
.info {
width: 100%;
padding-top: 5px;
color: #000;
opacity: 0.85;
}
.info h1 {
font-size: 11px;
margin: 5px 0 0 0;
}
.info h2 {
font-size: 10px;
margin: 3px 0 0 0;
}
.to-bottom {
width: 100%;
margin-top: auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.track {
background-color: #ff0057;
opacity: 0.9;
height: 3px;
width: 100%;
}
.controls {
width: 150px;
display: flex;
height: 60px;
justify-content: space-between;
align-items: center;
}
.controls .navigate {
display: flex;
box-shadow: 1px 2px 7px 2px rgba(0, 0, 0, 0.09);
width: 33px;
height: 33px;
line-height: 1;
color: #ff0057;
cursor: pointer;
background: #fff;
opacity: 0.9;
border-radius: 50%;
text-align: center;
justify-content: center;
align-items: center;
}
.controls .navigate.disabled {
pointer-events: none;
color: #606060;
background-color: #f7f7f7;
}
.controls .navigate.navigate-play {
width: 38px;
height: 38px;
}
.navigate-play .fa-play {
margin-left: 3px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://unpkg.com/axios#0.22.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue#next"></script>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#300;500&display=swap" rel="stylesheet">
<div class="player-container">
<div id="audioPlayer">
<span class="volume" #click="toggleMute">
<i v-show="!muted" class="fa fa-volume-up"></i>
<i v-show="muted" class="fa fa-volume-off"></i>
</span>
<div class="album">
<div class="album-items">
<div class="cover" :class="{'spinning' : isSpinning}"></div>
<div class="info">
<h1>{{tracks[trackCount].name}}</h1>
<h2>{{tracks[trackCount].artistName}}</h2>
</div>
</div>
</div>
<div class="to-bottom">
<div class="track"></div>
<div class="controls">
<div class="navigate navigate-prev" :class="{'disabled' : trackCount == 0}" #click="prevTrack">
<i class="fa fa-step-backward"></i>
</div>
<div class="navigate navigate-play" #click="playPause">
<i v-show="!isPlaying" class="fa fa-play"></i>
<i v-show="isPlaying" class="fa fa-pause"></i>
</div>
<div class="navigate navigate-next" :class="{'disabled' : trackCount == tracks.length - 1}" #click="nextTrack">
<i class="fa fa-step-forward"></i>
</div>
</div>
</div>
</div>
</div>
The problem
But, to my surprise, the app is unaware of the fact that the value of this.player.ended has changed (or is supposed to).
What am I doing wrong?
An Audio object will not function in the same manner as normal JavaScript objects in Vue, as the internals that Vue uses to abstract away state change observation will not be maintained when the Audio object changes state. In other words, the thing that allows Vue to detect the Audio object switching from ended === false to ended === true won't work, preventing Vue from knowing that the component needs to be updated.
If you wish to observe a change in ended state, then you'll want to add a custom event listener to the object in your created hook to toggle the spinning state and simply remove the ended check:
const musicApp = {
data() {
return {
player: new Audio(),
trackCount: 0,
tracks: [],
muted: false,
isPlaying: false
};
},
methods: {
async getTracks() {
try {
const response = await axios
.get(
"https://api.napster.com/v2.1/tracks/top?apikey=ZTk2YjY4MjMtMDAzYy00MTg4LWE2MjYtZDIzNjJmMmM0YTdm"
)
.catch((error) => {
console.log(error);
});
this.tracks = response;
this.tracks = response.data.tracks;
} catch (error) {
console.log(error);
}
},
nextTrack() {
if (this.trackCount < this.tracks.length - 1) {
this.trackCount++;
this.setPlayerSource();
this.playPause();
}
},
prevTrack() {
if (this.trackCount >= 1) {
this.trackCount--;
this.setPlayerSource();
this.playPause();
}
},
setPlayerSource() {
this.player.src = this.tracks[this.trackCount].previewURL;
},
playPause() {
if (this.player.paused) {
this.isPlaying = true;
this.player.play();
} else {
this.isPlaying = false;
this.player.pause();
}
},
toggleMute() {
this.player.muted = !this.player.muted;
this.muted = this.player.muted;
}
},
async created() {
await this.getTracks();
this.setPlayerSource();
this.player.addEventListener('ended', () => {
this.isPlaying = false;
});
},
computed: {
isSpinning() {
return this.isPlaying;
}
}
};
Vue.createApp(musicApp).mount("#audioPlayer");
html,
body {
margin: 0;
padding: 0;
font-size: 16px;
}
body * {
box-sizing: border-box;
font-family: "Montserrat", sans-serif;
}
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.player-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #2998ff;
background-image: linear-gradient(62deg, #2998ff 0%, #5966eb 100%);
}
#audioPlayer {
width: 300px;
height: 300px;
border-radius: 8px;
position: relative;
overflow: hidden;
background-color: #00ca81;
background-image: linear-gradient(160deg, #00ca81 0%, #ffffff 100%);
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
display: flex;
flex-direction: column;
align-items: center;
}
.volume {
color: #ff0057;
opacity: 0.9;
display: inline-block;
width: 20px;
font-size: 20px;
position: absolute;
top: 5px;
right: 6px;
cursor: pointer;
}
.album {
width: 100%;
flex: 1;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.album-items {
padding: 0 10px;
text-align: center;
}
.cover {
width: 150px;
height: 150px;
margin: auto;
box-shadow: 0px 5px 12px 0px rgba(0, 0, 0, 0.17);
border-radius: 50%;
background: url("https://w7.pngwing.com/pngs/710/955/png-transparent-vinyl-record-artwork-phonograph-record-compact-disc-lp-record-disc-jockey-symbol-miscellaneous-classical-music-sound.png") center top transparent;
background-size: cover;
}
.cover.spinning {
webkit-animation: spin 6s linear infinite;
/* Safari */
animation: spin 6s linear infinite;
}
.info {
width: 100%;
padding-top: 5px;
color: #000;
opacity: 0.85;
}
.info h1 {
font-size: 11px;
margin: 5px 0 0 0;
}
.info h2 {
font-size: 10px;
margin: 3px 0 0 0;
}
.to-bottom {
width: 100%;
margin-top: auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.track {
background-color: #ff0057;
opacity: 0.9;
height: 3px;
width: 100%;
}
.controls {
width: 150px;
display: flex;
height: 60px;
justify-content: space-between;
align-items: center;
}
.controls .navigate {
display: flex;
box-shadow: 1px 2px 7px 2px rgba(0, 0, 0, 0.09);
width: 33px;
height: 33px;
line-height: 1;
color: #ff0057;
cursor: pointer;
background: #fff;
opacity: 0.9;
border-radius: 50%;
text-align: center;
justify-content: center;
align-items: center;
}
.controls .navigate.disabled {
pointer-events: none;
color: #606060;
background-color: #f7f7f7;
}
.controls .navigate.navigate-play {
width: 38px;
height: 38px;
}
.navigate-play .fa-play {
margin-left: 3px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://unpkg.com/axios#0.22.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue#next"></script>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#300;500&display=swap" rel="stylesheet">
<div class="player-container">
<div id="audioPlayer">
<span class="volume" #click="toggleMute">
<i v-show="!muted" class="fa fa-volume-up"></i>
<i v-show="muted" class="fa fa-volume-off"></i>
</span>
<div class="album">
<div class="album-items">
<div class="cover" :class="{'spinning' : isSpinning}"></div>
<div class="info">
<h1>{{tracks[trackCount].name}}</h1>
<h2>{{tracks[trackCount].artistName}}</h2>
</div>
</div>
</div>
<div class="to-bottom">
<div class="track"></div>
<div class="controls">
<div class="navigate navigate-prev" :class="{'disabled' : trackCount == 0}" #click="prevTrack">
<i class="fa fa-step-backward"></i>
</div>
<div class="navigate navigate-play" #click="playPause">
<i v-show="!isPlaying" class="fa fa-play"></i>
<i v-show="isPlaying" class="fa fa-pause"></i>
</div>
<div class="navigate navigate-next" :class="{'disabled' : trackCount == tracks.length - 1}" #click="nextTrack">
<i class="fa fa-step-forward"></i>
</div>
</div>
</div>
</div>
</div>
Try to add ended event instead
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement#events
const audioElement = new Audio('car_horn.wav');
audioElement.addEventListener('ended', () => {
this.isPlaying = false
})
when my component re-renders itself after setState(); it seems to set the wrong scale for the page and all the content seems to fall off the side, it looks like the HTML and CSS has got the wrong screen size, and therefore the images, text, and boxes don't fit the screen, this isn't an issue with my CSS breakpoints or anything but I don't understand what I need to do since i've never seen this before
Before re-render:
after re-render:
MoviesHome.js
constructor(props){
super(props)
this.state = {
slideUpClass: ['movieFullTabContainer', 'movieFullTabContainerClosed'],
isOpen: 0,
};
handleMovieClick = () => {
if(this.state.isOpen === 0){
this.setState({isOpen: 1});
}else{
this.setState({isOpen: 0});
}
}
...
<div className='rowsContainer'>
<div className='rowContent'>
{this.state.Trending != null ? <MoviesRow clickHandler={this.handleMovieClick} name={'For You'} index={0} movies={this.state.Trending}/> : ''}
{this.state.Trending != null ? <MoviesRow clickHandler={this.handleMovieClick} name={'Trending'} index={1} movies={this.state.Trending}/> : ''}
</div>
</div>
<MovieSlideUp clickHandler={this.handleMovieClick} slideupClass={this.state.slideUpClass[this.state.isOpen]}/>
MoviesRow.js
<div key={Math.random(0, 1000)} onClick={() => this.props.clickHandler()} className='sliderItem'>
<img className='sliderImg' src={`https://image.tmdb.org/t/p/w1280/${this.props.movies[i].poster_path}`} alt=''></img>
<div className='movieOverlayContainer'>
<div className='movieOverlayContainerContent'>
<p className='movieTitle'>{this.props.movies[i].title}</p>
<p>{this.props.movies[i].release_date.substring(0,4)}</p>
</div>
</div>
</div>
MovieFullTab.js
import CircleSVG from './SVG/Circle-Solid.svg';
import StarSVG from './SVG/Star-Solid.svg';
import HeartSVG from './SVG/Heart-Solid.svg';
import PlaySVG from './SVG/Play-Solid.svg';
...
<div id={this.props.slideupClass}>
<div onClick={() => this.props.clickHandler()} id='fullscreenTabContainer'>
<div id='fullscreenSurroundingContainer'>
<div id='fullscreenContent'>
<div id='movieInfoContainer'>
<div id='movieImageContainer'>
<img src='https://image.tmdb.org/t/p/w1280/jTswp6KyDYKtvC52GbHagrZbGvD.jpg'></img>
</div>
<div id='movieFullInfoContainer'>
<p id='movieFullInfoTitle'>Luca</p>
<p className='movieFullInfoText'>15</p>
<p className='movieFullInfoText'>2021</p>
<div id='fullGenreContainer'>
<p>Adventure</p>
<img alt='' className='seperator-side' src={CircleSVG}></img>
<p id='secondGenre'>Comedy</p>
</div>
<div id='movieFullRatingsContainer'>
<img id='featuredStarIcon' alt='' src={StarSVG}></img>
<p>8.6</p>
</div>
<div id='fullMovieInfoOverviewContainer'>
<p>Luca and his best friend Alberto experience an unforgettable summer on the Italian Riviera.
But all the fun is threatened by a deeply-held secret: they are sea monsters from another
world just below the water’s surface</p>
</div>
<div id='movieFullInfoButtonsContainer'>
<div id='movieFullInfoLikeButton'>
<img alt='' src={HeartSVG}></img>
</div>
<div id='movieFullInfoPlayButton'>
<p>Watch</p>
<img alt='' src={PlaySVG}></img>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
MoviesRow.css
.rowTopContainer{
display: flex;
align-items: baseline;
}
.ArrowButtonImage{
filter: invert(65%) sepia(5%) saturate(170%) hue-rotate(169deg) brightness(84%) contrast(82%);
}
.flippedArrow{
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
.buttonSlideContainer{
display: flex;
margin-left: auto;
}
.ButtonSlide:first-child{
margin-right: 35px;
}
.ButtonSlide{
width: 30px;
height: 25px;
cursor: pointer;
}
.movieRowTitleContainer{
margin-right: 20px;
}
.movieRowTitle{
color: white;
font-family: Bold;
font-size: 23px;
margin-bottom: 25px;
}
.viewAllButtonContainer {
cursor: pointer;
}
.viewAllButtonContainer:hover p {
text-decoration: underline;
}
.viewAllButtonContainer p {
color: white;
font-size: 0.9em;
}
.moviesRowSliderContainer{
display: flex;
overflow-x: hidden;
overflow: hidden;
width: 100%;
scroll-behavior: smooth;
}
.sliderItemContent:hover .movieOverlayContainer{
opacity: 1;
background-color: rgba(0, 0, 0, 0.61);
}
.sliderImg{
width: 100%;
height: 100%;
border-radius: 5px;
object-fit: cover;
}
.movieOverlayContainerContent{
position: relative;
top: 0;
left: 0;
text-align: center;
justify-content: flex-start;
display: flex;
flex-direction: column;
height: 90%;
width: 100%;
}
.movieOverlayContainerContent p:nth-child(2){
font-size: 1vw;
}
.movieTitle{
font-size: 1.4vw;
width: 80%;
margin-bottom: 5px;
margin: 0 auto;
margin-top: 5px;
font-family: Bold;
}
.movieShortInfoContainer{
margin-top: auto;
}
.movieShortInfoContent{
justify-content: center;
display: flex;
text-align: center;
margin-top: auto;
}
.movieShortInfoContent p:not(:first-child) {
/* margin-left: 15px; */
font-size: 0.9vw;
}
.movieShortInfoContent p:nth-child(3){
margin-left: 0;
}
.movieShortInfoContent p:nth-child(2){
margin-right: 15px;
}
.movieStarIcon{
height: 15px;
filter: invert(68%) sepia(95%) saturate(406%) hue-rotate(359deg) brightness(104%) contrast(88%);
}
.userRatingsContainer{
display: flex;
align-items: center;
}
.movieOverlayContainer {
position: absolute;
top: 0;
left: 0;
width: inherit;
height: inherit;
background-color: rgba(0, 0, 0, 0);
border-radius: 5px;
opacity: 0;
color: white;
transition: all 0.1s ease;
}
.sliderItem{
width: 19%;
height: auto;
flex:none;
position: relative;
}
.sliderItemContent{
height: 100%;
width: 80%;
cursor: pointer;
}
#media only screen and (max-width: 1400px) {
.sliderItem{
width: 18%;
}
}
#media only screen and (max-width: 650px) {
.sliderItem{
width: 38%;
}
.movieOverlayContainerContent p:nth-child(2){
font-size: 1.8vw;
}
}
#media only screen and (max-width: 550px) {
.movieTitle{
font-size: 3vw;
}
}
I Hope the code helps :)
It was simply the display: flex; container pushing the container, props to Drew Reese for helping resolve the issue... Thanks :)