Skip to content
Merged
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
180 changes: 72 additions & 108 deletions apps/playground/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,34 @@ export const Home = () => {

return (
<div className="min-h-screen bg-background text-foreground">
{/* Hero Section */}
<header className="bg-white/80 backdrop-blur-md border-b border-gray-200/50 sticky top-0 z-20 shadow-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="bg-primary p-2 rounded-xl shadow-lg">
<Box className="w-5 h-5 text-primary-foreground" />
{/* Header */}
<header className="bg-background border-b border-border sticky top-0 z-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-14 flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="bg-primary p-1.5 rounded-lg">
<Box className="w-4 h-4 text-primary-foreground" />
</div>
<span className="font-bold text-xl tracking-tight">Object UI Studio</span>
<span className="font-semibold text-base">Object UI Studio</span>
</div>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<button
onClick={() => navigate('/studio/new')}
className="flex items-center gap-2 px-4 py-2 text-sm font-semibold bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg transition-all shadow-sm hover:shadow"
className="flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium bg-primary text-primary-foreground hover:bg-primary/90 rounded-md transition-colors"
>
<Plus className="w-4 h-4" />
New Design
New
</button>
<button
onClick={() => navigate('/my-designs')}
className="flex items-center gap-2 px-4 py-2 text-sm font-semibold bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border rounded-lg transition-all shadow-sm hover:shadow"
className="flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium hover:bg-muted rounded-md transition-colors"
>
<FolderOpen className="w-4 h-4" />
My Designs
</button>
<a
href="https://github.com/objectql/objectui"
target="_blank"
className="flex items-center gap-2 px-4 py-2 text-sm font-medium bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border rounded-lg transition-all shadow-sm hover:shadow"
className="flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium hover:bg-muted rounded-md transition-colors"
>
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" />
Expand All @@ -58,122 +58,86 @@ export const Home = () => {
</div>
</header>

<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="text-center mb-20 relative">
{/* Decorative elements */}
<div className="absolute inset-0 -z-10 overflow-hidden">
<div className="absolute top-0 left-1/4 w-96 h-96 bg-muted/20 rounded-full blur-3xl opacity-30 animate-pulse"></div>
<div className="absolute top-20 right-1/4 w-80 h-80 bg-muted/30 rounded-full blur-3xl opacity-30 animate-pulse"></div>
</div>

<div className="inline-flex items-center gap-2 px-4 py-2 bg-muted border border-border rounded-full text-sm font-semibold text-muted-foreground mb-6 shadow-sm">
<span className="relative flex h-2 w-2">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
<span className="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
</span>
Interactive Visual Editor
</div>

<h1 className="text-5xl md:text-6xl lg:text-7xl font-black tracking-tight mb-6 leading-tight">
Build Stunning Interfaces,<br />
<span className="text-primary">Purely from JSON.</span>
</h1>
<p className="max-w-2xl mx-auto text-xl text-muted-foreground leading-relaxed mb-8">
Object UI transforms JSON schemas into fully functional, accessible, and responsive React applications.
<br className="hidden sm:block" />
<span className="font-semibold">Select a template below or start from scratch.</span>
</p>

<div className="flex justify-center gap-4">
<button
onClick={() => navigate('/studio/new')}
className="flex items-center gap-2 px-6 py-3 text-lg font-bold bg-primary text-primary-foreground hover:bg-primary/90 rounded-xl shadow-lg transition-all transform hover:scale-105"
>
<Plus className="w-5 h-5" />
Start New Design
</button>
<button
onClick={() => navigate('/my-designs')}
className="flex items-center gap-2 px-6 py-3 text-lg font-bold bg-secondary text-secondary-foreground hover:bg-secondary/80 border-2 border-border rounded-xl shadow-lg transition-all transform hover:scale-105"
>
<FolderOpen className="w-5 h-5" />
Open Saved
</button>
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
{/* Quick Actions */}
<div className="mb-6">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-semibold">Quick Start</h2>
<div className="flex items-center gap-2">
<button
onClick={() => navigate('/my-designs')}
className="flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium hover:bg-muted rounded-md transition-colors"
>
<FolderOpen className="w-4 h-4" />
Open Saved
</button>
</div>
</div>
</div>

{/* Category Filter */}
<div className="flex flex-wrap justify-center gap-3 mb-16">
{Object.keys(exampleCategories).map((category) => (
<button
key={category}
onClick={() => setActiveCategory(category)}
className={`
group flex items-center gap-2 px-5 py-2.5 rounded-xl text-sm font-semibold transition-all duration-200
${activeCategory === category
? 'bg-primary text-primary-foreground shadow-lg scale-105'
: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-2 border-border hover:shadow-md'}
`}
>
<CategoryIcon name={category} />
{category}
{activeCategory === category && (
<span className="ml-1 px-2 py-0.5 bg-primary-foreground/20 rounded-full text-xs font-bold">
{exampleCategories[category as keyof typeof exampleCategories].length}
<div className="mb-4">
<div className="flex items-center gap-2 border-b border-border">
{Object.keys(exampleCategories).map((category) => (
<button
key={category}
onClick={() => setActiveCategory(category)}
className={`
flex items-center gap-1.5 px-3 py-2 text-sm font-medium transition-colors border-b-2 -mb-px
${activeCategory === category
? 'border-primary text-primary'
: 'border-transparent text-muted-foreground hover:text-foreground hover:border-border'}
`}
>
<CategoryIcon name={category} />
{category}
<span
className={`text-xs ${activeCategory === category ? 'text-primary' : 'text-muted-foreground'}`}
>
({exampleCategories[category as keyof typeof exampleCategories].length})
</span>
)}
</button>
))}
</button>
))}
</div>
</div>

{/* Examples Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Templates Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{exampleCategories[activeCategory as keyof typeof exampleCategories].map((key) => {
// Try to parse the example to get a description or just format the title
const title = key.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');

return (
<div
key={key}
onClick={() => navigate(`/${key}`)}
className="group relative bg-card rounded-2xl border-2 border-border overflow-hidden hover:shadow-2xl transition-all duration-300 cursor-pointer hover:border-primary hover:-translate-y-1 flex flex-col h-72"
onClick={() => navigate(`/studio/${key}`)}
className="group bg-card rounded-lg border border-border overflow-hidden hover:border-primary hover:shadow-md transition-all cursor-pointer"
>
{/* Overlay on hover */}
<div className="absolute inset-0 bg-primary/0 group-hover:bg-primary/5 transition-all duration-500 pointer-events-none z-10"></div>

{/* Mock Preview Window */}
<div className="bg-muted border-b border-border p-6 flex-1 flex items-center justify-center overflow-hidden relative">
{/* Decorative grid */}
<div className="absolute inset-0 opacity-20 bg-dot-pattern-sm"></div>

<div className="relative w-3/4 h-3/4 bg-card shadow-xl border-2 border-border rounded-xl flex flex-col group-hover:scale-110 transition-transform duration-500">
<div className="h-5 border-b-2 border-border bg-muted flex items-center px-2 gap-1.5 rounded-t-xl">
<div className="w-2 h-2 rounded-full bg-red-500 shadow-sm"></div>
<div className="w-2 h-2 rounded-full bg-yellow-500 shadow-sm"></div>
<div className="w-2 h-2 rounded-full bg-green-500 shadow-sm"></div>
</div>
<div className="flex-1 p-3">
<div className="space-y-2.5">
<div className="h-2.5 bg-muted rounded-full w-1/2 animate-pulse"></div>
<div className="h-2.5 bg-muted rounded-full w-3/4 animate-pulse [animation-delay:75ms]"></div>
<div className="h-2.5 bg-muted rounded-full w-full animate-pulse [animation-delay:150ms]"></div>
</div>
{/* Preview */}
<div className="bg-muted p-4 aspect-video flex items-center justify-center border-b border-border">
<div className="w-full h-full bg-background rounded border border-border flex flex-col shadow-sm">
<div className="h-4 border-b border-border bg-muted flex items-center px-1.5 gap-1">
<div className="w-1.5 h-1.5 rounded-full bg-red-500"></div>
<div className="w-1.5 h-1.5 rounded-full bg-yellow-500"></div>
<div className="w-1.5 h-1.5 rounded-full bg-green-500"></div>
</div>
<div className="flex-1 p-2">
<div className="space-y-1.5">
<div className="h-1.5 bg-muted rounded w-1/2"></div>
<div className="h-1.5 bg-muted rounded w-3/4"></div>
<div className="h-1.5 bg-muted rounded w-full"></div>
</div>
</div>
</div>
</div>

<div className="p-6 relative z-10 bg-card border-t border-border">
<h3 className="text-lg font-bold group-hover:text-primary transition-colors mb-2">
{/* Info */}
<div className="p-3">
<h3 className="text-sm font-medium group-hover:text-primary transition-colors mb-1">
{title}
</h3>
<div className="flex items-center justify-between">
<div className="flex items-center text-sm font-semibold text-muted-foreground group-hover:text-primary transition-colors">
Launch Studio
<ArrowRight className="w-4 h-4 ml-2 transform group-hover:translate-x-2 transition-transform" />
</div>
<div className="px-3 py-1 bg-muted text-muted-foreground rounded-full text-xs font-bold group-hover:bg-primary group-hover:text-primary-foreground transition-colors">
Try Now
</div>
<div className="flex items-center text-xs text-muted-foreground">
<span>Open in Studio</span>
<ArrowRight className="w-3 h-3 ml-1 group-hover:translate-x-0.5 transition-transform" />
</div>
</div>
</div>
Expand Down
Loading