init elas atelier #1

Merged
nvrl merged 82 commits from ela into main 2026-05-18 13:55:42 +02:00
2 changed files with 41 additions and 22 deletions
Showing only changes of commit 5c106b7e28 - Show all commits
@@ -58,12 +58,13 @@ export default function AssetsButton({
aria-label="Asset library" aria-label="Asset library"
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
> >
<div className="absolute inset-0 bg-crust/80 backdrop-blur-md" aria-hidden="true" /> <div className="absolute inset-0 bg-[var(--crust)]/80 backdrop-blur-md" aria-hidden="true" />
<div <div
className="relative w-full max-w-5xl max-h-[90vh] bg-mantle border border-surface1 rounded-2xl shadow-2xl overflow-hidden flex flex-col animate-in fade-in slide-in-from-bottom-4 duration-200" className="relative w-full max-w-5xl max-h-[90vh] bg-[var(--base)] border border-[var(--surface2)] shadow-2xl overflow-hidden flex flex-col animate-in fade-in slide-in-from-bottom-4 duration-200"
style={{ borderRadius: 2 }}
onClick={e => e.stopPropagation()} onClick={e => e.stopPropagation()}
> >
<div className="flex items-center justify-between px-5 py-4 border-b border-surface1"> <div className="flex items-center justify-between px-5 py-4 border-b border-[var(--surface2)]/60">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -75,20 +76,21 @@ export default function AssetsButton({
strokeWidth="2" strokeWidth="2"
strokeLinecap="round" strokeLinecap="round"
strokeLinejoin="round" strokeLinejoin="round"
className="text-mauve" className="text-[var(--mauve)]"
aria-hidden="true" aria-hidden="true"
> >
<rect width="18" height="18" x="3" y="3" rx="2" ry="2" /> <rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
<circle cx="9" cy="9" r="2" /> <circle cx="9" cy="9" r="2" />
<path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" /> <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" />
</svg> </svg>
<h2 className="text-lg font-semibold text-lavender">Asset Library</h2> <h2 className="font-display italic text-xl text-[var(--text)]">Asset Library</h2>
</div> </div>
<button <button
type="button" type="button"
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
aria-label="Close" aria-label="Close"
className="p-1.5 rounded-md text-subtext0 hover:text-text hover:bg-surface0 transition-colors" className="p-1.5 text-[var(--subtext0)] hover:text-[var(--text)] hover:bg-[var(--surface0)] transition-colors"
style={{ borderRadius: 2 }}
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -57,58 +57,75 @@ export default function AssetManager({ mode = 'manage', onSelect }: Props) {
return ( return (
<div className="space-y-8"> <div className="space-y-8">
{alert && ( {alert && (
<div className={`p-4 rounded-lg mb-6 text-sm ${ <div
alert.type === 'success' ? 'bg-green/20 text-green border border-green/30' : 'bg-red/20 text-red border border-red/30' className={`p-4 mb-6 text-sm font-display italic border ${
}`}> alert.type === 'success'
? 'bg-[color-mix(in_srgb,var(--green)_18%,transparent)] text-[var(--green)] border-[var(--green)]/40'
: 'bg-[color-mix(in_srgb,var(--red)_18%,transparent)] text-[var(--red)] border-[var(--red)]/40'
}`}
style={{ borderRadius: 2 }}
>
{alert.msg} {alert.msg}
</div> </div>
)} )}
{/* Upload Zone */} {/* Upload Zone */}
<div <div
className="glass p-6 border-dashed border-2 border-surface1 hover:border-mauve transition-colors group relative cursor-pointer" className="glass p-6 border-dashed border-2 border-[var(--surface2)] hover:border-[var(--mauve)] transition-colors group relative cursor-pointer"
onClick={() => fileRef.current?.click()} onClick={() => fileRef.current?.click()}
onDragOver={e => { e.preventDefault(); e.stopPropagation(); }} onDragOver={e => { e.preventDefault(); e.stopPropagation(); }}
onDrop={e => { e.preventDefault(); e.stopPropagation(); if (e.dataTransfer.files.length) handleUpload(e.dataTransfer.files); }} onDrop={e => { e.preventDefault(); e.stopPropagation(); if (e.dataTransfer.files.length) handleUpload(e.dataTransfer.files); }}
> >
<input ref={fileRef} type="file" multiple className="hidden" onChange={e => { if (e.target.files?.length) handleUpload(e.target.files); }} /> <input ref={fileRef} type="file" multiple className="hidden" onChange={e => { if (e.target.files?.length) handleUpload(e.target.files); }} />
<div className="text-center py-4"> <div className="text-center py-4">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" className="mx-auto mb-4 text-subtext0 group-hover:text-mauve transition-colors"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" className="mx-auto mb-4 text-[var(--subtext0)] group-hover:text-[var(--mauve)] transition-colors"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/></svg>
<p className="text-lg font-bold text-lavender">Click or drag to upload assets</p> <p className="font-display italic text-xl text-[var(--text)] group-hover:text-[var(--mauve)] transition-colors">Click or drag to upload assets</p>
<p className="text-xs text-subtext0 mt-1">Any file type up to 50MB</p> <p className="font-sans text-xs uppercase tracking-[0.2em] text-[var(--subtext0)] mt-2">Any file type · up to 50 MB</p>
</div> </div>
</div> </div>
{/* Grid */} {/* Grid */}
{assets.length === 0 ? ( {assets.length === 0 ? (
<div className="text-center py-20 text-subtext0">No assets uploaded yet.</div> <div className="text-center py-20 font-display italic text-[var(--subtext0)]">No assets uploaded yet.</div>
) : ( ) : (
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-4"> <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-4">
{assets.map(asset => ( {assets.map(asset => (
<div key={asset.name} className="group relative aspect-square bg-crust rounded-xl overflow-hidden border border-white/5 hover:border-mauve/40 transition-colors shadow-lg flex flex-col"> <div
<div className="flex-1 overflow-hidden bg-surface0/20 relative cursor-pointer"> key={asset.name}
className="group relative aspect-square overflow-hidden bg-[var(--surface0)] border border-[var(--surface2)]/60 hover:border-[var(--mauve)]/60 transition-colors shadow-md flex flex-col"
style={{ borderRadius: 2 }}
>
<div className="flex-1 overflow-hidden bg-[var(--mantle)] relative cursor-pointer">
{isImage(asset.name) ? ( {isImage(asset.name) ? (
<img src={asset.url} className="w-full h-full object-cover opacity-80 group-hover:opacity-100 transition-opacity" alt={asset.name} /> <img src={asset.url} className="w-full h-full object-cover opacity-90 group-hover:opacity-100 transition-opacity" alt={asset.name} />
) : ( ) : (
<div className="flex flex-col items-center justify-center h-full text-subtext0"> <div className="flex flex-col items-center justify-center h-full text-[var(--subtext0)]">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mb-2"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mb-2"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg>
<span className="text-[8px] font-mono px-2 truncate w-full text-center">{asset.name.split('.').pop()?.toUpperCase()}</span> <span className="text-[8px] font-mono px-2 truncate w-full text-center">{asset.name.split('.').pop()?.toUpperCase()}</span>
</div> </div>
)} )}
{/* Hover overlay */} {/* Hover overlay */}
<div className="absolute inset-0 bg-crust/70 backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center gap-3"> <div className="absolute inset-0 bg-[var(--crust)]/75 backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center gap-3">
{mode === 'select' && onSelect && ( {mode === 'select' && onSelect && (
<button onClick={() => onSelect(asset)} className="bg-mauve hover:bg-pink text-crust px-4 py-2 rounded-lg text-sm font-bold transition-colors shadow-lg inline-flex items-center gap-1.5"> <button
onClick={() => onSelect(asset)}
className="bg-[var(--mauve)] hover:bg-[var(--red)] text-[var(--rosewater)] px-4 py-2 text-sm font-display italic font-medium transition-colors shadow-lg inline-flex items-center gap-1.5"
style={{ borderRadius: 1 }}
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
Insert Insert
</button> </button>
)} )}
<button onClick={() => handleDelete(asset.name)} className="bg-red/80 hover:bg-red text-white p-2.5 rounded-lg transition-colors shadow-lg"> <button
onClick={() => handleDelete(asset.name)}
className="bg-[var(--red)]/80 hover:bg-[var(--red)] text-[var(--rosewater)] p-2.5 transition-colors shadow-lg"
style={{ borderRadius: 1 }}
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
</button> </button>
</div> </div>
</div> </div>
<div className="p-2 bg-crust text-[10px] truncate border-t border-white/5 text-subtext1">{asset.name}</div> <div className="p-2 bg-[var(--surface0)] text-[10px] truncate border-t border-[var(--surface2)]/50 text-[var(--subtext1)] font-mono">{asset.name}</div>
</div> </div>
))} ))}
</div> </div>