From f43aa125eab9cf1568ccfede90eed0829d50a7ac Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sat, 5 Sep 2026 19:41:39 +0330 Subject: [PATCH] Fix note color swatches outside teleported editor panel. Use hex palettes so Keep-style colors render when the create panel is portaled to body. Co-authored-by: Cursor --- apps/web/src/views/NotesView.vue | 173 ++++++++++++++++++++++++------- 1 file changed, 138 insertions(+), 35 deletions(-) diff --git a/apps/web/src/views/NotesView.vue b/apps/web/src/views/NotesView.vue index e066e4c..2172e31 100644 --- a/apps/web/src/views/NotesView.vue +++ b/apps/web/src/views/NotesView.vue @@ -67,6 +67,7 @@ const draftActivityId = ref(''); const draftReminder = ref(''); const draftLocation = ref(''); const draftAnalyze = ref(true); +const draftPinned = ref(false); const draftChecklist = ref([]); const draftFiles = ref([]); const existingAttachments = ref([]); @@ -130,17 +131,18 @@ const draftColorCss = computed(() => colorToCss(draftColor.value)); const personName = (id: string) => people.value.find((p) => p.id === id)?.fullName ?? ''; +/** Hex only — panel is Teleported outside `.notes-page`, so CSS vars would not inherit. */ +const NOTE_COLOR_HEX: Record = { + sand: '#fff8e1', + rose: '#fce4ec', + sky: '#e3f2fd', + mint: '#e0f2f1', + lavender: '#f3e5f5', + default: '#ffffff', +}; + function colorToCss(raw: string | null | undefined): string { - const key = normalizeColor(raw); - const map: Record = { - sand: 'var(--note-sand)', - rose: 'var(--note-rose)', - sky: 'var(--note-sky)', - mint: 'var(--note-mint)', - lavender: 'var(--note-lavender)', - default: 'var(--note-default)', - }; - return map[key]; + return NOTE_COLOR_HEX[normalizeColor(raw)]; } function normalizeColor(raw: string | null | undefined): ColorKey { @@ -359,6 +361,7 @@ function resetDraft() { draftReminder.value = ''; draftLocation.value = ''; draftAnalyze.value = true; + draftPinned.value = false; draftChecklist.value = []; draftFiles.value = []; existingAttachments.value = []; @@ -381,6 +384,7 @@ function openEditor(mode: OpenMode = 'default', note?: NoteDto) { draftReminder.value = note.reminderAt ? note.reminderAt.slice(0, 16) : ''; draftLocation.value = note.locationText ?? ''; draftAnalyze.value = note.analyzeEnabled !== false; + draftPinned.value = note.pinned; draftChecklist.value = [...(note.checklist ?? [])]; draftFiles.value = []; existingAttachments.value = [...note.attachments]; @@ -496,6 +500,7 @@ async function saveNote() { : null, locationText: draftLocation.value.trim() || null, analyzeEnabled: draftAnalyze.value, + pinned: draftPinned.value, checklist, }; const pending = [...draftFiles.value]; @@ -534,6 +539,24 @@ async function togglePin(id: string) { menuOpenId.value = null; await api.patch(`/notes/${id}/pin`); await load(); + if (editingId.value === id) { + const n = notes.value.find((x) => x.id === id); + if (n) draftPinned.value = n.pinned; + } +} + +async function onPinClick() { + const next = !draftPinned.value; + draftPinned.value = next; + if (!editingId.value) return; + const note = notes.value.find((n) => n.id === editingId.value); + if (note && note.pinned === next) return; + try { + await api.patch(`/notes/${editingId.value}/pin`); + if (note) note.pinned = next; + } catch { + draftPinned.value = !next; + } } async function removeNote(id: string) { @@ -864,7 +887,13 @@ onBeforeUnmount(() => { class="panel-root desktop-panel" >
-
@@ -1059,7 +1108,7 @@ onBeforeUnmount(() => {
+
@@ -1825,23 +1891,60 @@ onBeforeUnmount(() => { .swatches { display: flex; - gap: 0.45rem; + gap: 0.5rem; + flex-wrap: wrap; + align-items: center; +} +.palette-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.65rem; flex-wrap: wrap; } .swatch { - width: 28px; - height: 28px; + width: 32px; + height: 32px; border-radius: 50%; - border: 1px solid rgba(15, 23, 42, 0.12); + border: 1.5px solid rgba(15, 23, 42, 0.18); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; - color: var(--teal); + color: #0f766e; padding: 0; + flex-shrink: 0; + box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08); +} +.swatch.tone-default { + border-color: #94a3b8; + background-image: linear-gradient( + 45deg, + #f1f5f9 25%, + transparent 25%, + transparent 75%, + #f1f5f9 75% + ); + background-size: 8px 8px; } .swatch.selected { - box-shadow: 0 0 0 2px var(--teal); + box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--teal, #0d9488); +} +.pin-btn.on { + border-color: #f59e0b; + color: #b45309; + background: #fffbeb; +} + +.panel-root { + --note-sand: #fff8e1; + --note-rose: #fce4ec; + --note-sky: #e3f2fd; + --note-mint: #e0f2f1; + --note-lavender: #f3e5f5; + --note-default: #ffffff; + --teal: #0d9488; + --teal-soft: #ccfbf1; } .media-row {