Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions src/components/ImageOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Image from "next/image";
import { useRef, useState, useEffect } from "react";
import { OverlayPosition } from "@/lib/types";
import { ArrowUpLeft, ArrowUpRight, ArrowDownLeft, ArrowDownRight, Upload, Trash2, FileImage } from "lucide-react";
import { cn } from "@/lib/utils";

interface ImageOverlayPanelProps {
overlayFile: File | null;
Expand All @@ -12,6 +13,8 @@ interface ImageOverlayPanelProps {
setOverlaySize: (v: number) => void;
overlayOpacity: number;
setOverlayOpacity: (v: number) => void;
isSelected?: boolean;
setIsSelected?: (v: boolean) => void;
}

const POSITIONS: { value: OverlayPosition; icon: React.ReactNode; label: string }[] = [
Expand All @@ -30,6 +33,8 @@ export default function ImageOverlayPanel({
setOverlaySize,
overlayOpacity,
setOverlayOpacity,
isSelected = false,
setIsSelected,
}: ImageOverlayPanelProps) {
const inputRef = useRef<HTMLInputElement>(null);
const [thumbUrl, setThumbUrl] = useState<string>("");
Expand All @@ -44,6 +49,18 @@ export default function ImageOverlayPanel({
return () => URL.revokeObjectURL(url);
}, [overlayFile]);

useEffect(() => {
return () => {
if (setIsSelected) setIsSelected(false);
};
}, [setIsSelected]);

useEffect(() => {
if (!overlayFile && setIsSelected) {
setIsSelected(false);
}
}, [overlayFile, setIsSelected]);

const handleUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) setOverlayFile(file);
Expand Down Expand Up @@ -98,7 +115,36 @@ export default function ImageOverlayPanel({
</label>

{/* Right Side: Horizontal Details Card */}
<div className="flex-1 min-w-0 h-11 rounded-lg border border-[var(--border)] bg-[var(--bg)] flex items-center justify-between px-3 gap-2.5">
<div
role="button"
onClick={() => {
if (overlayFile && setIsSelected) {
setIsSelected(!isSelected);
}
}}
onFocus={() => {
if (overlayFile && setIsSelected) {
setIsSelected(true);
}
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
if (overlayFile && setIsSelected) {
setIsSelected(!isSelected);
}
}
}}
tabIndex={overlayFile ? 0 : -1}
className={cn(
"flex-1 min-w-0 h-11 rounded-lg border flex items-center justify-between px-3 gap-2.5 outline-none transition-all duration-200",
overlayFile ? "cursor-pointer" : "",
isSelected && overlayFile
? "border-film-500 ring-2 ring-film-500/30 bg-film-500/10"
: "border-[var(--border)] bg-[#121d30]/20"
)}
aria-label={overlayFile ? `Image overlay: ${overlayFile.name}. Press Backspace or Delete to remove.` : "No image overlay selected"}
>
{overlayFile ? (
<>
{/* File Info block */}
Expand All @@ -116,9 +162,13 @@ export default function ImageOverlayPanel({

<button
type="button"
onClick={() => setOverlayFile(null)}
onClick={(e) => {
e.stopPropagation(); // prevent triggering selection change
setOverlayFile(null);
}}
aria-label="Remove overlay image"
className="w-6 h-6 rounded flex items-center justify-center bg-[var(--error-bg)] hover:bg-[var(--error-hover)] text-[var(--error)] border border-[var(--error-border)] transition shrink-0"
title="Remove image"
>
<Trash2 size={11} aria-hidden="true" />
</button>
Expand Down
16 changes: 11 additions & 5 deletions src/components/OnboardingTour.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,16 @@ export default function OnboardingTour() {
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") dismiss();
if (e.key === "ArrowRight" || e.key === "Enter") {
if (stepIndex < TOUR_STEPS.length - 1) setStepIndex((i) => i + 1);
else dismiss();
setStepIndex((i) => {
if (i < TOUR_STEPS.length - 1) return i + 1;
dismiss();
return i;
});
}
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
}, [visible, stepIndex, dismiss]);
}, [visible, dismiss]);

if (!visible || !targetRect || !currentStep) return null;

Expand All @@ -380,8 +383,11 @@ export default function OnboardingTour() {
totalSteps={TOUR_STEPS.length}
rect={targetRect}
onNext={() => {
if (stepIndex < TOUR_STEPS.length - 1) setStepIndex((i) => i + 1);
else dismiss();
setStepIndex((i) => {
if (i < TOUR_STEPS.length - 1) return i + 1;
dismiss();
return i;
});
}}
onSkip={dismiss}
tooltipRef={tooltipRef}
Expand Down
Loading