I would like to make the transition smoother when selecting states between the left arrow & right arrow.
App.js
import React from "react";
import { useState } from "react";
import { GoArrowLeft, GoArrowRight } from "react-icons/go";
const ExampleMenu = () => {
const [showtab, setTab] = useState(false);
const handleTab = () => {
setTab(!showtab);
};
return (
<div className='flex justify-between text-white items-center bg-slate-800 mx-auto h-24'>
<h3 className='md:text-3xl z-10 pl-4 w-full sm:text-xl text-slate-300 font-bold '>LOGO</h3>
<div onClick={handleTab} className='hidden md:block animate-pulse pr-4'>
{!showtab ? <GoArrowLeft size={40}/> : <GoArrowRight size={40}/>}
</div>
<div onClick={handleTab}>
{!showtab ? <class className='hidden' /> :
<ul className='hidden md:flex p-4 space-x-2'>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>}
</div>
</div>
);
};
export default ExampleMenu;
Live Example - Tailwind isn't working as it should on here, but if you c+p the code into VSC you'll see it better.
When the left arrow is clicked, the menu will open slower & smoother, same for the right arrow. That is the goal i am trying to accomplish. Thank you in advance!
Dependencies:
npm install react-icons
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
I recommend using React Transition Group since they make react transitions much easier, I've also made a sample here
import { CSSTransition } from "react-transition-group";
...
return (
...
<CSSTransition
in={showtab}
timeout={300}
classNames="tab"
unmountOnExit
>
<ul className="md:flex p-4 space-x-2">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</CSSTransition>
</div>
);
...
Related
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
I am using react.js and the problem that I am having is that the images wont load in npm run preview even though I included them in the public folder, reconfigured the image paths, and they are included in the assets folder in the dist folder. all of the images are showing on the local preview of the website
This is how it looks like
these are my paths for my images in the assets folder
export default [
{
title: "Flaco Ramirez Boxing Website",
imgUrl: "/assets/frb.png",
stack: ["Typescript", "React", "Tailwind", "Vite"],
link: "",
},
{
title: "Portfolio Website ",
imgUrl: "/assets/portfolio.jpeg",
stack: ["Javascript", "React", "Tailwind", "Vite"],
link: "",
},
{
title: "Discord Bot ",
imgUrl: "/assets/discord.png",
stack: ["Python", "Discord.py"],
link: "",
},
];
in PortfolioItem.jsx
import React from 'react';
export function PortfolioItem({ title, imgUrl, stack, link }) {
return (
<a
href={link}
target="_blank"
rel="noopener noreferrer"
className="border-2 border-stone-900 dark:border-white rounded-md overflow-hidden"
>
<img
src={imgUrl}
alt="portfolio"
className="w-full h-36 md:h-48 object-cover cursor-pointer"
/>
<div className="w-full p-4">
<h3 className="text-lg md:text-xl dark:text-white mb-2 md:mb-3 font-semibold ">{title}</h3>
<p className="flex flex-wrap gap-2 flex-row items-center justify-start text-xs md:text-sm dark:text-white ">
{stack.map(item => (
<span className="inline-block px-2 py-1 font-semibold border-2 border-stone-900 dark:border-white rounded-md">
{item}
</span>
))}
</p>
</div>
</a>
)
}
export default PortfolioItem;
in Portfolio.jsx
import React from "react";
import porfolio from "../data/porfolio";
import PortfolioItem from "./PortfolioItem";
export function Portfolio() {
return (
<div className="flex flex-col md:flex-row items-center justify-center">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{porfolio.map((project) => (
<PortfolioItem
imgUrl={project.imgUrl}
title={project.title}
stack={project.stack}
link={project.link}
/>
))}
</div>
</div>
);
}
export default Portfolio;
Vite's preview task doesn't run a new build. It just serves the dist folder as-is.
If you want to always see the latest build via preview, I suggest you add a pre-script in package.json...
"scripts": {
...
👉 "prepreview": "npm run build", 👈
"preview": "vite preview"
},
I want to display an array once a button is clicked. By default it is invisible. Just like in drop-downs in menu bars. I'm using group and group-focus. The array is getting invisible but on button click it's not reappearing!
<div className="group">
<button className="pointer-events-auto">Ingredients</button>
<ul className="invisible group-focus:visible grid sm:grid-cols-3 text-justify sm:text-sm text-xs grid-cols-2 gap-x-3 gap-y-1 list-decimal list-inside">
{menu.ingredients.map(item => <li className="" key={item}>{ item }</li>)}
</ul>
</div>
I've set the visibility for group-focus in next.config.js but still it's not working:
module.exports = {
...,
variants: {
extend: {
backgroundColor: ['group-focus'],
visibility: ['hover', 'focus', 'group-focus'],
},
},
plugins: [],
}
import React, { useState } from 'react'
function component() {
const [show, setShow] = useState(false)
const handleShow = () => {
(show ? setShow(false) : setShow(true))
}
return (
<div>
<div className="group">
<button onClick={handleShow} className="pointer-events-auto">Ingredients</button>
<div className={show ? "block" : "hidden"}>
<ul className="invisible group-focus:visible grid sm:grid-cols-3 text-justify sm:text-sm text-xs grid-cols-2 gap-x-3 gap-y-1 list-decimal list-inside">
{menu.ingredients.map(item => <li className="" key={item}>{item}</li>)}
</ul>
</div>
</div>
</div>
)
}
export default component
This will work fine.
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.
The stack for my project is GatsbyJS, TypeScript, Twin Macro (TailwindCSS), and Emotion.
In my styles.tsx file, I style and define my navbar button like this:
import React, {FC} from 'react'
import tw, {styled} from 'twin.macro'
export type ButtonComponentProps = {
children?: any,
onClick?: (e?: React.MouseEvent) => void
} & React.ButtonHTMLAttributes<HTMLButtonElement>
const ThisButton = ({onClick, children, ...rest}: ButtonComponentProps) =>
<button onClick={onClick} {...rest}>{children}</button>
export const NavButton = tw(ThisButton)`
text-black cursor-pointer text-xl leading-none px-3 py-1 border border-solid
border-transparent rounded bg-transparent block lg:hidden outline-none
focus:outline-none
`
Now my markup file, index.tsx looks like this:
import React, {useState} from 'react'
import {faBars} from '#fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '#fortawesome/react-fontawesome'
import {Nav, InnerNav, InnerMost, DropDown, Logo, NavButton,
DropMenu, ListItem, InnerItem, ExtraButton
} from './styles'
import {StaticImage} from 'gatsby-plugin-image'
const Navbar = () => {
const [navbarOpen, setNavbarOpen] = useState(false)
return (
<>
<Nav>
<InnerNav>
<InnerMost>
<Logo href="/">
<StaticImage
src="../../images/logo.png"
alt="Company logo"
width={180}
placeholder="blurred"
/>
</Logo>
<NavButton
type="button"
onClick={() => setNavbarOpen(!navbarOpen)}
>
<FontAwesomeIcon icon={faBars} />
</NavButton>
</InnerMost>
...
}
export default Navbar
What's so weird is that it works splendidly in development mode. But when I run gatsby build or deploy it, it doesn't work. Now if you're thinking the problem is FontAwesome, it's not. I replaced it, ran the build again and it still didn't work. I looked in my browser dev tools and everything looked fine until I saw the Events Listeners section. In development, all the event listeners you could think of, such as click, close, load, mouseover, etc. are there. However, in production, only load is there.
Can anyone help me, please!