Update UI design to premium violet palette, tweak hero section, and make search bar outline visible
This commit is contained in:
parent
eb8a302222
commit
c159ad4f37
11 changed files with 247 additions and 152 deletions
|
|
@ -57,25 +57,21 @@ export const DocumentGrid = ({ isTrash }: { isTrash: boolean }) => {
|
|||
<div
|
||||
key={doc.id}
|
||||
onContextMenu={(e) => handleContextMenu(e, doc.id)}
|
||||
className={`group relative flex flex-col bg-white dark:bg-gray-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-xl transition-all duration-300 border-2 ${
|
||||
isSelected ? 'border-indigo-500 shadow-md ring-2 ring-indigo-500/20' : 'border-transparent hover:border-indigo-200 dark:hover:border-indigo-800'
|
||||
className={`group relative flex flex-col bg-white dark:bg-gray-800 rounded-3xl overflow-hidden shadow-sm hover:shadow-xl hover:shadow-accent-500/10 transition-all duration-300 border border-gray-200 dark:border-gray-700 hover:-translate-y-1 ${
|
||||
isSelected ? 'border-accent-500 shadow-md ring-2 ring-accent-500/50 scale-[1.02]' : 'hover:border-accent-300 dark:hover:border-accent-700'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="absolute top-3 left-3 z-10 opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
style={{ opacity: isSelected ? 1 : undefined }}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={isSelected}
|
||||
onChange={() => toggleSelection(doc.id)}
|
||||
className="w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
{isSelected && (
|
||||
<div className="absolute top-3 left-3 z-20 w-6 h-6 bg-accent-500 rounded-full flex items-center justify-center shadow-md ring-2 ring-white">
|
||||
<svg className="w-4 h-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Link
|
||||
to={`/editor/${doc.id}`}
|
||||
className="relative aspect-[3/4] bg-gray-100 dark:bg-gray-900 overflow-hidden"
|
||||
className="relative aspect-[3/4] bg-gray-50/50 dark:bg-gray-900/50 overflow-hidden"
|
||||
onClick={(e) => {
|
||||
if (isTrash) e.preventDefault() // disable link in trash
|
||||
}}
|
||||
|
|
@ -83,27 +79,32 @@ export const DocumentGrid = ({ isTrash }: { isTrash: boolean }) => {
|
|||
<img
|
||||
src={thumbnailUrl}
|
||||
alt={doc.title}
|
||||
className={`w-full h-full object-cover transition-transform duration-500 group-hover:scale-105 ${isTrash ? 'grayscale opacity-70' : ''}`}
|
||||
className={`w-full h-full object-contain transition-transform duration-500 group-hover:scale-105 p-3 ${isTrash ? 'grayscale opacity-70' : ''}`}
|
||||
loading="lazy"
|
||||
onError={(e) => {
|
||||
// Fallback if no thumbnail
|
||||
(e.target as HTMLImageElement).src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="%239ca3af" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>'
|
||||
;(e.target as HTMLImageElement).className = 'w-1/2 h-1/2 absolute top-1/4 left-1/4 opacity-30 object-contain'
|
||||
const target = e.target as HTMLImageElement;
|
||||
target.onerror = null;
|
||||
target.src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="%23cbd5e1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="9" y1="9" x2="15" y2="15"></line><line x1="15" y1="9" x2="9" y2="15"></line></svg>';
|
||||
}}
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-black/10 opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none" />
|
||||
|
||||
{/* Hover overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/40 via-transparent to-gray-900/10 opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none" />
|
||||
</Link>
|
||||
|
||||
<div className="p-4 flex flex-col">
|
||||
<h3 className="text-sm font-semibold text-gray-900 dark:text-white truncate" title={doc.title}>
|
||||
<div className="p-4 flex flex-col gap-1.5 border-t border-gray-100 dark:border-gray-700 bg-white dark:bg-gray-800">
|
||||
<h3 className="text-sm font-bold text-gray-900 dark:text-white truncate" title={doc.title}>
|
||||
{doc.title}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||
{formatDistanceToNow(new Date(doc.updated_at), { addSuffix: true })}
|
||||
</p>
|
||||
<p className="text-[10px] text-gray-400 dark:text-gray-500 mt-0.5">
|
||||
{(doc.size_bytes / 1024 / 1024).toFixed(1)} MB
|
||||
</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs font-semibold text-gray-500 dark:text-gray-400">
|
||||
{formatDistanceToNow(new Date(doc.updated_at), { addSuffix: true })}
|
||||
</p>
|
||||
<p className="text-[10px] font-bold text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-700 px-2 py-0.5 rounded-md">
|
||||
{(doc.size_bytes / 1024 / 1024).toFixed(1)} MB
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue