{"id":19977179,"url":"https://github.com/adrianhajdin/iphone","last_synced_at":"2025-04-08T11:08:35.290Z","repository":{"id":227845113,"uuid":"772535194","full_name":"adrianhajdin/iphone","owner":"adrianhajdin","description":"Recreate the Apple iPhone 15 Pro website, combining GSAP animations and Three.js 3D effects. From custom animations to animated 3D models, this tutorial covers it all.","archived":false,"fork":false,"pushed_at":"2024-07-12T11:18:10.000Z","size":39063,"stargazers_count":1410,"open_issues_count":15,"forks_count":269,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-01T09:32:58.530Z","etag":null,"topics":["gsap","reactjs","threejs"],"latest_commit_sha":null,"homepage":"https://iphone-doc.vercel.app/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adrianhajdin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-15T11:38:01.000Z","updated_at":"2025-04-01T00:21:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"90c58aa7-6511-4d7a-a710-bef61f9e1021","html_url":"https://github.com/adrianhajdin/iphone","commit_stats":{"total_commits":6,"total_committers":1,"mean_commits":6.0,"dds":0.0,"last_synced_commit":"16ec9fda2f4f658fd662c5818c5a10b1a9545e1b"},"previous_names":["adrianhajdin/iphone"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianhajdin%2Fiphone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianhajdin%2Fiphone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianhajdin%2Fiphone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianhajdin%2Fiphone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adrianhajdin","download_url":"https://codeload.github.com/adrianhajdin/iphone/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247829491,"owners_count":21002995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gsap","reactjs","threejs"],"created_at":"2024-11-13T03:27:15.450Z","updated_at":"2025-04-08T11:08:35.265Z","avatar_url":"https://github.com/adrianhajdin.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cbr /\u003e\n    \u003ca href=\"https://youtu.be/kRQbRAJ4-Fs\" target=\"_blank\"\u003e\n      \u003cimg src=\"https://i.postimg.cc/37PnQw8n/Image-from.png\" alt=\"Project Banner\"\u003e\n    \u003c/a\u003e\n  \u003cbr /\u003e\n\n  \u003cdiv\u003e\n    \u003cimg src=\"https://img.shields.io/badge/-React_JS-black?style=for-the-badge\u0026logoColor=white\u0026logo=react\u0026color=61DAFB\" alt=\"react.js\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/-Three_JS-black?style=for-the-badge\u0026logoColor=white\u0026logo=threedotjs\u0026color=000000\" alt=\"three.js\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/-GSAP-black?style=for-the-badge\u0026logoColor=white\u0026logo=greensock\u0026color=88CE02\" alt=\"greensock\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/-Tailwind_CSS-black?style=for-the-badge\u0026logoColor=white\u0026logo=tailwindcss\u0026color=06B6D4\" alt=\"tailwindcss\" /\u003e\n  \u003c/div\u003e\n\n  \u003ch3 align=\"center\"\u003eIphone 15 Website\u003c/h3\u003e\n\n   \u003cdiv align=\"center\"\u003e\n     Build this project step by step with our detailed tutorial on \u003ca href=\"https://www.youtube.com/@javascriptmastery/videos\" target=\"_blank\"\u003e\u003cb\u003eJavaScript Mastery\u003c/b\u003e\u003c/a\u003e YouTube. Join the JSM family!\n    \u003c/div\u003e\n\u003c/div\u003e\n\n## 📋 \u003ca name=\"table\"\u003eTable of Contents\u003c/a\u003e\n\n1. 🤖 [Introduction](#introduction)\n2. ⚙️ [Tech Stack](#tech-stack)\n3. 🔋 [Features](#features)\n4. 🤸 [Quick Start](#quick-start)\n5. 🕸️ [Snippets](#snippets)\n6. 🔗 [Links](#links)\n7. 🚀 [More](#more)\n\n## 🚨 Tutorial\n\nThis repository contains the code corresponding to an in-depth tutorial available on our YouTube channel, \u003ca href=\"https://www.youtube.com/@javascriptmastery/videos\" target=\"_blank\"\u003e\u003cb\u003eJavaScript Mastery\u003c/b\u003e\u003c/a\u003e. \n\nIf you prefer visual learning, this is the perfect resource for you. Follow our tutorial to learn how to build projects like these step-by-step in a beginner-friendly manner!\n\n\u003ca href=\"https://youtu.be/kRQbRAJ4-Fs\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/sujatagunale/EasyRead/assets/151519281/1736fca5-a031-4854-8c09-bc110e3bc16d\" /\u003e\u003c/a\u003e\n\n## \u003ca name=\"introduction\"\u003e🤖 Introduction\u003c/a\u003e\n\nThis is a clone of Apple's iPhone 15 Pro website using React.js and TailwindCSS. It highlights the effective use of GSAP (Greensock Animations) and Three.js for displaying iPhone 15 Pro models in various colors and shapes.\n\nIf you're getting started and need assistance or face any bugs, join our active Discord community with over 27k+ members. It's a place where people help each other out.\n\n\u003ca href=\"https://discord.com/invite/n6EdbFJ\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/sujatagunale/EasyRead/assets/151519281/618f4872-1e10-42da-8213-1d69e486d02e\" /\u003e\u003c/a\u003e\n\n## \u003ca name=\"tech-stack\"\u003e⚙️ Tech Stack\u003c/a\u003e\n\n- React.js\n- Three.js\n- React Three Fiber\n- React Three Drei\n- GSAP (Greensock)\n- Vite\n- Tailwind CSS\n\n## \u003ca name=\"features\"\u003e🔋 Features\u003c/a\u003e\n\n👉 **Beautiful Subtle Smooth Animations using GSAP**: Enhanced user experience with seamless and captivating animations powered by GSAP.\n\n👉 **3D Model Rendering with Different Colors and Sizes**: Explore the iPhone 15 Pro from every angle with dynamic 3D rendering, offering various color and size options.\n\n👉 **Custom Video Carousel (made with GSAP)**: Engage users with a unique and interactive video carousel developed using GSAP for a personalized browsing experience.\n\n👉 **Completely Responsive**: Consistent access and optimal viewing on any device with a fully responsive design that adapts to different screen sizes.\n\nand many more, including code architecture and reusability \n\n## \u003ca name=\"quick-start\"\u003e🤸 Quick Start\u003c/a\u003e\n\nFollow these steps to set up the project locally on your machine.\n\n**Prerequisites**\n\nMake sure you have the following installed on your machine:\n\n- [Git](https://git-scm.com/)\n- [Node.js](https://nodejs.org/en)\n- [npm](https://www.npmjs.com/) (Node Package Manager)\n\n**Cloning the Repository**\n\n```bash\ngit clone https://github.com/JavaScript-Mastery-Pro/iphone-doc.git\ncd iphone-doc\n```\n\n**Installation**\n\nInstall the project dependencies using npm:\n\n```bash\nnpm install\n```\n\n**Running the Project**\n\n```bash\nnpm run dev\n```\n\nOpen [http://localhost:5173](http://localhost:5173) in your browser to view the project.\n\n## \u003ca name=\"snippets\"\u003e🕸️ Snippets\u003c/a\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003etailwind.config.js\u003c/code\u003e\u003c/summary\u003e\n\n```javascript\n/** @type {import('tailwindcss').Config} */\nexport default {\n  content: [\"./index.html\", \"./src/**/*.{js,ts,jsx,tsx}\"],\n  theme: {\n    extend: {\n      colors: {\n        blue: \"#2997FF\",\n        gray: {\n          DEFAULT: \"#86868b\",\n          100: \"#94928d\",\n          200: \"#afafaf\",\n          300: \"#42424570\",\n        },\n        zinc: \"#101010\",\n      },\n    },\n  },\n  plugins: [],\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003econstants/index.js\u003c/code\u003e\u003c/summary\u003e\n\n```javascript\nimport {\n  blackImg,\n  blueImg,\n  highlightFirstVideo,\n  highlightFourthVideo,\n  highlightSecondVideo,\n  highlightThirdVideo,\n  whiteImg,\n  yellowImg,\n} from \"../utils\";\n\nexport const navLists = [\"Store\", \"Mac\", \"iPhone\", \"Support\"];\n\nexport const hightlightsSlides = [\n  {\n    id: 1,\n    textLists: [\n      \"Enter A17 Pro.\",\n      \"Game‑changing chip.\",\n      \"Groundbreaking performance.\",\n    ],\n    video: highlightFirstVideo,\n    videoDuration: 4,\n  },\n  {\n    id: 2,\n    textLists: [\"Titanium.\", \"So strong. So light. So Pro.\"],\n    video: highlightSecondVideo,\n    videoDuration: 5,\n  },\n  {\n    id: 3,\n    textLists: [\n      \"iPhone 15 Pro Max has the\",\n      \"longest optical zoom in\",\n      \"iPhone ever. Far out.\",\n    ],\n    video: highlightThirdVideo,\n    videoDuration: 2,\n  },\n  {\n    id: 4,\n    textLists: [\"All-new Action button.\", \"What will yours do?.\"],\n    video: highlightFourthVideo,\n    videoDuration: 3.63,\n  },\n];\n\nexport const models = [\n  {\n    id: 1,\n    title: \"iPhone 15 Pro in Natural Titanium\",\n    color: [\"#8F8A81\", \"#ffe7b9\", \"#6f6c64\"],\n    img: yellowImg,\n  },\n  {\n    id: 2,\n    title: \"iPhone 15 Pro in Blue Titanium\",\n    color: [\"#53596E\", \"#6395ff\", \"#21242e\"],\n    img: blueImg,\n  },\n  {\n    id: 3,\n    title: \"iPhone 15 Pro in White Titanium\",\n    color: [\"#C9C8C2\", \"#ffffff\", \"#C9C8C2\"],\n    img: whiteImg,\n  },\n  {\n    id: 4,\n    title: \"iPhone 15 Pro in Black Titanium\",\n    color: [\"#454749\", \"#3b3b3b\", \"#181819\"],\n    img: blackImg,\n  },\n];\n\nexport const sizes = [\n  { label: '6.1\"', value: \"small\" },\n  { label: '6.7\"', value: \"large\" },\n];\n\nexport const footerLinks = [\n  \"Privacy Policy\",\n  \"Terms of Use\",\n  \"Sales Policy\",\n  \"Legal\",\n  \"Site Map\",\n];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eLights.jsx\u003c/code\u003e\u003c/summary\u003e\n\n```javascript\nimport { Environment, Lightformer } from \"@react-three/drei\";\n\nconst Lights = () =\u003e {\n  return (\n    // group different lights and lightformers. We can use group to organize lights, cameras, meshes, and other objects in the scene.\n    \u003cgroup name=\"lights\"\u003e\n      {/**\n       * @description Environment is used to create a background environment for the scene\n       * https://github.com/pmndrs/drei?tab=readme-ov-file#environment\n       */}\n      \u003cEnvironment resolution={256}\u003e\n        \u003cgroup\u003e\n          {/**\n           * @description Lightformer used to create custom lights with various shapes and properties in a 3D scene.\n           * https://github.com/pmndrs/drei?tab=readme-ov-file#lightformer\n           */}\n          \u003cLightformer\n            form=\"rect\"\n            intensity={10}\n            position={[-1, 0, -10]}\n            scale={10}\n            color={\"#495057\"}\n          /\u003e\n          \u003cLightformer\n            form=\"rect\"\n            intensity={10}\n            position={[-10, 2, 1]}\n            scale={10}\n            rotation-y={Math.PI / 2}\n          /\u003e\n          \u003cLightformer\n            form=\"rect\"\n            intensity={10}\n            position={[10, 0, 1]}\n            scale={10}\n            rotation-y={Math.PI / 2}\n          /\u003e\n        \u003c/group\u003e\n      \u003c/Environment\u003e\n\n      {/**\n       * @description spotLight is used to create a light source positioned at a specific point\n       * in the scene that emits light in a specific direction.\n       * https://threejs.org/docs/#api/en/lights/SpotLight\n       */}\n      \u003cspotLight\n        position={[-2, 10, 5]}\n        angle={0.15}\n        penumbra={1} // the penumbra is the soft edge of a shadow cast by a point light\n        decay={0} // the amount the light dims as it moves away from the source\n        intensity={Math.PI * 0.2} // the light intensity\n        color={\"#f8f9fa\"}\n      /\u003e\n      \u003cspotLight\n        position={[0, -25, 10]}\n        angle={0.15}\n        penumbra={1}\n        decay={0}\n        intensity={Math.PI * 0.2}\n        color={\"#f8f9fa\"}\n      /\u003e\n      \u003cspotLight\n        position={[0, 15, 5]}\n        angle={0.15}\n        penumbra={1}\n        decay={0.1}\n        intensity={Math.PI * 3}\n      /\u003e\n    \u003c/group\u003e\n  );\n};\n\nexport default Lights;\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003ematerials\u003c/code\u003e\u003c/summary\u003e\n\n```javascript\n    useEffect(() =\u003e {\n      Object.entries(materials).map((material) =\u003e {\n        // these are the material names that can't be changed color\n        if (\n          material[0] !== \"zFdeDaGNRwzccye\" \u0026\u0026\n          material[0] !== \"ujsvqBWRMnqdwPx\" \u0026\u0026\n          material[0] !== \"hUlRcbieVuIiOXG\" \u0026\u0026\n          material[0] !== \"jlzuBkUzuJqgiAK\" \u0026\u0026\n          material[0] !== \"xNrofRCqOXXHVZt\"\n        ) {\n          material[1].color = new THREE.Color(props.item.color[0]);\n        }\n        material[1].needsUpdate = true;\n      });\n    }, [materials, props.item]);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eVideoCarousel.jsx\u003c/code\u003e\u003c/summary\u003e\n\n```javascript\nimport gsap from \"gsap\";\nimport { useGSAP } from \"@gsap/react\";\nimport { ScrollTrigger } from \"gsap/all\";\ngsap.registerPlugin(ScrollTrigger);\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { hightlightsSlides } from \"../constants\";\nimport { pauseImg, playImg, replayImg } from \"../utils\";\n\nconst VideoCarousel = () =\u003e {\n  const videoRef = useRef([]);\n  const videoSpanRef = useRef([]);\n  const videoDivRef = useRef([]);\n\n  // video and indicator\n  const [video, setVideo] = useState({\n    isEnd: false,\n    startPlay: false,\n    videoId: 0,\n    isLastVideo: false,\n    isPlaying: false,\n  });\n\n  const [loadedData, setLoadedData] = useState([]);\n  const { isEnd, isLastVideo, startPlay, videoId, isPlaying } = video;\n\n  useGSAP(() =\u003e {\n    // slider animation to move the video out of the screen and bring the next video in\n    gsap.to(\"#slider\", {\n      transform: `translateX(${-100 * videoId}%)`,\n      duration: 2,\n      ease: \"power2.inOut\", // show visualizer https://gsap.com/docs/v3/Eases\n    });\n\n    // video animation to play the video when it is in the view\n    gsap.to(\"#video\", {\n      scrollTrigger: {\n        trigger: \"#video\",\n        toggleActions: \"restart none none none\",\n      },\n      onComplete: () =\u003e {\n        setVideo((pre) =\u003e ({\n          ...pre,\n          startPlay: true,\n          isPlaying: true,\n        }));\n      },\n    });\n  }, [isEnd, videoId]);\n\n  useEffect(() =\u003e {\n    let currentProgress = 0;\n    let span = videoSpanRef.current;\n\n    if (span[videoId]) {\n      // animation to move the indicator\n      let anim = gsap.to(span[videoId], {\n        onUpdate: () =\u003e {\n          // get the progress of the video\n          const progress = Math.ceil(anim.progress() * 100);\n\n          if (progress != currentProgress) {\n            currentProgress = progress;\n\n            // set the width of the progress bar\n            gsap.to(videoDivRef.current[videoId], {\n              width:\n                window.innerWidth \u003c 760\n                  ? \"10vw\" // mobile\n                  : window.innerWidth \u003c 1200\n                  ? \"10vw\" // tablet\n                  : \"4vw\", // laptop\n            });\n\n            // set the background color of the progress bar\n            gsap.to(span[videoId], {\n              width: `${currentProgress}%`,\n              backgroundColor: \"white\",\n            });\n          }\n        },\n\n        // when the video is ended, replace the progress bar with the indicator and change the background color\n        onComplete: () =\u003e {\n          if (isPlaying) {\n            gsap.to(videoDivRef.current[videoId], {\n              width: \"12px\",\n            });\n            gsap.to(span[videoId], {\n              backgroundColor: \"#afafaf\",\n            });\n          }\n        },\n      });\n\n      if (videoId == 0) {\n        anim.restart();\n      }\n\n      // update the progress bar\n      const animUpdate = () =\u003e {\n        anim.progress(\n          videoRef.current[videoId].currentTime /\n            hightlightsSlides[videoId].videoDuration\n        );\n      };\n\n      if (isPlaying) {\n        // ticker to update the progress bar\n        gsap.ticker.add(animUpdate);\n      } else {\n        // remove the ticker when the video is paused (progress bar is stopped)\n        gsap.ticker.remove(animUpdate);\n      }\n    }\n  }, [videoId, startPlay]);\n\n  useEffect(() =\u003e {\n    if (loadedData.length \u003e 3) {\n      if (!isPlaying) {\n        videoRef.current[videoId].pause();\n      } else {\n        startPlay \u0026\u0026 videoRef.current[videoId].play();\n      }\n    }\n  }, [startPlay, videoId, isPlaying, loadedData]);\n\n  // vd id is the id for every video until id becomes number 3\n  const handleProcess = (type, i) =\u003e {\n    switch (type) {\n      case \"video-end\":\n        setVideo((pre) =\u003e ({ ...pre, isEnd: true, videoId: i + 1 }));\n        break;\n\n      case \"video-last\":\n        setVideo((pre) =\u003e ({ ...pre, isLastVideo: true }));\n        break;\n\n      case \"video-reset\":\n        setVideo((pre) =\u003e ({ ...pre, videoId: 0, isLastVideo: false }));\n        break;\n\n      case \"pause\":\n        setVideo((pre) =\u003e ({ ...pre, isPlaying: !pre.isPlaying }));\n        break;\n\n      case \"play\":\n        setVideo((pre) =\u003e ({ ...pre, isPlaying: !pre.isPlaying }));\n        break;\n\n      default:\n        return video;\n    }\n  };\n\n  const handleLoadedMetaData = (i, e) =\u003e setLoadedData((pre) =\u003e [...pre, e]);\n\n  return (\n    \u003c\u003e\n      \u003cdiv className=\"flex items-center\"\u003e\n        {hightlightsSlides.map((list, i) =\u003e (\n          \u003cdiv key={list.id} id=\"slider\" className=\"sm:pr-20 pr-10\"\u003e\n            \u003cdiv className=\"video-carousel_container\"\u003e\n              \u003cdiv className=\"w-full h-full flex-center rounded-3xl overflow-hidden bg-black\"\u003e\n                \u003cvideo\n                  id=\"video\"\n                  playsInline={true}\n                  className={`${\n                    list.id === 2 \u0026\u0026 \"translate-x-44\"\n                  } pointer-events-none`}\n                  preload=\"auto\"\n                  muted\n                  ref={(el) =\u003e (videoRef.current[i] = el)}\n                  onEnded={() =\u003e\n                    i !== 3\n                      ? handleProcess(\"video-end\", i)\n                      : handleProcess(\"video-last\")\n                  }\n                  onPlay={() =\u003e\n                    setVideo((pre) =\u003e ({ ...pre, isPlaying: true }))\n                  }\n                  onLoadedMetadata={(e) =\u003e handleLoadedMetaData(i, e)}\n                \u003e\n                  \u003csource src={list.video} type=\"video/mp4\" /\u003e\n                \u003c/video\u003e\n              \u003c/div\u003e\n\n              \u003cdiv className=\"absolute top-12 left-[5%] z-10\"\u003e\n                {list.textLists.map((text, i) =\u003e (\n                  \u003cp key={i} className=\"md:text-2xl text-xl font-medium\"\u003e\n                    {text}\n                  \u003c/p\u003e\n                ))}\n              \u003c/div\u003e\n            \u003c/div\u003e\n          \u003c/div\u003e\n        ))}\n      \u003c/div\u003e\n\n      \u003cdiv className=\"relative flex-center mt-10\"\u003e\n        \u003cdiv className=\"flex-center py-5 px-7 bg-gray-300 backdrop-blur rounded-full\"\u003e\n          {videoRef.current.map((_, i) =\u003e (\n            \u003cspan\n              key={i}\n              className=\"mx-2 w-3 h-3 bg-gray-200 rounded-full relative cursor-pointer\"\n              ref={(el) =\u003e (videoDivRef.current[i] = el)}\n            \u003e\n              \u003cspan\n                className=\"absolute h-full w-full rounded-full\"\n                ref={(el) =\u003e (videoSpanRef.current[i] = el)}\n              /\u003e\n            \u003c/span\u003e\n          ))}\n        \u003c/div\u003e\n\n        \u003cbutton className=\"control-btn\"\u003e\n          \u003cimg\n            src={isLastVideo ? replayImg : !isPlaying ? playImg : pauseImg}\n            alt={isLastVideo ? \"replay\" : !isPlaying ? \"play\" : \"pause\"}\n            onClick={\n              isLastVideo\n                ? () =\u003e handleProcess(\"video-reset\")\n                : !isPlaying\n                ? () =\u003e handleProcess(\"play\")\n                : () =\u003e handleProcess(\"pause\")\n            }\n          /\u003e\n        \u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/\u003e\n  );\n};\n\nexport default VideoCarousel;\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eutils/index.js\u003c/code\u003e\u003c/summary\u003e\n\n```javascript\nimport hero from \"/assets/images/hero.jpeg\";\n\nexport const heroImg = hero;\n\nimport hmv from \"/assets/videos/hero.mp4\";\nimport smallmv from \"/assets/videos/smallHero.mp4\";\nimport highlightFirstmv from \"/assets/videos/highlight-first.mp4\";\nimport highlightSectmv from \"/assets/videos/hightlight-third.mp4\";\nimport highlightThirdmv from \"/assets/videos/hightlight-sec.mp4\";\nimport highlightFourthmv from \"/assets/videos/hightlight-fourth.mp4\";\nimport exploremv from \"/assets/videos/explore.mp4\";\nimport framemv from \"/assets/videos/frame.mp4\";\n\nimport apple from \"/assets/images/apple.svg\";\nimport search from \"/assets/images/search.svg\";\nimport bag from \"/assets/images/bag.svg\";\nimport watch from \"/assets/images/watch.svg\";\nimport right from \"/assets/images/right.svg\";\nimport replay from \"/assets/images/replay.svg\";\nimport play from \"/assets/images/play.svg\";\nimport pause from \"/assets/images/pause.svg\";\n\nimport yellow from \"/assets/images/yellow.jpg\";\nimport blue from \"/assets/images/blue.jpg\";\nimport white from \"/assets/images/white.jpg\";\nimport black from \"/assets/images/black.jpg\";\nimport explore1 from \"/assets/images/explore1.jpg\";\nimport explore2 from \"/assets/images/explore2.jpg\";\nimport chip from \"/assets/images/chip.jpeg\";\nimport frame from \"/assets/images/frame.png\";\n\nexport const heroVideo = hmv;\nexport const smallHeroVideo = smallmv;\nexport const highlightFirstVideo = highlightFirstmv;\nexport const highlightSecondVideo = highlightSectmv;\nexport const highlightThirdVideo = highlightThirdmv;\nexport const highlightFourthVideo = highlightFourthmv;\nexport const exploreVideo = exploremv;\nexport const frameVideo = framemv;\n\nexport const appleImg = apple;\nexport const searchImg = search;\nexport const bagImg = bag;\nexport const watchImg = watch;\nexport const rightImg = right;\nexport const replayImg = replay;\nexport const playImg = play;\nexport const pauseImg = pause;\n\nexport const yellowImg = yellow;\nexport const blueImg = blue;\nexport const whiteImg = white;\nexport const blackImg = black;\nexport const explore1Img = explore1;\nexport const explore2Img = explore2;\nexport const chipImg = chip;\nexport const frameImg = frame;\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eindex.css\u003c/code\u003e\u003c/summary\u003e\n\n```css\n@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\n\nbody {\n  color: white;\n  width: 100dvw;\n  overflow-x: hidden;\n  height: 100%;\n  background: #000;\n  border-color: #3b3b3b;\n  user-select: none;\n}\n\ncanvas {\n  touch-action: none;\n}\n\n.scrim-max-width {\n  margin-inline-start: auto;\n  margin-inline-end: auto;\n  position: relative;\n  max-width: 1120px;\n}\n\n@layer utilities {\n  .flex-center {\n    @apply flex items-center justify-center\n  }\n\n  .nav-height {\n    @apply h-[calc(100vh-60px)]\n  }\n\n  .btn {\n    @apply px-5 py-2 rounded-3xl bg-blue my-5 hover:bg-transparent border border-transparent hover:border hover:text-blue hover:border-blue\n  }\n\n  .color-container {\n    @apply flex items-center justify-center px-4 py-4 rounded-full bg-gray-300 backdrop-blur\n  }\n\n  .size-btn-container {\n    @apply flex items-center justify-center p-1 rounded-full bg-gray-300 backdrop-blur ml-3 gap-1\n  }\n\n  .size-btn {\n    @apply w-10 h-10 text-sm flex justify-center items-center bg-white text-black rounded-full transition-all\n  }\n\n  .common-padding {\n    @apply sm:py-32 py-20 sm:px-10 px-5\n  }\n\n  .section-heading {\n    @apply text-gray lg:text-6xl md:text-5xl text-3xl lg:mb-0 mb-5 font-medium opacity-0 translate-y-20\n  }\n\n  .feature-text {\n    @apply text-gray max-w-md text-lg md:text-xl font-semibold opacity-0 translate-y-[100px]\n  }\n\n  .feature-text-container {\n    @apply w-full flex-center flex-col md:flex-row mt-10 md:mt-16 gap-5\n  }\n\n  .feature-video {\n    @apply w-full h-full object-cover object-center scale-150 opacity-0\n  }\n\n  .feature-video-container {\n    @apply w-full flex flex-col md:flex-row gap-5 items-center\n  }\n\n  .link {\n    @apply text-blue hover:underline cursor-pointer flex items-center text-xl opacity-0 translate-y-20\n  }\n\n  .control-btn {\n    @apply ml-4 p-4 rounded-full bg-gray-300 backdrop-blur flex-center\n  }\n\n  .hero-title {\n    @apply text-center font-semibold text-3xl text-gray-100 opacity-0 max-md:mb-10\n  }\n\n  .hiw-title {\n    @apply text-4xl md:text-7xl font-semibold text-center\n  }\n\n  .hiw-subtitle {\n    @apply text-gray font-semibold text-xl md:text-2xl py-10 text-center\n  }\n\n  .hiw-video {\n    @apply absolute w-[95%] h-[90%] rounded-[56px] overflow-hidden\n  }\n\n  .hiw-text-container {\n    @apply flex md:flex-row flex-col justify-between items-start gap-24\n  }\n\n  .hiw-text {\n    @apply text-gray text-xl font-normal md:font-semibold\n  }\n\n  .hiw-bigtext {\n    @apply text-white text-3xl md:text-5xl font-normal md:font-semibold my-2\n  }\n\n  .video-carousel_container {\n    @apply relative sm:w-[70vw] w-[88vw] md:h-[70vh] sm:h-[50vh] h-[35vh]\n  }\n\n  .g_fadeIn {\n    @apply opacity-0 translate-y-[100px]\n  }\n}\n```\n\n\u003c/details\u003e\n\n## \u003ca name=\"links\"\u003e🔗 Links\u003c/a\u003e\n\nPublic Assets used in the project can be found [here](https://drive.google.com/file/d/1syHiNxSIGXVApaIozdrLXM2x5dPhvaJL/view?usp=sharing)\n\n## \u003ca name=\"more\"\u003e🚀 More\u003c/a\u003e\n\n**Advance your skills with Next.js 14 Pro Course**\n\nEnjoyed creating this project? Dive deeper into our PRO courses for a richer learning adventure. They're packed with detailed explanations, cool features, and exercises to boost your skills. Give it a go!\n\n\u003ca href=\"https://jsmastery.pro/next14\" target=\"_blank\"\u003e\n\u003cimg src=\"https://github.com/sujatagunale/EasyRead/assets/151519281/557837ce-f612-4530-ab24-189e75133c71\" alt=\"Project Banner\"\u003e\n\u003c/a\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n**Accelerate your professional journey with the Expert Training program**\n\nAnd if you're hungry for more than just a course and want to understand how we learn and tackle tech challenges, hop into our personalized masterclass. We cover best practices, different web skills, and offer mentorship to boost your confidence. Let's learn and grow together!\n\n\u003ca href=\"https://www.jsmastery.pro/masterclass\" target=\"_blank\"\u003e\n\u003cimg src=\"https://github.com/sujatagunale/EasyRead/assets/151519281/fed352ad-f27b-400d-9b8f-c7fe628acb84\" alt=\"Project Banner\"\u003e\n\u003c/a\u003e\n\n#\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrianhajdin%2Fiphone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadrianhajdin%2Fiphone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrianhajdin%2Fiphone/lists"}