diff --git a/index.html b/index.html
index 29d4d0f..ccfd1bf 100644
--- a/index.html
+++ b/index.html
@@ -205,14 +205,45 @@
position: relative;
}
+ /* ── Editor title bar ── */
+ .editor-title-bar {
+ display: flex;
+ align-items: center;
+ padding: 0 14px;
+ height: 44px;
+ border-bottom: 1px solid var(--border);
+ flex-shrink: 0;
+ gap: 10px;
+ }
+ #note-title-display {
+ flex: 1;
+ font-size: 15px;
+ font-weight: 700;
+ color: var(--fg);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ cursor: text;
+ opacity: 0.75;
+ }
+ #note-title-display:hover { opacity: 1; }
+ #note-title-input {
+ flex: 1;
+ font-size: 15px;
+ font-weight: 700;
+ font-family: 'Roboto Mono', monospace;
+ border: none;
+ outline: none;
+ background: transparent;
+ color: var(--fg);
+ display: none;
+ }
+
/* floating share + dark toggle */
.float-actions {
- position: absolute;
- top: 10px;
- right: 12px;
display: flex;
gap: 6px;
- z-index: 10;
+ flex-shrink: 0;
}
.float-btn {
padding: 5px 12px;
@@ -226,28 +257,14 @@
color: #000;
}
.float-btn:hover { background: var(--accent-hover); }
- .float-icon-btn {
- background: none;
- border: 1px solid var(--border);
- border-radius: 4px;
- padding: 4px 8px;
- cursor: pointer;
- font-size: 15px;
- color: var(--fg);
- }
- .float-icon-btn:hover { background: var(--sidebar-hover); }
- /* save flash */
.save-flash {
- position: absolute;
- top: 12px;
- left: 50%;
- transform: translateX(-50%);
font-size: 11px;
color: var(--muted);
opacity: 0;
transition: opacity 0.4s;
pointer-events: none;
+ white-space: nowrap;
}
.save-flash.show { opacity: 1; }
@@ -415,10 +432,13 @@
-
+
+
Untitled
+
✓ saved
-
-
+
+
+
@@ -499,16 +519,63 @@
let autoSaveTimer = null, syncTimer = null, flashTimer = null;
const $ = id => document.getElementById(id);
- const notepad = $('notepad');
- const mdView = $('md-view');
- const canvasWrap = $('canvas-wrap');
- const canvas = $('drawing-canvas');
- const drawCtrls = $('draw-controls');
- const sidebar = $('sidebar');
- const notesList = $('notes-list');
- const saveFlash = $('save-flash');
- const wordCount = $('word-count');
- const syncStatus = $('sync-status');
+ const notepad = $('notepad');
+ const mdView = $('md-view');
+ const canvasWrap = $('canvas-wrap');
+ const canvas = $('drawing-canvas');
+ const drawCtrls = $('draw-controls');
+ const sidebar = $('sidebar');
+ const notesList = $('notes-list');
+ const saveFlash = $('save-flash');
+ const wordCount = $('word-count');
+ const syncStatus = $('sync-status');
+ const titleDisplay = $('note-title-display');
+ const titleInput = $('note-title-input');
+
+ // ── Title display & rename ────────────────────────────────────────────────
+ function setTitleDisplay(title) {
+ titleDisplay.textContent = title || 'Untitled';
+ }
+
+ titleDisplay.addEventListener('click', () => {
+ titleDisplay.style.display = 'none';
+ titleInput.style.display = '';
+ titleInput.value = notes[currentId]?.title || '';
+ titleInput.focus();
+ titleInput.select();
+ });
+
+ titleInput.addEventListener('blur', commitTitleInput);
+ titleInput.addEventListener('keydown', e => {
+ if (e.key === 'Enter') titleInput.blur();
+ if (e.key === 'Escape') { renderTitle(); titleInput.style.display = 'none'; titleDisplay.style.display = ''; }
+ });
+
+ function commitTitleInput() {
+ if (!notes[currentId]) return;
+ notes[currentId].title = titleInput.value.trim();
+ notes[currentId].updatedAt = Date.now();
+ persist();
+ renderTitle();
+ renderList();
+ titleInput.style.display = 'none';
+ titleDisplay.style.display = '';
+ scheduleSync();
+ }
+
+ function renderTitle() {
+ setTitleDisplay(notes[currentId]?.title || '');
+ }
+
+ function autoTitleFromContent() {
+ const n = notes[currentId];
+ if (!n) return;
+ const firstLine = notepad.value.split('\n')[0].trim();
+ n.title = firstLine;
+ n.updatedAt = Date.now();
+ renderTitle();
+ renderList();
+ }
// ── Persist ──────────────────────────────────────────────────────────────
function persist() { localStorage.setItem('noted_notes', JSON.stringify(notes)); }
@@ -622,6 +689,7 @@
$('text-color').value = n.textColor || '#000000';
updateWordCount();
renderMd();
+ renderTitle();
undoStack = []; redoStack = [];
if (ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -664,7 +732,7 @@
clearTimeout(autoSaveTimer);
autoSaveTimer = setTimeout(() => saveNote(), 3000);
}
- notepad.addEventListener('input', () => { updateWordCount(); renderMd(); scheduleAutoSave(); });
+ notepad.addEventListener('input', () => { updateWordCount(); renderMd(); autoTitleFromContent(); scheduleAutoSave(); });
// ── Markdown ──────────────────────────────────────────────────────────────
function renderMd() { if (isMd) mdView.innerHTML = marked.parse(notepad.value || ''); }