Skip to content

Commit

Permalink
feat: add hero section
Browse files Browse the repository at this point in the history
  • Loading branch information
ladunjexa committed May 15, 2024
1 parent 78af3ed commit 5c950bc
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 99 deletions.
2 changes: 2 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Navbar from "@/components/layout/navbar";
import Hero from "@/components/sections/hero";
import ButtonGradient from "@/components/svg/button-gradient";
import { cn } from "@/lib/utils";

Expand All @@ -7,6 +8,7 @@ export default function Home() {
<main>
<div className={cn("overflow-hidden pt-[4.75rem] lg:pt-[5.25rem]")}>
<Navbar />
<Hero />
</div>
<ButtonGradient />
</main>
Expand Down
2 changes: 1 addition & 1 deletion components/atoms/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from "react";
import Link from "next/link";

type Props = {
className: string;
className?: string;
href?: string;
children: React.ReactNode;
onClick?: () => void;
Expand Down
53 changes: 53 additions & 0 deletions components/layout/section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from "react";
import { cn } from "@/lib/utils";
import SectionSvg from "../svg/section-svg";

type Props = {
className: string;
id: string;
crosses: boolean;
crossesOffset: string;
customPaddings: boolean;
children: React.ReactNode;
};

const Section = ({ className, id, crosses, crossesOffset, customPaddings, children }: Props) => {
return (
<div
id={id}
className={cn(
"relative",
customPaddings || "py-10 lg:py-16 xl:py-20",
!customPaddings && crosses && "lg:py-32 xl:py-40",
className
)}
>
{children}

<div
className={cn(
"pointer-events-none absolute left-5 top-0 hidden h-full w-0.25 bg-stroke-1 md:block lg:left-7.5 xl:left-10"
)}
/>
<div
className={cn(
"pointer-events-none absolute right-5 top-0 hidden h-full w-0.25 bg-stroke-1 md:block lg:right-7.5 xl:right-10"
)}
/>

{crosses && (
<>
<div
className={cn(
"hidden absolute top-0 left-7.5 right-7.5 h-0.25 bg-stroke-1",
crossesOffset && `${crossesOffset} pointer-events-none lg:block xl:left-10 right-10`
)}
/>
<SectionSvg crossesOffset={crossesOffset} />
</>
)}
</div>
);
};

export default Section;
22 changes: 22 additions & 0 deletions components/sections/hero/company-logos.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { companyLogos } from "@/constants";
import React from "react";
import Image from "next/image";

const CompanyLogos = ({ className }: { className: string }) => {
return (
<div className={className}>
<h5 className="tagline mb-6 text-center text-n-1/50">
Helping people create beautiful content at
</h5>
<ul className="flex">
{companyLogos.map((logo, index) => (
<li key={index} className="flex h-[8.5rem] flex-1 items-center justify-center">
<Image src={logo} width={134} height={28} alt={logo} />
</li>
))}
</ul>
</div>
);
};

export default CompanyLogos;
17 changes: 17 additions & 0 deletions components/sections/hero/generating.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { images } from "@/constants";
import { cn } from "@/lib/utils";
import Image from "next/image";
import React from "react";

const Generating = ({ className }: { className?: string }) => {
return (
<div
className={cn("flex h-14 items-center rounded-[1.7rem] bg-n-8/80 px-6 text-base", className)}
>
<Image src={images.loading} className="mr-4 size-5" alt="loading" width={5} height={5} />
AI is generating
</div>
);
};

export default Generating;
111 changes: 111 additions & 0 deletions components/sections/hero/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"use client";

import React, { useRef } from "react";
import Section from "../../layout/section";
import { cn } from "@/lib/utils";
import Image from "next/image";
import { images, heroIcons } from "@/constants";
import Button from "../../atoms/button";
import { BackgroundCircles, BottomLine, Gradient } from "../../design/hero";
import { ScrollParallax } from "react-just-parallax";
import Generating from "./generating";
import Notification from "./notification";
import CompanyLogos from "./company-logos";

type Props = {};

const Hero = (props: Props) => {
const parallaxRef = useRef(null);
return (
<Section
className={cn("pt-[12rem] -mt-[5.25rem]")}
crosses
crossesOffset="lg:translate-y-[5.25rem]"
customPaddings
id="hero"
>
<div className="container relative" ref={parallaxRef}>
<div className="relative z-1 mx-auto mb-16 max-w-[62rem] text-center md:mb-20 lg:mb-24">
<h1 className="h1 mb-6">
Explore the Possibilities of&nbsp;AI&nbsp;Chatting with{" "}
<span className="relative inline-block">
Brainwave
<Image
src={images.curve}
className="absolute left-0 top-full w-full xl:-mt-2"
width={624}
height={28}
alt="curve"
/>
</span>
</h1>
<p className={cn("body-1 max-w-3xl mx-auto mb-6 text-n-2 lg:mb-8")}>
Unleash the power of AI within Brainwave. Upgrade your productivity with Brainwave, the
open AI chat app.
</p>
<Button href="/pricing" white>
Get Started
</Button>
</div>

<div className={cn("relative max-w-[23rem] mx-auto md:max-w-5xl xl:mb-24")}>
<div className={cn("relative z-1 rounded-2xl p-0.5 bg-conic-gradient")}>
<div className={cn("relative bg-n-8 rounded-[1rem]")}>
<div className={cn("h-[1.4rem] bg-n-10 rounded-t-[0.9rem]")} />
<div
className={cn(
"aspect-[33/40] rounded-b-[0.9rem] overflow-hidden md:aspect-[688/490] lg:aspect-[1024/490]"
)}
>
<Image
src={images.robot}
width={1024}
height={490}
className="translte-y-[8%] w-full scale-[1.7] md:-translate-y-[10%] md:scale-100 lg:-translate-y-[23%]"
alt="AI"
/>

<Generating className="absolute inset-x-4 bottom-5 md:bottom-8 md:left-1/2 md:right-auto md:w-[31rem] md:-translate-x-1/2" />

<ScrollParallax isAbsolutelyPositioned>
<ul className="absolute -left-[5.5rem] bottom-[7.5rem] hidden rounded-2xl border border-n-1/10 bg-n-9/40 p-1 backdrop-blur xl:flex">
{heroIcons.map((icon, index) => (
<li className="p-5" key={index}>
<Image src={icon} height={24} width={25} alt={icon} />
</li>
))}
</ul>
</ScrollParallax>

<ScrollParallax isAbsolutelyPositioned>
<Notification
className="absolute -right-[5.5rem] bottom-44 hidden w-72 xl:flex"
title="Code generation"
/>
</ScrollParallax>
</div>
</div>

<Gradient />
</div>
<div className="absolute left-1/2 top-[-54%] w-[234%] -translate-x-1/2 md:top-[-46%] md:w-[138%] lg:top-[-104%]">
<Image
src={images.heroBackground}
width={1440}
height={1880}
className="w-full"
alt="hero"
/>
</div>

<BackgroundCircles parallaxRef={parallaxRef} />
</div>

<CompanyLogos className="relative z-10 mt-20 hidden lg:block" />
</div>
<BottomLine />
</Section>
);
};

export default Hero;
41 changes: 41 additions & 0 deletions components/sections/hero/notification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { images, notificationImages } from "@/constants";
import { cn } from "@/lib/utils";
import Image from "next/image";
import React from "react";

type Props = {
className: string;
title: string;
};

const Notification = ({ className, title }: Props) => {
return (
<div
className={cn(
"flex items-center p-4 pr-6 bg-n-9/40 backdrop-blur border border-n-1/10 rounded-2xl gap-5",
className
)}
>
<Image src={images.notification1} width={62} height={62} alt="image" className="rounded-xl" />
<div className="flex-1">
<h6 className="mb-1 justify-between text-base font-semibold">{title}</h6>

<div className="flex items-center justify-between">
<ul className="-m-0.5 flex">
{notificationImages.map((item, index) => (
<li
key={index}
className="flex size-6 overflow-hidden rounded-full border-2 border-n-12"
>
<Image src={item} className="w-full" width={20} height={20} alt={item} />
</li>
))}
</ul>
<div className="body-2 text-n-13">1m ago</div>
</div>
</div>
</div>
);
};

export default Notification;
Loading

0 comments on commit 5c950bc

Please sign in to comment.