fix: editor native layout, UI polish, meme templates auth, pipeline export, install queuing

- Remove editor from AppLayout so it owns the full viewport with no sidebar/padding
- Add back-arrow in menu bar for navigation, restyle menu bar to match native app feel
- Slim left toolbar from 48px to 36px with smaller icons and subtler dividers
- Fix options bar overlapping canvas via shrink-0 and overflow-hidden
- Fix opacity/blend controls clipping in right panel with min-w-0 on flex children
- Add global range slider CSS for consistent thin-track + round-thumb styling
- Make meme template routes public so img tags can load without Bearer auth
- Show pipeline export buttons in default compact view, not just expanded hover
- Queue individual AI feature installs instead of erroring when one is active
This commit is contained in:
SnapOtter
2026-05-08 23:30:27 +08:00
parent 23f24c10d1
commit e22ffa4ec9
23 changed files with 181 additions and 94 deletions
+25 -12
View File
@@ -630,14 +630,16 @@ export function AutomatePage() {
<button
type="button"
onClick={() => handleExportPipeline(p)}
className="opacity-0 group-hover:opacity-100 p-1 rounded hover:bg-primary/10 text-muted-foreground hover:text-primary transition-all shrink-0"
className="p-1 rounded hover:bg-primary/10 text-muted-foreground hover:text-primary transition-all shrink-0"
title="Export pipeline"
>
<Download className="h-3 w-3" />
</button>
<button
type="button"
onClick={() => handleDeletePipeline(p.id)}
className="opacity-0 group-hover:opacity-100 p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive transition-all shrink-0"
className="p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive transition-all shrink-0"
title="Delete pipeline"
>
<Trash2 className="h-3 w-3" />
</button>
@@ -652,17 +654,28 @@ export function AutomatePage() {
</button>
</div>
) : (
<div className="flex flex-wrap gap-1">
<div className="space-y-1">
{savedPipelines.slice(0, 3).map((p) => (
<button
key={p.id}
type="button"
onClick={() => handleLoadPipeline(p)}
className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-muted text-xs text-foreground hover:bg-primary/10 hover:text-primary transition-colors truncate max-w-[110px]"
>
<Play className="h-3 w-3 shrink-0" />
<span className="truncate">{p.name}</span>
</button>
<div key={p.id} className="flex items-center gap-1">
<button
type="button"
onClick={() => handleLoadPipeline(p)}
className="flex-1 text-left text-xs text-foreground hover:text-primary truncate py-1 px-2 rounded hover:bg-muted"
>
{p.name}
<span className="text-muted-foreground ml-1">
({p.steps.length} step{p.steps.length !== 1 ? "s" : ""})
</span>
</button>
<button
type="button"
onClick={() => handleExportPipeline(p)}
className="p-1 rounded hover:bg-primary/10 text-muted-foreground hover:text-primary transition-all shrink-0"
title="Export pipeline"
>
<Download className="h-3 w-3" />
</button>
</div>
))}
{savedPipelines.length > 3 && (
<button
+1 -1
View File
@@ -151,7 +151,7 @@ export function EditorPage() {
}
return (
<div className="flex flex-col h-full overflow-hidden">
<div className="flex flex-col h-screen overflow-hidden bg-background text-foreground">
<EditorMenuBar
onNewDocument={() => setShowNewDocument(true)}
onOpenImage={handleOpenImage}