Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
.section {
width: 100%;
padding-inline: 1.25rem;
}

.container {
max-width: 75rem;
margin-inline: auto;
}

.card {
position: relative;
overflow: hidden;
border-radius: 32px;
background: #fff;
}

.overlay {
position: absolute;
inset: 0;
pointer-events: none;
border: 1px solid rgb(0 0 0 / 10%);
border-radius: 32px;
}

.content {
display: flex;
flex-direction: column;
gap: 1.5rem;
padding: 1.5rem;
}

.copyColumn {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
}

.copyStack {
display: flex;
flex-direction: column;
gap: 0.75rem;
}

.title {
max-width: 430px;
font-family: "Inter", sans-serif;
font-size: 32px;
font-weight: 600;
line-height: 1.2;
color: #000;
margin: auto;
text-align: center;
}

.descriptionWrap {
max-width: 357px;
}

.description {
font-family: "Inter Display", sans-serif;
font-size: 18px;
line-height: 1.4;
color: rgb(0 0 0 / 40%);
}

.ctaWrap {
display: flex;
justify-content: center;
padding-top: 1rem;
margin-top: 1.5rem;
}

.ctaButton {
position: relative;
display: flex;
width: 100%;
max-width: 280px;
align-items: center;
justify-content: center;
gap: 0.625rem;
height: 3rem;
padding-inline: 1.25rem;
border: 0;
border-radius: 999px;
background: #000;
cursor: pointer;
transition: transform 0.2s ease;
}

.ctaButton:hover {
transform: scale(0.99);
box-shadow: none;
}

.iconFrame {
position: relative;
display: flex;
height: 1rem;
width: 1rem;
align-items: center;
justify-content: center;
}

.iconLayer {
position: absolute;
transition:
opacity 0.3s ease,
transform 0.3s ease;
}

.iconVisible {
opacity: 1;
transform: scale(1);
}

.iconHidden {
opacity: 0;
transform: scale(0.5);
}

.ctaLabel {
position: relative;
white-space: nowrap;
font-family: "Inter Display", sans-serif;
font-size: 18px;
font-weight: 500;
line-height: 1.5rem;
color: #fff;
}

.mediaColumn {
width: 100%;
flex-shrink: 0;
}

.dashboardImage {
width: 100%;
height: auto;
border-radius: 12px;
object-fit: contain;
}

@media (min-width: 1024px) {
.section {
padding-inline: 2rem;
}

.content {
flex-direction: row;
gap: 0;
}

.copyColumn {
min-height: 0;
padding:16px;
}


.title {
max-width: 430px;
font-family: "Inter", sans-serif;
font-size: 36px;
font-weight: 600;
line-height: 1.2;
color: #000;
margin: 4px 0 0 4px;
text-align: left;
}

.ctaWrap {
justify-content: flex-start;
margin-top: 0;
}

.ctaButton {
width: auto;
max-width: none;
justify-content: flex-start;
}

.mediaColumn {
width: 600px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import dashboardImg from "@/public/images/home/d67b5e94653944c1d0d4998c6b169c37f98060ad.png";
import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import { CopyIcon } from "./shared";
import { CopyIcon } from "../shared/shared";
import styles from "./BuildChatSection.module.css";

// ---------------------------------------------------------------------------
// Constants
Expand All @@ -16,22 +17,7 @@ const CARD_SHADOW = "0px 8px 16px -4px rgba(22,34,51,0.08)";
// ---------------------------------------------------------------------------

function SectionTitle() {
return (
<p className="font-['Inter',sans-serif] font-semibold text-[22px] lg:text-4xl text-black leading-[1.25] max-w-[430px]">
Build an AI chat in minutes
</p>
);
}

function SectionDescription() {
return (
<div className="max-w-[357px]">
<p className="font-['Inter_Display',sans-serif] text-lg text-black/40 leading-[1.4]">
This scaffolds a Reference chat interface with a beautiful Component library and a fully
functional OpenUI lang and Renderer.
</p>
</div>
);
return <p className={styles.title}>Build a Generative UI chat in minutes</p>;
}

function CtaButton() {
Expand Down Expand Up @@ -61,19 +47,19 @@ function CtaButton() {
};

return (
<div className="flex items-center justify-center lg:justify-start mt-6 lg:mt-0 pt-4">
<div className={styles.ctaWrap}>
<button
onClick={handleClick}
className="bg-black rounded-full h-12 px-5 flex items-center gap-2.5 cursor-pointer relative transition-all duration-200 hover:scale-105 w-full max-w-[280px] lg:max-w-none lg:w-auto justify-center lg:justify-start"
className={styles.ctaButton}
>
<span className="relative size-4 flex items-center justify-center">
<span className={styles.iconFrame}>
<span
className={`absolute transition-all duration-300 ${copied ? "opacity-0 scale-50" : "opacity-100 scale-100"}`}
className={`${styles.iconLayer} ${copied ? styles.iconHidden : styles.iconVisible}`}
>
<CopyIcon />
</span>
<svg
className={`size-4 absolute transition-all duration-300 ${copied ? "opacity-100 scale-100" : "opacity-0 scale-50"}`}
className={`${styles.iconLayer} ${copied ? styles.iconVisible : styles.iconHidden}`}
fill="none"
viewBox="0 0 14 14"
>
Expand All @@ -86,7 +72,7 @@ function CtaButton() {
/>
</svg>
</span>
<span className="font-['Inter_Display',sans-serif] font-medium text-[18px] leading-6 text-white relative whitespace-nowrap">
<span className={styles.ctaLabel}>
npx @openuidev/cli@latest create
</span>
</button>
Expand All @@ -99,7 +85,7 @@ function DashboardIllustration() {
<Image
src={dashboardImg}
alt="AI chat dashboard illustration"
className="w-full h-auto rounded-xl object-contain"
className={styles.dashboardImage}
placeholder="blur"
/>
);
Expand All @@ -111,28 +97,27 @@ function DashboardIllustration() {

export function BuildChatSection() {
return (
<div className="w-full px-5 lg:px-8">
<div className="max-w-[1200px] mx-auto">
<div className="bg-white rounded-[16px] relative overflow-hidden">
<div className={styles.section}>
<div className={styles.container}>
<div className={styles.card}>
{/* Border + shadow overlay */}
<div
aria-hidden="true"
className="absolute border border-[rgba(0,0,0,0.1)] border-solid inset-0 pointer-events-none rounded-[16px]"
className={styles.overlay}
style={{ boxShadow: CARD_SHADOW }}
/>

<div className="flex flex-col lg:flex-row p-6 gap-6 lg:gap-0">
<div className={styles.content}>
{/* Left: text content */}
<div className="flex flex-col flex-1 justify-between min-h-[240px] lg:min-h-0">
<div className="flex flex-col gap-3">
<div className={styles.copyColumn}>
<div className={styles.copyStack}>
<SectionTitle />
<SectionDescription />
</div>
<CtaButton />
</div>

{/* Right: illustration */}
<div className="w-full lg:w-[600px] shrink-0">
<div className={styles.mediaColumn}>
<DashboardIllustration />
</div>
</div>
Expand Down
Loading
Loading