public: hero improvements

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-03-14 07:00:11 +01:00
parent f276deeeeb
commit d3a57178b6
15 changed files with 179 additions and 57 deletions

View File

@@ -0,0 +1,20 @@
import { Navbar } from '../navbar';
interface Props {
children: React.ReactNode;
}
export default function Layout({ children }: Props) {
return (
<>
<Navbar darkText />
<div
className="opacity-50 w-full h-screen text-blue-950 bg-[radial-gradient(circle_at_2px_2px,#D9DEF6_2px,transparent_0)] absolute top-0 left-0 right-0 z-0"
style={{
backgroundSize: '70px 70px',
}}
/>
<div className="relative">{children}</div>
</>
);
}

View File

@@ -1,4 +1,4 @@
import { Heading1 } from '../copy';
import { Heading1 } from '../../copy';
export const dynamic = 'force-dynamic';
export const revalidate = 3600;

View File

@@ -1,4 +1,4 @@
import { Heading1 } from '../copy';
import { Heading1 } from '../../copy';
export const dynamic = 'force-dynamic';
export const revalidate = 3600;

View File

@@ -1,8 +1,12 @@
import { Tooltip, TooltipContent } from '@/components/ui/tooltip';
import { TooltipTrigger } from '@radix-ui/react-tooltip';
import Image from 'next/image';
import { PreviewCarousel } from './carousel';
import { Heading1, Lead2 } from './copy';
import { JoinWaitlistHero } from './join-waitlist-hero';
import { SocialProofServer } from './social-proof';
import { SocialProof } from './social-proof/social-proof';
const avatars = [
'https://api.dicebear.com/7.x/adventurer/svg?seed=Chester&backgroundColor=b6e3f4',
@@ -10,7 +14,7 @@ const avatars = [
'https://api.dicebear.com/7.x/adventurer/svg?seed=Boo&backgroundColor=ffdfbf',
];
export function Hero({ waitlistCount }: { waitlistCount: number }) {
export function Hero() {
return (
<div className="flex py-32 flex-col items-center w-full text-center bg-[#1F54FF] relative overflow-hidden">
{/* <div className="inset-0 absolute h-full w-full bg-[radial-gradient(circle,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%)]"></div> */}
@@ -37,16 +41,12 @@ export function Hero({ waitlistCount }: { waitlistCount: number }) {
alternative to Mixpanel
</Heading1>
<Lead2 className="text-white/70 font-light">
Mixpanel + Plausible = <span className="text-white">Openpanel!</span>{' '}
<br />A simple analytics tool that your wallet can afford.
The power of Mixpanel, the ease of Plausible <br />
and nothing from Google Analytics 😉
</Lead2>
<div className="my-12 w-full flex flex-col items-center">
<JoinWaitlistHero />
<div className="mt-6 flex justify-center items-center">
<p className="text-white">
{waitlistCount} people have already signed up! 🚀
</p>
</div>
<SocialProofServer className="mt-6" />
</div>
</div>

View File

@@ -25,14 +25,14 @@ export function JoinWaitlistHero({ className }: JoinWaitlistProps) {
useEffect(() => {
if (open) {
// @ts-ignore
window.op('event', 'waitlist_open');
window.op?.('event', 'waitlist_open');
}
}, [open]);
useEffect(() => {
if (success) {
// @ts-ignore
window.op('event', 'waitlist_success', {
window.op?.('event', 'waitlist_success', {
email: value,
});
}
@@ -113,15 +113,23 @@ export function JoinWaitlistHero({ className }: JoinWaitlistProps) {
>
Join waitlist now
</Button>
<Link
href="https://dashboard.openpanel.dev/share/overview/ZQsEhG"
target="_blank"
rel="nofollow"
>
<Button size="lg" variant="outline" className="text-lg h-12">
Demo
</Button>
</Link>
<div className="relative">
<Link
href="https://dashboard.openpanel.dev/share/overview/ZQsEhG"
target="_blank"
rel="nofollow"
>
<Button size="lg" variant="outline" className="text-lg h-12">
Demo
</Button>
</Link>
<img
src="/clickable-demo.png"
className="w-44 shrink-0 absolute left-full -top-8 translate-x-10 max-w-none"
alt="Clickable demo button"
/>
</div>
</div>
</>
);

View File

@@ -35,39 +35,10 @@ export default function RootLayout({
font.className
)}
>
<div
className="w-full h-screen text-blue-950 bg-[radial-gradient(circle_at_2px_2px,#D9DEF6_2px,transparent_0)] absolute top-0 left-0 right-0 z-0"
style={{
backgroundSize: '70px 70px',
}}
/>
<div className="relative">{children}</div>
{children}
<Footer />
</body>
<Script
src="https://openpanel.dev/op.js"
async
defer
strategy="afterInteractive"
/>
<Script
id="openpanel"
dangerouslySetInnerHTML={{
__html: `
window.op =
window.op ||
function (...args) {
(window.op.q = window.op.q || []).push(args);
};
window.op('ctor', {
clientId: '301c6dc1-424c-4bc3-9886-a8beab09b615',
trackScreenViews: true,
trackOutgoingLinks: true,
trackAttributes: true,
});
`,
}}
/>
{/* 301c6dc1-424c-4bc3-9886-a8beab09b615 */}
</html>
);
}

View File

@@ -0,0 +1,34 @@
'use client';
import { Logo } from '@/components/Logo';
import { cn } from '@/utils/cn';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
interface Props {
darkText?: boolean;
className?: string;
}
export function Navbar({ darkText = false, className }: Props) {
const pathname = usePathname();
const textColor = darkText ? 'text-blue-dark' : 'text-white';
return (
<div
className={cn('absolute top-0 left-0 right-0 z-10', textColor, className)}
>
<div className="container flex justify-between items-center py-4">
<Logo />
<nav className="flex gap-4">
{pathname !== '/' && <Link href="/">Home</Link>}
<a href="https://docs.openpanel.dev" target="_blank">
Docs
</a>
<a href="https://dashboard.openpanel.dev" target="_blank">
Sign in
</a>
</nav>
</div>
</div>
);
}

View File

@@ -1,18 +1,18 @@
import { db } from '@openpanel/db';
import { PreviewCarousel } from './carousel';
import { Heading2, Lead2, Paragraph } from './copy';
import { Hero } from './hero';
import { Navbar } from './navbar';
import { Sections } from './section';
export const dynamic = 'force-dynamic';
export const revalidate = 3600;
export default async function Page() {
const waitlistCount = await db.waitlist.count();
export default function Page() {
return (
<div>
<Hero waitlistCount={waitlistCount} />
<Navbar darkText={false} className="[&_img]:hidden" />
<Hero />
<div className="container">
<div className="my-24">
<Heading2 className="md:text-5xl mb-2 leading-none">

View File

@@ -0,0 +1,17 @@
import { TooltipProvider } from '@/components/ui/tooltip';
import { db } from '@openpanel/db';
import { SocialProof } from './social-proof';
interface Props {
className?: string;
}
export async function SocialProofServer(props: Props) {
const waitlistCount = await db.waitlist.count();
return (
<TooltipProvider>
<SocialProof count={waitlistCount} {...props} />;
</TooltipProvider>
);
}

View File

@@ -0,0 +1,72 @@
'use client';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { cn } from '@/utils/cn';
import Image from 'next/image';
interface JoinWaitlistProps {
className?: string;
count: number;
}
export function SocialProof({ className, count }: JoinWaitlistProps) {
return (
<div className={cn('flex gap-2 justify-center items-center', className)}>
<div className="flex">
<Tooltip>
<TooltipTrigger>
<Image
className="rounded-full"
src="/clickhouse.png"
width={24}
height={24}
alt="Clickhouse"
/>
</TooltipTrigger>
<TooltipContent>Clickhouse is here</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger className="-mx-3">
<Image
className="rounded-full"
src="/getdreams.png"
width={24}
height={24}
alt="GetDreams"
/>
</TooltipTrigger>
<TooltipContent>GetDreams is here</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger>
<Image
className="rounded-full"
src="/kiddokitchen.png"
width={24}
height={24}
alt="KiddoKitchen"
/>
</TooltipTrigger>
<TooltipContent>KiddoKitchen is here</TooltipContent>
</Tooltip>
</div>
<p className="text-white">
{count} early birds have already signed up! 🚀
</p>
</div>
);
}

View File

@@ -37,7 +37,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-100%] md:translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',
className
)}
{...props}