Skip to content

Commit 54ced1e

Browse files
committed
Improve unsaved indicator tooltip visibility
1 parent beb492c commit 54ced1e

1 file changed

Lines changed: 22 additions & 1 deletion

File tree

components/PromptEditor.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import LanguageDropdown from './LanguageDropdown';
1616
import PythonExecutionPanel from './PythonExecutionPanel';
1717
import ScriptExecutionPanel from './ScriptExecutionPanel';
1818
import EmojiPickerOverlay from './EmojiPickerOverlay';
19+
import Tooltip from './Tooltip';
1920

2021
interface DocumentEditorProps {
2122
documentNode: DocumentOrFolder;
@@ -179,6 +180,7 @@ const DocumentEditor: React.FC<DocumentEditorProps> = ({
179180
const [isGeneratingTitle, setIsGeneratingTitle] = useState(false);
180181
const [isGeneratingEmoji, setIsGeneratingEmoji] = useState(false);
181182
const [isTitleEmojiPickerOpen, setIsTitleEmojiPickerOpen] = useState(false);
183+
const [showUnsavedTooltip, setShowUnsavedTooltip] = useState(false);
182184
const [titleEmojiAnchor, setTitleEmojiAnchor] = useState<{ x: number; y: number } | null>(null);
183185
const [isCopied, setIsCopied] = useState(false);
184186
const [viewMode, setViewMode] = useState<ViewMode>(resolveDefaultViewMode(documentNode.default_view_mode, documentNode.language_hint));
@@ -236,6 +238,7 @@ const DocumentEditor: React.FC<DocumentEditorProps> = ({
236238
const acceptButtonRef = useRef<HTMLButtonElement>(null);
237239
const titleInputRef = useRef<HTMLInputElement>(null);
238240
const languageButtonRef = useRef<HTMLButtonElement | null>(null);
241+
const unsavedIndicatorRef = useRef<HTMLDivElement>(null);
239242
const isContentInitialized = useRef(false);
240243
const editorRef = useRef<CodeEditorHandle>(null);
241244
const richTextEditorRef = useRef<RichTextEditorHandle>(null);
@@ -1035,7 +1038,25 @@ const DocumentEditor: React.FC<DocumentEditorProps> = ({
10351038
{isGeneratingTitle ? <Spinner /> : <RefreshIcon className="w-4 h-4 text-primary" />}
10361039
</IconButton>
10371040
)}
1038-
{isDirty && <div className="relative group flex-shrink-0"><div className="w-2 h-2 bg-primary rounded-full animate-pulse"></div><span className="absolute bottom-full mb-2 left-1/2 -translate-x-1/2 z-50 w-max px-2 py-1 text-xs font-semibold text-tooltip-text bg-tooltip-bg rounded-md opacity-0 group-hover:opacity-100">Unsaved changes</span></div>}
1041+
{isDirty && (
1042+
<>
1043+
<div
1044+
ref={unsavedIndicatorRef}
1045+
className="relative flex-shrink-0"
1046+
onMouseEnter={() => setShowUnsavedTooltip(true)}
1047+
onMouseLeave={() => setShowUnsavedTooltip(false)}
1048+
onFocus={() => setShowUnsavedTooltip(true)}
1049+
onBlur={() => setShowUnsavedTooltip(false)}
1050+
tabIndex={0}
1051+
aria-label="Unsaved changes"
1052+
>
1053+
<div className="w-2 h-2 bg-primary rounded-full animate-pulse" />
1054+
</div>
1055+
{showUnsavedTooltip && unsavedIndicatorRef.current && (
1056+
<Tooltip targetRef={unsavedIndicatorRef} content="Unsaved changes" position="bottom" />
1057+
)}
1058+
</>
1059+
)}
10391060
{isLocked && (
10401061
<div className="flex items-center gap-1 text-xs font-semibold text-primary flex-shrink-0">
10411062
<LockClosedIcon className="w-3.5 h-3.5" />

0 commit comments

Comments
 (0)