Compare commits

...
Author SHA1 Message Date
bflatastic 0b27b4854c mx-auto fix 2025-05-14 02:27:16 +07:00
bflatastic 395a4a3644 artcraft landing 2 2025-05-14 02:25:07 +07:00
12 changed files with 340 additions and 27 deletions
@@ -1,8 +1,8 @@
import { Route, Routes } from "react-router-dom";
import Landing from "../pages/landing";
import Download from "../pages/download";
import Navbar from "../components/navbar";
import Footer from "../components/footer";
import Landing2 from "../pages/landing2";
export function App() {
return (
@@ -10,7 +10,7 @@ export function App() {
<Navbar />
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/" element={<Landing2 />} />
<Route path="/download" element={<Download />} />
</Routes>
@@ -0,0 +1,29 @@
import { Button } from "@storyteller/ui-button";
import { faDiscord } from "@fortawesome/free-brands-svg-icons";
import { SOCIAL_LINKS } from "../../config/links";
interface DiscordButtonProps {
className?: string;
small?: boolean;
}
export const DiscordButton = ({
className = "",
small = false,
}: DiscordButtonProps) => {
const sizeClasses = small
? "px-4 py-2 text-md rounded-xl"
: "text-lg px-4 py-2 md:px-8 md:py-4 md:text-2xl rounded-2xl";
return (
<Button
className={`relative z-10 ${sizeClasses} font-bold transition-all duration-300 shadow-lg hover:shadow-blue-500/25 ${className}`}
icon={faDiscord}
as="link"
href={SOCIAL_LINKS.DISCORD}
target="_blank"
>
Join Discord
</Button>
);
};
@@ -0,0 +1 @@
export * from "./discord-button";
@@ -1,18 +1,15 @@
import {
Disclosure,
DisclosureButton,
DisclosurePanel,
} from "@headlessui/react";
import { Disclosure, DisclosureButton } from "@headlessui/react";
import { faBars } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button } from "@storyteller/ui-button";
// import { Button } from "@storyteller/ui-button";
import { twMerge } from "tailwind-merge";
import { useEffect, useState } from "react";
import { DiscordButton } from "../discord-button";
const navigation = [
{ name: "Home", href: "/", current: true },
{ name: "Download", href: "/download", current: false },
];
// const navigation = [
// { name: "Home", href: "/", current: true },
// { name: "Download", href: "/download", current: false },
// ];
export default function Navbar() {
const [scrolled, setScrolled] = useState(false);
@@ -30,11 +27,13 @@ export default function Navbar() {
<Disclosure
as="nav"
className={twMerge(
"z-20 fixed top-0 left-0 w-full transition-colors duration-200",
scrolled ? "bg-[#1b1b1f]/70 backdrop-blur-lg" : "bg-transparent"
"z-20 fixed top-0 left-0 w-full transition-colors duration-200 bg-transparent",
scrolled
? "bg-[#1b1b1f]/70 backdrop-blur-lg lg:bg-transparent lg:backdrop-blur-none"
: "bg-transparent"
)}
>
<div className="mx-auto max-w-[1920px] sm:px-6 lg:px-8 px-6 md:px-16 xl:px-32">
<div className="mx-auto max-w-screen sm:px-6 lg:px-8 px-6 md:px-16 xl:px-4">
<div className="flex h-16 justify-between">
<div className="flex">
<div className="flex shrink-0 items-center">
@@ -46,7 +45,7 @@ export default function Navbar() {
/>
</a>
</div>
<div className="hidden md:ml-7 md:flex md:items-center md:space-x-3">
{/* <div className="hidden md:ml-7 md:flex md:items-center md:space-x-3">
{navigation.map((item) => (
<a
key={item.name}
@@ -62,27 +61,24 @@ export default function Navbar() {
{item.name}
</a>
))}
</div>
</div> */}
</div>
<div className="flex items-center">
<div className="hidden md:ml-4 md:flex md:shrink-0 md:items-center">
<Button as="link" href="/download">
{/* <Button as="link" href="/download">
Download
</Button>
</Button> */}
<DiscordButton small />
</div>
<div className="mr-2 -ml-2 flex items-center md:hidden">
<div className="-ml-2 flex items-center md:hidden">
{/* Mobile menu button */}
<DisclosureButton className="group relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:ring-2 focus:ring-white focus:outline-hidden focus:ring-inset">
<span className="absolute -inset-0.5" />
<span className="sr-only">Open main menu</span>
<FontAwesomeIcon icon={faBars} />
</DisclosureButton>
<DiscordButton className="text-sm" small />
</div>
</div>
</div>
</div>
<DisclosurePanel className="md:hidden">
{/* <DisclosurePanel className="md:hidden">
<div className="space-y-1 px-2 pt-2 pb-3 sm:px-3">
{navigation.map((item) => (
<DisclosureButton
@@ -101,7 +97,7 @@ export default function Navbar() {
</DisclosureButton>
))}
</div>
</DisclosurePanel>
</DisclosurePanel> */}
</Disclosure>
);
}
@@ -1,2 +1,3 @@
export * from "./landing";
export * from "./landing2";
export * from "./download";
@@ -0,0 +1 @@
export { default } from "./landing2";
@@ -0,0 +1,238 @@
import { DiscordButton } from "../../components/discord-button";
import { motion } from "framer-motion";
const fadeUpVariants = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.6,
delay: 0.2,
ease: "easeOut",
staggerChildren: 0.1,
},
},
};
const Landing = () => {
const videos = [
{
src: "https://www.youtube.com/embed/H4NFXGMuwpY?si=U2_m5Ic1YBn6176D",
},
{
src: "https://www.youtube.com/embed/pGn-1BKo3nY?si=q4dm0ICb6wF1JW8N",
},
{
src: "https://www.youtube.com/embed/7x7IZkHiGD8?si=tL8nK4CULigpfHQR",
},
];
return (
<div className="relative min-h-screen bg-[#101014] text-white bg-dots">
<div className="dotted-pattern absolute inset-0 z-[0] opacity-50" />
{/* Hero Section */}
<div className="relative flex overflow-hidden xl:items-center xl:pt-0 mb-0">
<motion.div
className="w-full flex flex-col items-center justify-center text-center pt-36 px-10"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={fadeUpVariants}
>
<motion.div className="relative" variants={fadeUpVariants}>
<h1 className="relative mb-6 md:mb-10 font-extrabold text-4xl sm:text-[3rem] md:text-[4rem] lg:text-[6rem] !leading-none">
<span className="text-primary">“</span>
Is this really AI?
<span className="text-primary">”</span>
</h1>
<span className="absolute -right-5 bottom-1 md:-right-14 md:bottom-14 text-xl md:text-3xl font-bold opacity-40 italic">
— You
</span>
</motion.div>
</motion.div>
</div>
{/* Hero Section */}
<div className="relative z-10 mx-auto max-w-[100rem] px-4 md:px-16 lg:px-12 xl:px-32 lg:mb-32">
<motion.div
className="items-center gap-16 mb-12 p-4 bg-white/10 backdrop-blur-md rounded-[40px]"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={fadeUpVariants}
>
<div className="rounded-[24px] overflow-hidden bg-[#1C1C20]">
<video
muted
autoPlay
loop
className="w-full aspect-[16/9] object-cover"
>
<source src="/videos/hero-video.mp4" type="video/mp4" />
</video>
</div>
</motion.div>
<motion.div
className="flex justify-center"
variants={fadeUpVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<DiscordButton />
</motion.div>
</div>
<div className="overflow-hidden py-24 sm:py-32">
<motion.div
className="mx-auto max-w-[88rem] md:px-6 lg:px-8"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={fadeUpVariants}
>
<div className="grid grid-cols-1 gap-20 lg:grid-cols-2 lg:items-center">
<motion.div
className="px-6 lg:px-0 lg:pt-4 lg:pr-4"
variants={fadeUpVariants}
>
<div className="max-w-2xl lg:mx-0 mb-10 md:mb-16">
<h2 className="relative font-extrabold text-4xl md:text-5xl lg:text-6xl xl:text-[4.8rem] !leading-tight">
Our tool lets you design, control, and achieve{" "}
<span className="text-primary">great consistency.</span>
</h2>
</div>
<DiscordButton />
</motion.div>
<div className="sm:px-6 lg:px-0">
<div className="relative isolate overflow-hidden bg-indigo-500 sm:mx-auto sm:max-w-2xl sm:rounded-3xl sm:pr-0 lg:mx-0 lg:max-w-none">
<div className="mx-auto max-w-2xl sm:mx-0 sm:max-w-none border-[16px] border-white/10 rounded-3xl overflow-hidden">
<video
src="/videos/artcraft-3d-demo.mp4"
autoPlay
muted
loop
className="aspect-square w-full max-w-none rounded-tl-xl bg-gray-800 ring-1 ring-white/10 object-cover h-full rounded-lg overflow-hidden"
/>
</div>
</div>
</div>
</div>
</motion.div>
</div>
<div className="overflow-hidden md:py-24 sm:py-32">
<motion.div
className="mx-auto max-w-[88rem] md:px-6 lg:px-8"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={fadeUpVariants}
>
<div className="grid grid-cols-1 gap-20 lg:grid-cols-2 lg:items-center">
<div className="sm:px-6 lg:px-0 order-2 lg:order-1">
<motion.div
className="relative isolate overflow-hidden bg-indigo-500 sm:mx-auto sm:max-w-2xl sm:rounded-3xl sm:pr-0 lg:mx-0 lg:max-w-none"
variants={fadeUpVariants}
>
<div className="mx-auto max-w-2xl sm:mx-0 sm:max-w-none border-[16px] border-white/10 rounded-3xl overflow-hidden">
<motion.video
src="/videos/artcraft-canvas-demo.mp4"
autoPlay
muted
loop
className="aspect-square w-full max-w-none rounded-tl-xl bg-gray-800 ring-1 ring-white/10 object-cover h-full rounded-lg overflow-hidden"
variants={fadeUpVariants}
/>
</div>
</motion.div>
</div>
<motion.div
className="px-6 lg:px-0 lg:pt-4 lg:pr-4 order-1 lg:order-2"
variants={fadeUpVariants}
>
<div className=" max-w-2xl lg:mx-0 mb-10 md:mb-16">
<h2 className="relative font-extrabold text-4xl md:text-5xl lg:text-6xl xl:text-[4.8rem] !leading-tight">
<span className="text-primary">Patented</span> Brain to Art
Interface
</h2>
</div>
<DiscordButton />
</motion.div>
</div>
</motion.div>
</div>
<div className="relative z-10 mx-auto max-w-screen px-4 py-32 sm:px-24 lg:px-32">
{/* Videos Section */}
<motion.div
className="space-y-12"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={fadeUpVariants}
>
<div className="text-center">
<h1 className="md:mb-16 text-4xl md:text-7xl font-extrabold">
Made using{" "}
<span className="relative after:absolute after:bottom-0 after:left-0 after:w-full after:h-[5px] md:after:h-[12px] after:bg-primary/60 after:mb-1">
ArtCraft
</span>
</h1>
{/* <p className="text-lg text-gray-300 max-w-2xl mx-auto">
See examples of artwork created using ArtCraft.
</p> */}
</div>
<div className="grid gap-8 xl:grid-cols-3">
{videos.map((video, index) => (
<motion.div
key={index}
className="group relative rounded-2xl bg-white/10 backdrop-blur-md p-1.5 transition-all duration-300 hover:bg-white/20 hover:scale-[1.02] hover:shadow-2xl hover:shadow-primary/20"
variants={fadeUpVariants}
>
<div className="aspect-video overflow-hidden rounded-xl">
<iframe
width="100%"
height="100%"
src={video.src}
title="YouTube video player"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
className="rounded-xl transition-transform duration-300 group-hover:scale-[1.02]"
/>
</div>
<div className="absolute inset-0 rounded-2xl border border-white/10 group-hover:border-white/20 transition-colors duration-300 pointer-events-none" />
</motion.div>
))}
</div>
</motion.div>
</div>
<div className="relative z-10 mx-auto max-w-[1920px] px-4 md:pt-32 md:pb-56 sm:px-24 lg:px-32">
{/* Discord CTA Section */}
<motion.div
className="flex flex-col items-center justify-center text-center p-12 py-20 rounded-[40px] bg-primary/30 backdrop-blur-md border-[6px] border-primary/60"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={fadeUpVariants}
>
<h2 className="relative mb-12 font-extrabold text-4xl lg:text-6xl max-w-3xl !leading-tight">
Why haven't you joined our Discord yet?
</h2>
{/* <p className="text-lg text-gray-400 mb-8 max-w-2xl">
Connect with other creators, share your work, get feedback, and stay
updated with the latest features and updates.
</p> */}
<DiscordButton />
</motion.div>
</div>
<div></div>
</div>
);
};
export default Landing;
+3
View File
@@ -51,6 +51,9 @@
},
{
"path": "../../libs/tauri-utils/tsconfig.lib.json"
},
{
"path": "../editor3d"
}
]
}
+3
View File
@@ -25,6 +25,9 @@
{
"path": "../../libs/tauri-utils"
},
{
"path": "../editor3d"
},
{
"path": "./tsconfig.app.json"
},
+40
View File
@@ -16,6 +16,7 @@
"@headlessui/react": "^2.2.2",
"@preact/signals-react": "^3.0.1",
"@remix-run/serve": "^2.15.0",
"framer-motion": "^12.11.0",
"pnpm": "^10.8.1",
"react": "18.3.1",
"react-device-detect": "^2.2.3",
@@ -18610,6 +18611,32 @@
"url": "https://github.com/sponsors/rawify"
}
},
"node_modules/framer-motion": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.11.0.tgz",
"integrity": "sha512-BaBPmkhaC2l0n619Kt1nQaxSdUdyyz5V1Z7EKJ1CcraOTZitgVx0RTbL8lmg2XesaFi6o8MPBIhkWDIvzDpGaQ==",
"dependencies": {
"motion-dom": "^12.11.0",
"motion-utils": "^12.9.4",
"tslib": "^2.4.0"
},
"peerDependencies": {
"@emotion/is-prop-valid": "*",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/is-prop-valid": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -22987,6 +23014,19 @@
"node": ">= 0.8"
}
},
"node_modules/motion-dom": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.11.0.tgz",
"integrity": "sha512-CItkGYJenn5ZsbzTX0D9mE0UWdjdd9r535FrxEXhzR8Kwa9I2dLr1uhEJgQPWbgaIJ6i0sNFnf2T9NvVDWQVBw==",
"dependencies": {
"motion-utils": "^12.9.4"
}
},
"node_modules/motion-utils": {
"version": "12.9.4",
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.9.4.tgz",
"integrity": "sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg=="
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+1
View File
@@ -8,6 +8,7 @@
"@headlessui/react": "^2.2.2",
"@preact/signals-react": "^3.0.1",
"@remix-run/serve": "^2.15.0",
"framer-motion": "^12.11.0",
"pnpm": "^10.8.1",
"react": "18.3.1",
"react-device-detect": "^2.2.3",