inspiration-app/Docs/design/library-layouts.tsx

377 lines
14 KiB
TypeScript

import React, { useState } from 'react';
import { Search, Grid, List, User, Plus, FolderOpen, Image, Upload } from 'lucide-react';
const InspirationEngine = () => {
const [activeView, setActiveView] = useState('library');
const [showDropzone, setShowDropzone] = useState(false);
// Warm Creative Palette
const colors = {
bg: '#1c1917',
surface: '#292524',
text: '#fafaf9',
textMuted: '#a8a29e',
border: '#44403c',
primary: '#f97316',
primaryHover: '#ea580c',
accent: '#fbbf24'
};
// Mock data for library items
const mockItems = [
{ id: 1, height: 200, width: 'normal' },
{ id: 2, height: 280, width: 'wide' },
{ id: 3, height: 160, width: 'normal' },
{ id: 4, height: 240, width: 'normal' },
{ id: 5, height: 200, width: 'normal' },
{ id: 6, height: 300, width: 'wide' },
{ id: 7, height: 180, width: 'normal' },
{ id: 8, height: 220, width: 'normal' },
{ id: 9, height: 260, width: 'wide' },
{ id: 10, height: 190, width: 'normal' },
{ id: 11, height: 240, width: 'normal' },
{ id: 12, height: 200, width: 'wide' },
{ id: 13, height: 220, width: 'normal' },
{ id: 14, height: 180, width: 'normal' },
{ id: 15, height: 260, width: 'normal' },
{ id: 16, height: 200, width: 'wide' },
{ id: 17, height: 240, width: 'normal' },
{ id: 18, height: 180, width: 'normal' },
];
// Mock data for collections
const mockCollections = [
{ id: 1, name: 'Brand Identity', itemCount: 47, preview: [colors.primary, colors.accent, colors.primaryHover, colors.primary] },
{ id: 2, name: 'UI Inspiration', itemCount: 132, preview: [colors.accent, colors.primary, colors.accent, colors.primaryHover] },
{ id: 3, name: 'Typography', itemCount: 28, preview: [colors.primaryHover, colors.primary, colors.accent, colors.primary] },
{ id: 4, name: 'Color Palettes', itemCount: 64, preview: [colors.primary, colors.primaryHover, colors.accent, colors.primary] },
{ id: 5, name: 'Illustration', itemCount: 89, preview: [colors.accent, colors.primary, colors.primaryHover, colors.accent] },
{ id: 6, name: 'Photography', itemCount: 156, preview: [colors.primary, colors.accent, colors.primary, colors.primaryHover] },
{ id: 7, name: 'Web Design', itemCount: 93, preview: [colors.primaryHover, colors.accent, colors.primary, colors.accent] },
{ id: 8, name: 'Motion Graphics', itemCount: 41, preview: [colors.primary, colors.primaryHover, colors.accent, colors.primary] },
];
const LibraryView = () => (
<>
{/* Compact Horizontal Filters Toolbar */}
<div className="px-8 py-3 flex items-center gap-2 border-b" style={{ borderColor: colors.border }}>
<button
className="px-3 py-2 flex items-center gap-2 text-sm hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.textMuted
}}
>
<Grid size={14} />
Filter
</button>
<button
className="px-3 py-2 flex items-center gap-2 text-sm hover:opacity-90 transition-all font-medium"
style={{
backgroundColor: colors.primary,
color: '#fff'
}}
>
All Items
<span className="text-xs opacity-70"></span>
</button>
<button
className="px-3 py-2 flex items-center gap-2 text-sm hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.textMuted
}}
>
Source
<span className="text-xs opacity-70"></span>
</button>
<button
className="px-3 py-2 flex items-center gap-2 text-sm hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.textMuted
}}
>
Media type
<span className="text-xs opacity-70"></span>
</button>
<button
className="px-3 py-2 flex items-center gap-2 text-sm hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.textMuted
}}
>
Date added
<span className="text-xs opacity-70"></span>
</button>
<button
className="px-3 py-2 flex items-center gap-2 text-sm hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.textMuted
}}
>
Tags
<span className="text-xs opacity-70"></span>
</button>
<div className="flex-1" />
<span className="text-sm font-medium" style={{ color: colors.textMuted }}>
1,427 items
</span>
<button
className="px-3 py-2 hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.text
}}
>
<Grid size={16} />
</button>
<button
className="px-3 py-2 hover:opacity-80 transition-all"
style={{
backgroundColor: colors.surface,
color: colors.textMuted
}}
>
<List size={16} />
</button>
</div>
{/* Main Content - Tightly Packed Masonry Grid */}
<main className="flex-1 overflow-auto">
<div className="columns-5 gap-0.5">
{mockItems.map((item, index) => {
const demoColors = [colors.primary, colors.accent, colors.surface, colors.primaryHover];
const itemColor = demoColors[index % demoColors.length];
return (
<div
key={item.id}
className="mb-0.5 break-inside-avoid group cursor-pointer relative overflow-hidden transition-all hover:opacity-90"
style={{
height: `${item.height}px`,
backgroundColor: itemColor
}}
>
<div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-60 transition-all flex items-center justify-center opacity-0 group-hover:opacity-100">
<button
className="px-4 py-2 text-sm font-medium hover:scale-105 transition-transform"
style={{ backgroundColor: colors.text, color: colors.bg }}
>
View Details
</button>
</div>
</div>
);
})}
</div>
</main>
</>
);
const CollectionsView = () => (
<>
{/* Collections Toolbar */}
<div className="px-8 py-4 flex items-center justify-between border-b" style={{ borderColor: colors.border }}>
<div className="flex items-center gap-3">
<h2 className="text-xl font-bold">Your Collections</h2>
<span className="text-sm" style={{ color: colors.textMuted }}>
{mockCollections.length} collections
</span>
</div>
<button
className="px-4 py-2 flex items-center gap-2 text-sm font-medium hover:opacity-90 transition-all"
style={{
backgroundColor: colors.primary,
color: '#fff'
}}
>
<Plus size={16} />
New Collection
</button>
</div>
{/* Collections Grid */}
<main className="flex-1 overflow-auto">
<div className="grid grid-cols-4 gap-0.5">
{mockCollections.map(collection => (
<div
key={collection.id}
className="group cursor-pointer relative"
>
{/* Collection Preview Grid */}
<div
className="aspect-square overflow-hidden transition-all hover:opacity-90"
style={{
backgroundColor: colors.surface
}}
>
<div className="grid grid-cols-2 grid-rows-2 h-full gap-0">
{collection.preview.map((color, idx) => (
<div
key={idx}
style={{
backgroundColor: color
}}
/>
))}
</div>
{/* Hover Overlay with Info */}
<div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-70 transition-all flex flex-col items-center justify-center opacity-0 group-hover:opacity-100 p-4">
<h3 className="font-bold text-base mb-2 text-center" style={{ color: colors.text }}>
{collection.name}
</h3>
<div className="flex items-center gap-2 text-sm mb-4" style={{ color: colors.textMuted }}>
<Image size={14} />
<span>{collection.itemCount} items</span>
</div>
<button
className="px-4 py-2 text-sm font-medium hover:scale-105 transition-transform"
style={{ backgroundColor: colors.text, color: colors.bg }}
>
Open Collection
</button>
</div>
</div>
</div>
))}
{/* Create New Collection Card */}
<div
className="aspect-square cursor-pointer transition-all hover:opacity-80 flex flex-col items-center justify-center gap-3"
style={{
backgroundColor: colors.surface
}}
>
<div
className="w-12 h-12 flex items-center justify-center"
style={{
backgroundColor: colors.primary,
color: '#fff'
}}
>
<Plus size={24} />
</div>
<span className="font-medium text-sm" style={{ color: colors.textMuted }}>
Create Collection
</span>
</div>
</div>
</main>
</>
);
return (
<div className="w-full h-screen flex flex-col" style={{ backgroundColor: colors.bg, color: colors.text }}>
{/* Header */}
<header className="border-b" style={{ borderColor: colors.border }}>
<div className="px-8 py-6 flex items-center justify-between">
<div className="text-2xl font-bold tracking-tight">INSPIRATION</div>
{/* Prominent Central Search with Image Toggle */}
<div className="flex-1 max-w-2xl mx-12 flex gap-3">
<div className="relative flex-1">
<Search
className="absolute left-4 top-1/2 -translate-y-1/2"
style={{ color: colors.textMuted }}
size={20}
/>
<input
type="text"
placeholder="Search by idea, concept, or visual..."
className="w-full py-4 pl-12 pr-4 text-base transition-all"
style={{
backgroundColor: colors.surface,
color: colors.text,
border: 'none',
outline: 'none'
}}
/>
</div>
<button
onClick={() => setShowDropzone(!showDropzone)}
className="px-4 py-4 hover:opacity-90 transition-all"
style={{
backgroundColor: showDropzone ? colors.primary : colors.surface,
color: showDropzone ? '#fff' : colors.textMuted
}}
title="Search by image"
>
<Image size={20} />
</button>
</div>
<nav className="flex items-center gap-6">
<button
onClick={() => setActiveView('library')}
className="hover:opacity-70 transition-opacity font-medium"
style={{ color: activeView === 'library' ? colors.text : colors.textMuted }}
>
Library
</button>
<button
onClick={() => setActiveView('collections')}
className="hover:opacity-70 transition-opacity font-medium"
style={{ color: activeView === 'collections' ? colors.text : colors.textMuted }}
>
Collections
</button>
<button className="hover:opacity-70 transition-opacity">
<User size={22} style={{ color: colors.textMuted }} />
</button>
</nav>
</div>
{/* Expandable Image Search Dropzone */}
{showDropzone && (
<div className="px-8 pb-6">
<div
className="p-8 text-center cursor-pointer hover:opacity-80 transition-all"
style={{ backgroundColor: colors.surface }}
>
<Upload size={32} style={{ color: colors.primary, margin: '0 auto 12px' }} />
<p className="font-medium mb-2" style={{ color: colors.text }}>
Drop your image to search
</p>
<p className="text-sm mb-4" style={{ color: colors.textMuted }}>
Drag and drop, or click to browse
</p>
<div className="flex gap-3 justify-center">
<button
className="px-4 py-2 text-sm font-medium hover:opacity-90 transition-all"
style={{ backgroundColor: colors.primary, color: '#fff' }}
>
Choose File
</button>
<button
className="px-4 py-2 text-sm font-medium hover:opacity-80 transition-all"
style={{ backgroundColor: colors.bg, color: colors.textMuted }}
>
Paste URL
</button>
</div>
</div>
</div>
)}
</header>
{/* Active View */}
{activeView === 'library' ? <LibraryView /> : <CollectionsView />}
</div>
);
};
export default InspirationEngine;