Impulsive
In a world which is ever so hungry for dopamine, this interface aims to exploit one of the most impulsive human traits - shopping. In the form of a fluid concept that tiktok-ifys the shopping experience, miles away from whatever the hell Amazon UI has been for decades.
Also accompanied by some old freinds from Buttons.
Gist
Impulsive is meant to be a @laurentdelrey's "ship to friends" concept brought-to-life for personaly satisfaction. This component tries to demonstrate a more personalized, quality-driven, addictive, seamless, and carefully curated shopping flow.
Conveyed by some of my guilty wishlist items:)
Code
npm i framer-motion react-epic-spinners
/components/lab/Impulsive/impulsive.js
"use client"import React, { useState } from "react"import Image from "next/image"import { motion } from "framer-motion"import gucci from "@/assests/images/gucci.jpg"import zara from "@/assests/images/zara.jpg"import mokka2 from "@/assests/images/mokka.jpg"import flow from "@/assests/images/floe.jpeg"import { HollowDotsSpinner } from 'react-epic-spinners'export const Implusive = () => {return (<div className="bg-red-100/[0.6] shadow-[0px_10px_38px_-10px_rgba(22,23,24,0.35),0px_10px_20px_-15px_rgba(22,23,24,0.2)] rounded-[22px] snap-y h-[318px] w-fit mx-auto p-3 overflow-auto [&::-webkit-scrollbar]:hidden"><motion.div className="relative overflow-hidden bg-[#efd9cb] [&::-webkit-scrollbar]:hidden snap-center mt-3 h-[300px] w-[250px] rounded-[20px] p-3"><div className="z-10 absolute top-3 w-fit left-3"><h1 className="text-3xl text-left w-fit text-[#e4ae8c] font-Gucci">BLOOM</h1><h1 className="text-sm text-left w-fit text-[#e4ae8c] font-Gucci">GUCCI</h1></div><Image src={gucci} className="-z-[0] absolute -right-0 top-0"/><Button price={200} color={"#cd9f82"} /></motion.div><motion.div className="relative overflow-hidden bg-[#efd9cb] [&::-webkit-scrollbar]:hidden snap-center mt-3 h-[300px] w-[250px] rounded-[20px] p-3"><div className="z-10 absolute top-3 w-fit left-3"><h1 className="text-3xl text-left w-fit text-[#676565] font-Zara">ZARA</h1></div><Image src={zara} className="-z-[0] absolute -right-0 top-0"/><Button price={80} color={"#6291b2"} /></motion.div><motion.div className="relative overflow-hidden bg-[#efd9cb] [&::-webkit-scrollbar]:hidden snap-center mt-3 h-[300px] w-[250px] rounded-[20px] p-3"><div className="z-10 absolute top-3 w-fit left-3"><h1 className="text-3xl text-left w-fit text-[#cf9977] font-NTW">Mokka</h1><h1 className="text-sm text-left w-fit text-[#cf9977] font-NTW">notwoways</h1></div><Image src={mokka2} className="-z-[0] absolute -right-0 top-0"/><Button price={100} color={"#cd9f82"} /></motion.div><motion.div className="relative overflow-hidden bg-[#efd9cb] [&::-webkit-scrollbar]:hidden snap-center mt-3 h-[300px] w-[250px] rounded-[20px] p-3"><div className="z-10 absolute top-3 w-fit left-3"><h1 className="text-3xl text-left w-fit text-[#ffffff] font-NTW">floe</h1><h1 className="text-sm text-left w-fit text-[#ffffff] font-NTW">notwoways</h1></div><Image src={flow} className="-z-[0] absolute -right-0 top-0"/><Button price={100} color={"#7ab1be"} /></motion.div></div>)}const Button = ({price, color}) => {const [hover, setHover] = useState(false)const [isDone, setIsDone] = useState(false)const [ width, setWidth ] = useState(220){hover && setTimeout(() => {setHover(false)setIsDone(true)setWidth(140)}, 2000)}const pathVariantsA = {hidden: {opacity:0,pathLength:0},visible: {opacity:1,pathLength:1,scale:[0.9,0.9,1,1.1,1.16,1.1,1],transition:{duration:0.7,fade:0.7}}}return (<div><motion.div initial={{width:220}} animate={{width:width,backgroundColor:isDone ? "#00ff00" : color}} whileHover={{scale:0.93}} onTap={() => {setHover(true); setIsDone(false); setWidth(120)}} transition={{duration:0.2,type:"spring",stiffness:120,bounce:0.4}} className="bg-[#cd9f82]/[.6] overflow-hidden backdrop-blur-[30px] shadow-[0px_10px_38px_-10px_rgba(22,23,24,0.35),0px_10px_20px_-15px_rgba(22,23,24,0.2)] h-[40px] rounded-[18px] mx-auto mt-[235px] flex gap-2 items-center cursor-default text-xl justify-center text-white">{hover && <HollowDotsSpinner color="white" size={7} className='absolute'/>}{isDone && <svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><motion.path variants={pathVariantsA} initial="hidden" animate={isDone ? "visible" : "hidden"} d="M7 12.5l3 3 7-7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></motion.path><motion.path variants={pathVariantsA} initial="hidden" animate={isDone ? "visible" : "hidden"} d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></motion.path></svg>}<motion.p animate={{opacity:hover ? 0 : 1}} onAnimationComplete={() => {isDone ? setTimeout(() => {setIsDone(false); setHover(false);setWidth(220)}, 3000) : null}} transition={{duration:0.1}}>{isDone ? "Added" : "Order"} {isDone ? "" : <h1 className="absolute right-2.5 bottom-2.5 text-[#dbdad9] text-sm">{price}</h1>}</motion.p></motion.div></div>)}export default Implusive
The code for this component is here. Some libraries used are:
Next.js
framer-motion
tailwindcss
react-epic-spinners
Inspired by the legendary designer @laurentdelrey's "ship to friends" concept.