Framer motion parallax effect - javascript

I'm trying to achieve a parallax effect similar to this one using framer-motion in my Next.js app:
https://www.nicyiallouris.com
This is my current ProjectCard component:
"use client";
import { asText } from "#prismicio/helpers";
import { motion, useScroll, useTransform } from "framer-motion";
import Image from "next/image";
import Link from "next/link";
import type { ProjectDocumentData } from "../../../.slicemachine/prismicio";
export const ProjectCard = ({
href,
project,
index,
}: {
href: string;
project: ProjectDocumentData;
index: number;
}) => {
const { scrollYProgress } = useScroll();
const y = useTransform(scrollYProgress, [0, 1], ["0%", `-${index * 10}%`]);
if (!project.cover.url) return null;
return (
<motion.div className="sticky top-0 flex min-h-[70vh] items-center justify-center overflow-hidden">
<Link
href={href}
aria-label={asText(project.title)}
className="absolute z-10"
>
<h3 className="relative border-b border-brand font-brand text-lg uppercase">
{asText(project.title)}
</h3>
</Link>
<Image
src={project.cover.url}
width={project.cover.widescreen.dimensions?.width}
height={project.cover.widescreen.dimensions?.height}
alt="Project Image"
className="absolute inset-0 h-full w-full object-cover"
placeholder="blur"
blurDataURL={`${project.cover.url}&blur=200`}
/>
</motion.div>
);
};
This isn't working though, the scroll effect is different, and the translate effect is pulling the project cards up above the footer. How can I get this done? Code is available here:
https://github.com/thejessewinton/ryan-spacone-www

Related

Focus state shouldn't change, React.JS + TailwindCSS

I have a question related to tailwindcss and React. I have a property that if a <NavItem /> is focused then the background and the text will change. <LanguageSwitcher /> is another component, and if it is focused, I want it to not change focus state of other items in navbar. <LanguageSwitcher /> doesn't affect URL.
Here's my code for item in navigation bar and images of how <LanguageSwitcher /> affects focus state of other items:
import React from "react";
import { Link } from "react-router-dom";
interface Props {
title: string;
url: string;
icon: JSX.Element;
}
const NavItem: React.FC<Props> = ({ title, url, icon }) => {
//https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-classes
return (
<Link
to={url}
className="text-center items-center flex-col justify-center font-medium px-1 text-white capitalize hover:font-semibold select-none group"
>
<div className="flex items-center justify-center mb-1 rounded-3xl px-2 py-1 group-hover:bg-btnHover group-focus:bg-btnActive group-focus:text-textActive transition-colors duration-75">
{icon}
</div>
<span>{title}</span>
</Link>
);
};
export default NavItem;
Is it possible? If so, how can I do it, maybe with useLocation from react-router-dom or directly with tailwindcss?
"Focus" generally means the UI element the user can currently interact with. I think you are conflating "focus state" with "active state". I'm guessing you want the Link to remain "active" while other UI elements have, or might not have, "focus", and are being interacted with. Switch to using the NavLink component and conditionally apply the "active" state CSS classname.
Here's an example*:
import React from "react";
import { NavLink } from "react-router-dom";
interface Props {
title: string;
url: string;
icon: JSX.Element;
}
const NavItem: React.FC<Props> = ({ title, url, icon }) => {
//https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-classes
return (
<NavLink
to={url}
className="text-center items-center flex-col justify-center font-medium px-1 text-white capitalize hover:font-semibold select-none group"
>
{({ isActive }: { isActive: boolean }) => (
<>
<div
className={
[
"flex items-center justify-center mb-1 rounded-3xl px-2 py-1 group-hover:bg-btnHover transition-colors duration-75"
isActive ? "group-focus:bg-btnActive group-focus:text-textActive" : null
]
.filter(Boolean)
.join(" ")
}
>
{icon}
</div>
<span>{title}</span>
</>
)}
</NavLink>
);
};
export default NavItem;
*Note: I've just guessed/plucked the CSS classnames that looked like they were related to the "focus/active" CSS styling, you will want to double-check the actual classes in your implementation.

Google OAuth not directing to home page in react

I am setting up a login page using google OAuth in react, I am following a youtube tutorial, everything seems to work fine but somehow after logging in, I am not being redirected to my homepage. here is the code (Login.jsx):
import React from 'react'
import GoogleLogin from 'react-google-login';
import { useNavigate } from 'react-router-dom';
import { FcGoogle } from 'react-icons/fc';
import carVideo from '../assets/car.mp4';
import logo from '../assets/speedograph white.png';
import { client } from '../client';
const Login = () => {
const navigate = useNavigate();
const responseGoogle = (response) => {
localStorage.setItem('user', JSON.stringify(response.profileObj));
if (response.profileObj) {
const { name, googleId, imageUrl } = response.profileObj;
const doc = {
_id: googleId,
_type: 'user',
userName: name,
image: imageUrl,
};
client.createIfNotExists(doc).then(() => {
navigate('/', { replace: true });
});
}
};
return (
<div className = "flex justify-start items-center flex-col h-screen">
<div className='relative w-full h-full'>
<video
src={carVideo}
type='video/mp4'
loop
controls={false}
muted
autoPlay
className='w-full h-full object-cover'
/>
<div className = "absolute flex flex-col justify-center items-center top-0 right-0 left-0 bottom-0 bg-blackOverlay">
<div className="p-5 ml-3">
<img src={logo} width="130px" alt="logo" />
</div>
<div className='shadow-2xl'>
<GoogleLogin
clientId={process.env.REACT_APP_GOOGLE_API_TOKEN}
render={(renderProps) => (
<button
type='button'
className='bg-white flex justify-center items-center p-3 rounded-lg cursor-pointer outline-none'
onClick={renderProps.onClick}
disabled={renderProps.disabled}
>
<FcGoogle className='mr-4' />Sign in with Google
</button>
)}
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy="single_host_origin"
/>
</div>
</div>
</div>
</div>
)
}
export default Login
I think the problem is due to the if condition, but I added it after reviewing a Stackoverflow tab that suggested adding it as a null check, before adding it I was getting the error:
Cannot destructure property 'name' of 'response.profileObj'
now the error is gone but it is not redirecting me to the home page (neither did it do so before the error). So where am I missing in my code exactly?

Fixed Left- 0 (TailwindCss) overlaping body content

i have an issue on my project i'am working on, i have a SIDEBAR and a TOPHEADER(NAVBAR).., now the issue starts when i want to have a FIXED SIDEBAR without it obscuring other page elements like TopHeader/Navbar and body content to the left side of the page.. tried adding ml-20 on topHeader div but that didnt help as it just opens up a whitespace on the left,,also tried using Space-x-20 class that also didnt help because it only pushed the body content to the right just like iwanted but theres another issue , the TopHeader is stuck on the left ..on this project iam using Tailwindcss to style the project would appreciate the help.
This is how it looks like with the "Fixed left-0 "
enter image description here
enter image description here
How I want it to look: enter image description here
enter image description here
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { HiMenuAlt3 } from "react-icons/hi";
import { AiFillHome, AiOutlinePoweroff } from "react-icons/ai";
import { FiPlay } from "react-icons/fi";
import {
BsDisplay,
BsQuestionCircle,
BsTrophy,
BsTwitter,
} from "react-icons/bs";
import { MdOutlineGames } from "react-icons/md";
import { SiDiscord } from "react-icons/si";
import { BiNews } from "react-icons/bi";
import { TopHeader } from "../../components/TopHeader";
export const Sidebar = ({ children }) => {
const menus = [
{ name: "Home", link: "/", icon: AiFillHome },
{ name: "Play", link: "/", icon: FiPlay },
{ name: "Watch", link: "/", icon: BsDisplay },
{ name: "Leaderboard", link: "/", icon: BsTrophy, margin: true },
{ name: "Games", link: "/", icon: MdOutlineGames },
{ name: "News", link: "/", icon: BiNews },
{ name: "F.a.q", link: "/", icon: BsQuestionCircle, margin: true },
{ name: "Logout", link: "/", icon: AiOutlinePoweroff },
{ name: "Discord", link: "/", icon: SiDiscord, margin: true },
{ name: "Twitter", link: "/", icon: BsTwitter },
];
const [open, setOpen] = useState(true);
return (
<section className="flex">
<div
className={`fixed left-0 bg-black min-h-screen ${
open ? "w-72" : "w-16"
} duration-500 text-white px-4`}
>
<div className="py-3 flex justify-end">
<HiMenuAlt3
size={26}
className="cursor-pointer"
onClick={() => setOpen(!open)}
/>
</div>
<div className="mt-4 flex flex-col gap-4 relative">
{menus?.map((menu, i) => (
<Link
to={menu?.link}
key={i}
className={`${
menu?.margin && "mt-5"
} flex items-center text-sm gap-3.5 font-medium p-2 hover:bg-indigo-600 rounded-md`}
>
<div>{React.createElement(menu?.icon, { size: "20" })}</div>
<h2
style={{
transitionDelay: `${i + 3}00ms`,
}}
className={`whitespace-pre duration-500 ${
!open && "opacity-0 translate-x-28 overflow-hidden"
}`}
>
{menu?.name}
</h2>
</Link>
))}
</div>
</div>
<div className="bg-gray-800 w-full p-3">
<>
<TopHeader />
{children}
</>
</div>
</section>
);
};
import React from "react";
import { AiOutlineSearch } from "react-icons/ai";
import { BiUserCircle } from "react-icons/bi";
import { HiOutlineFlag } from "react-icons/hi";
import { IoMdNotificationsOutline } from "react-icons/io";
import "tw-elements";
export const TopHeader = () => {
return (
<div className="max-w-auto mx-auto px-4 mb-5 bg-black text-white">
<div className=" flex justify-between">
<div className="flex space-x-52">
{/*Logo*/}
<div>
<h1 className="flex items-center py-4 px-2 font-semibold">LOGO</h1>
</div>
{/* Search Input */}
<div className="hidden md:flex items-center space-x-1">
<div className="bg-gray-300 text-white rounded-full flex items-center px-2">
<AiOutlineSearch size={20} />
<input
className="bg-gray-300 p-2 rounded-full focus:outline-none"
type="text"
placeholder="Search Games"
/>
</div>
</div>
<div className="flex items-center space-x-3">
{/* Notification Button */}
{/*<button className="py-2 px-2 text-white">
<IoMdNotificationsOutline size={30} />
</button> */}
{/* RightSidebar Button */}
<button className="py-2 px-2 text-white">
<HiOutlineFlag size={30} />
</button>
{/* User Button*/}
<button className="py-2 px-2 text-white">
<BiUserCircle size={30} />
</button>
</div>
</div>
</div>
</div>
);
};
i finally found a good fix for my issue i had above , instead of using tailwind default " fixed left-0 " , i ended up using StickyNode and it kind of solved every bit of problems i had by wrapping my sidebar with stickynode component like this:
<Sticky>
<Sidebar />
</Sticky>

How to hide a custom toast notification with Tailwind css and react

Im working on a custom toast notification. But the hard part to me is I've not been able to hide the toast notification correctly. When I make a click to show it the toast has an animation to the left the problem is when the toast is gonna hide just disapear and it does not slide to the right. Im working with react and tailwind css. Here is the code. also leave a link to the case. https://codesandbox.io/s/toast-notification-ucx2v?file=/src/components/toastNotification.jsx
I hope you can help me guys.
-----App component-----
import { useEffect, useState } from "react";
import ToastNotification from "./components/toastNotification";
import "./styles.css";
export default function App() {
const [showToast, setShowToast] = useState(false);
const addToCart = () => {
setShowToast(true);
};
useEffect(() => {
setTimeout(() => {
setShowToast(false);
}, 3000);
}, [showToast]);
return (
<div className="App">
<ToastNotification showNotification={showToast} />
<button
className="w-1/2 p-2 flex items-center justify-center rounded-md bg-indigo-400 text-white"
type="submit"
onClick={addToCart}
>
Add to cart
</button>
</div>
);
}
-----Toast component-----
import React, { useEffect, useState } from "react";
const ToastNotification = ({ showNotification }) => {
useEffect(() => {
setTimeout(() => {}, 5000);
}, []);
return (
<>
{showNotification === false ? null : (
<div className="static z-20">
<div
className={`${
showNotification
? "animate__animated animate__slideInRight absolute top-16 right-4 flex items-center text-white max-w-sm w-full bg-green-400 shadow-md rounded-lg overflow-hidden mx-auto"
: "animate__animated animate__slideOutRight absolute top-16 right-4 flex items-center text-white max-w-sm w-full bg-green-400 shadow-md rounded-lg mx-auto"
}`}
>
<div class="w-10 border-r px-2">
<i class="far fa-check-circle"></i>
</div>
<div class="flex items-center px-2 py-3">
<div class="mx-3">
<p>add to car</p>
</div>
</div>
</div>
</div>
)}
</>
);
};
export default ToastNotification;

Looping through array within Sanity Io React

I'm using react with sanity io to create a portfolio page. I would like to create an unordered list according to how many tags I have a on a project. A project is composed of a title, image, description, and tags(this is just an array).
What I have tried is:
{project.tags.map(type => {
return (
<li>{type.type.name}</li>
)
})}
And I keep getting the error: "TypeError: project.forEach is not a function". If I just render
{project.tags}
all of the tags are displayed but then I can't style them hence the need to put them into a list.
Does anyone know how to accomplish this?
import React, { useEffect, useState} from "react";
import sanityClient from "../client.js";
import '../index.css';
export default function Project() {
const [projectData, setProjectData] = useState(null);
useEffect(() => {
sanityClient.fetch(`*[_type == "project"] | order(index) {
title,
mainImage{
asset->{
_id,
url
},
},
description,
projectType,
link,
tags
}`).then((data) => setProjectData(data)).catch(console.error);
}, []);
return (
<div className="antialiased text-gray-800 bg-gray-400">
<div className="container relative flex flex-col px-6 mx-auto space-y-8">
<div className="absolute inset-0 z-0 w-2 h-full bg-white shadow-md left-38 md:mx-auto md:right-0 md:left-0"></div>
{projectData && projectData.map((project, index)=> (
<div className="relative z-10 p-10 ">
<img src={project.mainImage.asset.url} alt={project.mainImage.alt} className="timeline-img" />
<div className={`${index % 2 === 0 ? "timeline-container-left timeline-container" : "timeline-container" }`} >
<p className="font-bold uppercase">{project.title}</p>
<div className={`${index % 2 === 0 ? "timeline-pointer-left timeline-pointer" : "timeline-pointer" }`} aria-hidden="true"></div>
<div className="p-6 bg-white rounded-md shadow-md sm:p-2">
<p className="pt-1">{project.description}</p>
</div>
</div>
</div>
))}
</div>
</div>
)
}
{project.tags.map( type => ( {type} ))} is the answer.

Categories