mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
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:
@@ -261,7 +261,7 @@ export function LayersPanel() {
|
||||
|
||||
function BlendModeSelect({ value, onChange }: { value: string; onChange: (mode: string) => void }) {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<label htmlFor="blend-mode-select" className="text-[10px] text-muted-foreground shrink-0">
|
||||
Blend
|
||||
</label>
|
||||
@@ -269,7 +269,7 @@ function BlendModeSelect({ value, onChange }: { value: string; onChange: (mode:
|
||||
id="blend-mode-select"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
className="flex-1 h-7 text-xs bg-muted border border-border rounded px-1.5 text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
|
||||
className="flex-1 min-w-0 h-7 text-xs bg-muted border border-border rounded px-1.5 text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
|
||||
data-testid="blend-mode-select"
|
||||
>
|
||||
{BLEND_MODES.map((mode) => (
|
||||
@@ -289,7 +289,7 @@ function BlendModeSelect({ value, onChange }: { value: string; onChange: (mode:
|
||||
function OpacitySlider({ value, onChange }: { value: number; onChange: (v: number) => void }) {
|
||||
const percent = Math.round(value * 100);
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<label htmlFor="layer-opacity-slider" className="text-[10px] text-muted-foreground shrink-0">
|
||||
Opacity
|
||||
</label>
|
||||
@@ -300,10 +300,10 @@ function OpacitySlider({ value, onChange }: { value: number; onChange: (v: numbe
|
||||
max={100}
|
||||
value={percent}
|
||||
onChange={(e) => onChange(Number(e.target.value) / 100)}
|
||||
className="flex-1"
|
||||
className="flex-1 min-w-0"
|
||||
data-testid="layer-opacity-slider"
|
||||
/>
|
||||
<span className="text-xs font-mono text-foreground tabular-nums w-8 text-right">
|
||||
<span className="text-[10px] font-mono text-foreground tabular-nums shrink-0">
|
||||
{percent}%
|
||||
</span>
|
||||
</div>
|
||||
@@ -990,7 +990,7 @@ function EffectSlider({
|
||||
onChange: (v: number) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="flex items-center gap-1.5 min-w-0">
|
||||
<span className="text-[10px] text-muted-foreground shrink-0 w-12">{label}</span>
|
||||
<input
|
||||
type="range"
|
||||
@@ -998,9 +998,9 @@ function EffectSlider({
|
||||
max={max}
|
||||
value={value}
|
||||
onChange={(e) => onChange(Number(e.target.value))}
|
||||
className="flex-1"
|
||||
className="flex-1 min-w-0"
|
||||
/>
|
||||
<span className="text-[10px] font-mono text-foreground tabular-nums w-10 text-right">
|
||||
<span className="text-[10px] font-mono text-foreground tabular-nums w-11 text-right shrink-0">
|
||||
{value}
|
||||
{suffix}
|
||||
</span>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { Minus, Plus } from "lucide-react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEditorStore } from "@/stores/editor-store";
|
||||
|
||||
const THUMBNAIL_MAX_HEIGHT = 80;
|
||||
@@ -257,11 +256,7 @@ export function NavigatorPanel() {
|
||||
step={0.001}
|
||||
value={Math.log(zoom / MIN_ZOOM) / Math.log(MAX_ZOOM / MIN_ZOOM)}
|
||||
onChange={handleZoomSlider}
|
||||
className={cn(
|
||||
"flex-1 h-1 appearance-none rounded-full bg-muted",
|
||||
"[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-2.5 [&::-webkit-slider-thumb]:h-2.5",
|
||||
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-foreground [&::-webkit-slider-thumb]:cursor-pointer",
|
||||
)}
|
||||
className="flex-1"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user