feat: new design

This commit is contained in:
Nik L
2026-04-13 13:09:46 -04:00
parent 14fcaea830
commit b2879e1a5e
34 changed files with 573 additions and 608 deletions

View File

@@ -1,7 +1,7 @@
'use client'
import { useState, FormEvent } from 'react'
import { Puzzle, Gavel, Coins, Building2, Check } from 'lucide-react'
import { Gavel, Coins, Building2, Puzzle } from 'lucide-react'
import { BetaSignup } from './beta-signup'
const plugins = [
{
@@ -26,65 +26,19 @@ const plugins = [
},
]
type Mode = 'button' | 'input' | 'submitting' | 'success' | 'error'
export function Waitlist() {
const [mode, setMode] = useState<Mode>('button')
const [email, setEmail] = useState('')
const [error, setError] = useState('')
async function onSubmit(e: FormEvent<HTMLFormElement>) {
e.preventDefault()
if (mode === 'submitting') return
setMode('submitting')
setError('')
try {
const res = await fetch('https://api.web3forms.com/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
access_key: '85d3252e-5890-450c-aa93-12dc89c7c9b5',
subject: 'Greywall enterprise / plugin SDK waitlist',
from_name: 'Greywall waitlist',
email,
message: '(waitlist section signup)',
botcheck: '',
}),
})
const data = await res.json()
if (data.success) {
setMode('success')
setEmail('')
} else {
setMode('error')
setError(data.message || 'Something went wrong. Try again?')
}
} catch {
setMode('error')
setError('Network error. Try again?')
}
}
return (
<section id="waitlist" className="py-24 px-4 sm:px-6 border-t border-border/30">
<div className="mx-auto max-w-5xl">
<div className="max-w-2xl mb-10">
<div className="flex items-center gap-2 mb-4">
<Puzzle className="h-4 w-4 text-primary" />
<span className="text-xs font-sans uppercase tracking-wider text-primary font-medium">
Plugin SDK &middot; Beta
</span>
</div>
<h2 className="font-serif text-3xl sm:text-4xl font-semibold tracking-tight mb-4">
<span className="text-serif text-[12px] font-bold uppercase tracking-[0.22em] text-primary mb-4 block">
Plugin SDK &middot; Beta
</span>
<h2 className="title-serif text-[36px] md:text-[48px] leading-none mb-4">
Extend Greyproxy.
</h2>
<p className="text-muted-foreground font-serif text-lg leading-relaxed">
We&apos;re building a plugin SDK on top of Greyproxy, and we&apos;ll help you
build the plugins you need on top of it.
<p className="text-serif font-normal text-[15px] md:text-[16px] leading-[1.55] text-muted-foreground">
We&apos;re building a plugin layer on top of GreyProxy for teams that need custom policy logic and shared operational controls.
</p>
</div>
@@ -96,7 +50,7 @@ export function Waitlist() {
className="p-4 sm:p-6 rounded-lg border border-border/40 bg-card/30"
>
<div className="flex items-center gap-3 mb-3">
<p.icon className="h-5 w-5 text-primary" />
<p.icon className="h-5 w-5 text-foreground" />
<h3 className="font-sans font-semibold text-sm">{p.title}</h3>
</div>
<p className="text-sm text-muted-foreground font-serif leading-relaxed">
@@ -110,55 +64,22 @@ export function Waitlist() {
<div className="mb-12 p-5 rounded-lg border border-primary/15 bg-primary/[0.03]">
<p className="text-sm text-muted-foreground font-serif leading-relaxed">
<span className="text-primary font-medium">Core stays free and open source.</span>{' '}
Sandbox, Greyproxy, and the dashboard stay Apache 2.0 forever. Plugin SDK and
enterprise ride on top.
Sandbox, GreyProxy, and the dashboard stay Apache 2.0. Team controls and plugins sit on top of that base.
</p>
</div>
{/* Waitlist CTA */}
<div className="flex flex-col items-center gap-2">
{mode === 'button' && (
<button
onClick={() => setMode('input')}
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md bg-primary text-primary-foreground font-sans text-sm font-medium hover:bg-primary/90 transition-colors cursor-pointer"
>
Join closed beta
<span aria-hidden="true">&rarr;</span>
</button>
)}
{(mode === 'input' || mode === 'submitting') && (
<form onSubmit={onSubmit} className="flex items-center gap-2">
<input
type="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@company.com"
autoFocus
className="rounded-md border border-border/40 bg-background/40 px-4 py-2.5 text-sm font-sans text-foreground placeholder:text-muted-foreground/60 focus:outline-none focus:border-primary/40 transition-colors w-56 sm:w-64"
/>
<button
type="submit"
disabled={mode === 'submitting'}
className="px-4 py-2.5 rounded-md bg-primary text-primary-foreground font-sans text-sm font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
{mode === 'submitting' ? '...' : 'Join'}
</button>
</form>
)}
{mode === 'success' && (
<div className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md border border-primary/20 bg-primary/[0.05] font-sans text-sm text-primary font-medium">
<Check className="h-4 w-4" />
You&apos;re on the list.
</div>
)}
{mode === 'error' && (
<p className="text-xs text-red-400/80 font-sans text-center">{error}</p>
)}
<p className="text-xs text-muted-foreground/60 font-serif">
No spam. Just one email when it&apos;s ready.
</p>
</div>
<BetaSignup
subject="Greywall enterprise / plugin SDK waitlist"
message="(waitlist section signup)"
buttonClassName="px-5 py-2.5 font-sans text-sm font-medium md:text-sm"
inputClassName="w-56 rounded-md border border-border/40 bg-background/40 px-4 py-2.5 text-sm font-sans text-foreground placeholder:text-muted-foreground/60 transition-colors focus:border-primary/40 focus:outline-none sm:w-64"
submitClassName="px-4 py-2.5 font-sans text-sm font-medium md:text-sm"
helperTextClassName="text-xs text-muted-foreground/60 font-serif"
successClassName="inline-flex items-center gap-2 px-5 py-2.5 rounded-md border border-primary/20 bg-primary/[0.05] font-sans text-sm text-primary font-medium"
errorClassName="text-xs text-red-400/80 font-sans text-center"
wrapperClassName="flex flex-col items-center gap-2"
/>
</div>
</section>
)