feat: Improve mobile UI/UX with larger touch targets and better layouts
This commit is contained in:
parent
8fd791df68
commit
a5bc7ddb39
3 changed files with 12 additions and 12 deletions
|
|
@ -442,7 +442,7 @@ export function Gallery() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Gallery Grid */}
|
{/* Gallery Grid */}
|
||||||
<div className="columns-1 sm:columns-2 md:columns-3 lg:columns-4 gap-4 space-y-4">
|
<div className="columns-2 sm:columns-2 md:columns-3 lg:columns-4 gap-3 md:gap-4 space-y-3 md:space-y-4">
|
||||||
{/* Skeleton Loading State */}
|
{/* Skeleton Loading State */}
|
||||||
{isGenerating && (
|
{isGenerating && (
|
||||||
<>
|
<>
|
||||||
|
|
@ -490,14 +490,14 @@ export function Gallery() {
|
||||||
<button
|
<button
|
||||||
onClick={(e) => { e.stopPropagation(); if (img.id) removeFromGallery(img.id); }}
|
onClick={(e) => { e.stopPropagation(); if (img.id) removeFromGallery(img.id); }}
|
||||||
|
|
||||||
className="absolute top-2 right-2 p-1.5 bg-black/50 hover:bg-destructive/80 rounded-full text-white opacity-0 group-hover:opacity-100 transition-all"
|
className="absolute top-2 right-2 p-2 md:p-1.5 bg-black/60 hover:bg-destructive/80 rounded-full text-white opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-all min-w-[36px] min-h-[36px] md:min-w-0 md:min-h-0 flex items-center justify-center"
|
||||||
title="Delete"
|
title="Delete"
|
||||||
>
|
>
|
||||||
<X className="h-4 w-4" />
|
<X className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Hover Overlay - Simplified: just show prompt */}
|
{/* Hover Overlay - Simplified: just show prompt */}
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex flex-col justify-end p-3 pointer-events-none">
|
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-transparent opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity flex flex-col justify-end p-2 md:p-3 pointer-events-none">
|
||||||
<p className="text-white text-xs line-clamp-2">{img.prompt}</p>
|
<p className="text-white text-xs line-clamp-2">{img.prompt}</p>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ export function PromptHero() {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-3xl mx-auto my-4 md:my-6 px-4">
|
<div className="w-full max-w-3xl mx-auto my-4 md:my-6 px-3 md:px-4 pb-20 md:pb-4">
|
||||||
{/* Error/Warning Notification Toast */}
|
{/* Error/Warning Notification Toast */}
|
||||||
{errorNotification && (
|
{errorNotification && (
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
|
|
@ -543,7 +543,7 @@ export function PromptHero() {
|
||||||
|
|
||||||
{/* Left Controls: References */}
|
{/* Left Controls: References */}
|
||||||
{/* For Meta AI: Only Subject is enabled (for video generation), Scene/Style disabled */}
|
{/* For Meta AI: Only Subject is enabled (for video generation), Scene/Style disabled */}
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2 w-full md:w-auto">
|
||||||
{((settings.provider === 'meta'
|
{((settings.provider === 'meta'
|
||||||
? ['subject']
|
? ['subject']
|
||||||
: ['subject', 'scene', 'style']) as ReferenceCategory[]).map((cat) => {
|
: ['subject', 'scene', 'style']) as ReferenceCategory[]).map((cat) => {
|
||||||
|
|
@ -561,7 +561,7 @@ export function PromptHero() {
|
||||||
? "Upload image to animate into video"
|
? "Upload image to animate into video"
|
||||||
: undefined}
|
: undefined}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[10px] font-medium transition-all border relative overflow-hidden",
|
"flex items-center gap-1.5 rounded-lg px-3 py-2 md:px-3 md:py-1.5 text-xs md:text-[10px] font-medium transition-all border relative overflow-hidden min-h-[44px] md:min-h-0",
|
||||||
hasRefs
|
hasRefs
|
||||||
? "bg-purple-500/10 text-purple-200 border-purple-500/30 hover:bg-purple-500/20"
|
? "bg-purple-500/10 text-purple-200 border-purple-500/30 hover:bg-purple-500/20"
|
||||||
: "bg-white/5 text-white/40 border-white/5 hover:bg-white/10 hover:text-white/70 hover:border-white/10",
|
: "bg-white/5 text-white/40 border-white/5 hover:bg-white/10 hover:text-white/70 hover:border-white/10",
|
||||||
|
|
@ -688,7 +688,7 @@ export function PromptHero() {
|
||||||
onClick={handleGenerate}
|
onClick={handleGenerate}
|
||||||
disabled={isGenerating || !prompt.trim()}
|
disabled={isGenerating || !prompt.trim()}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative overflow-hidden px-4 py-1.5 rounded-lg font-bold text-sm text-white shadow-lg transition-all active:scale-95 group border border-white/10",
|
"relative overflow-hidden px-5 py-2.5 md:px-4 md:py-1.5 rounded-xl md:rounded-lg font-bold text-base md:text-sm text-white shadow-lg transition-all active:scale-95 group border border-white/10 min-h-[44px] md:min-h-0",
|
||||||
"bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 hover:shadow-indigo-500/25"
|
"bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 hover:shadow-indigo-500/25"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -730,7 +730,7 @@ export function PromptHero() {
|
||||||
<img
|
<img
|
||||||
src={ref.thumbnail}
|
src={ref.thumbnail}
|
||||||
alt=""
|
alt=""
|
||||||
className="h-10 w-10 rounded object-cover ring-1 ring-white/10 group-hover/thumb:ring-purple-500/50 transition-all"
|
className="h-12 w-12 md:h-10 md:w-10 rounded object-cover ring-1 ring-white/10 group-hover/thumb:ring-purple-500/50 transition-all"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() => removeReference(cat, ref.id)}
|
onClick={() => removeReference(cat, ref.id)}
|
||||||
|
|
|
||||||
|
|
@ -47,27 +47,27 @@ export function Settings() {
|
||||||
{/* Provider Selection */}
|
{/* Provider Selection */}
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<label className="text-sm font-medium">Image Generation Provider</label>
|
<label className="text-sm font-medium">Image Generation Provider</label>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
||||||
{providers.map((p) => (
|
{providers.map((p) => (
|
||||||
<button
|
<button
|
||||||
key={p.id}
|
key={p.id}
|
||||||
onClick={() => setProvider(p.id)}
|
onClick={() => setProvider(p.id)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col items-center gap-2 p-4 rounded-xl border-2 transition-all",
|
"flex flex-col items-center gap-2 p-4 md:p-4 rounded-xl border-2 transition-all min-h-[100px] active:scale-95",
|
||||||
provider === p.id
|
provider === p.id
|
||||||
? "border-primary bg-primary/10"
|
? "border-primary bg-primary/10"
|
||||||
: "border-border hover:border-primary/50 bg-card"
|
: "border-border hover:border-primary/50 bg-card"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<p.icon className={cn(
|
<p.icon className={cn(
|
||||||
"h-6 w-6",
|
"h-7 w-7 md:h-6 md:w-6",
|
||||||
provider === p.id ? "text-primary" : "text-muted-foreground"
|
provider === p.id ? "text-primary" : "text-muted-foreground"
|
||||||
)} />
|
)} />
|
||||||
<span className={cn(
|
<span className={cn(
|
||||||
"font-medium text-sm",
|
"font-medium text-sm",
|
||||||
provider === p.id ? "text-primary" : ""
|
provider === p.id ? "text-primary" : ""
|
||||||
)}>{p.name}</span>
|
)}>{p.name}</span>
|
||||||
<span className="text-xs text-muted-foreground">{p.description}</span>
|
<span className="text-xs text-muted-foreground text-center">{p.description}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue