feat: améliorer styles dark mode avec background unifié #20293a, bordures notes/cards (1px solid #000 light, #dedfe2 dark), width input 600px→800px, ajout bouton pin corner absolu (top-right, hover scale 1.06), suppression backgrounds/borders/outlines inputs (transparent + !important), nettoyage code dupliqué note-input-collapsed, styles todo-draft-row transparent, et corrections mineures formatage CSS (espaces, indentation)

This commit is contained in:
2026-04-19 21:46:47 -04:00
parent ef6f9cb486
commit f99c1cbecb
11 changed files with 1098 additions and 200 deletions
+169 -80
View File
@@ -2,7 +2,7 @@ document.addEventListener("DOMContentLoaded", function () {
// Check URL parameters for custom views
const urlParams = new URLSearchParams(window.location.search);
const searchTagsRaw = urlParams.get("searchtags") || urlParams.get("searchTags") || "";
// Also check URL path for tag format (e.g., /tag/note)
const urlPath = window.location.pathname;
const pathMatch = urlPath.match(/\/tag\/(.+)$/);
@@ -10,17 +10,21 @@ document.addEventListener("DOMContentLoaded", function () {
// Parse all active tags to safely detect the view
const activeTags = (searchTagsRaw + " " + pathTagRaw).toLowerCase().split(/[\s,]+/).filter(t => t);
// Foolproof detection using sidebar active state and DOM rendered tags
const hasNoteActiveMenu = !!document.querySelector('.sidebar-link[aria-label="Notes"].active, .header-nav-link[aria-label="Notes"].active, .sidebar-link[href*="searchtags=note"].active, .sidebar-link[href*="searchtags=shaarli-note"].active');
const hasTodoActiveMenu = !!document.querySelector('.sidebar-link[aria-label="Mes tâches"].active, .header-nav-link[aria-label="Mes tâches"].active, .sidebar-link[href*="searchtags=shaarli-todo"].active');
const hasArchiveActiveMenu = !!document.querySelector('.sidebar-link[aria-label="Archive"].active, .header-nav-link[aria-label="Archive"].active, .sidebar-link[href*="searchtags=shaarli-archive"].active');
const hasTodoActiveMenu = !!document.querySelector('.sidebar-link[aria-label="Mes tâches"].active, .header-nav-link[aria-label="Mes tâches"].active, .sidebar-link[href*="searchtags=shaarli-todo"].active, .sidebar-link[href*="searchtags=todo"].active');
const hasArchiveActiveMenu = !!document.querySelector('.sidebar-link[aria-label="Archive"].active, .header-nav-link[aria-label="Archive"].active, .sidebar-link[href*="searchtags=shaarli-archive"].active, .sidebar-link[href*="searchtags=shaarli-archiver"].active');
const domChipTags = Array.from(document.querySelectorAll('.search-tag-chip')).map(el => (el.textContent || "").trim().toLowerCase());
const isNoteView = activeTags.includes("note") || activeTags.includes("shaarli-note") || hasNoteActiveMenu || domChipTags.includes("note") || domChipTags.includes("shaarli-note");
const isTodoView = activeTags.includes("shaarli-todo") || hasTodoActiveMenu || domChipTags.includes("shaarli-todo");
const isArchiveView = activeTags.includes("shaarli-archive") || hasArchiveActiveMenu || domChipTags.includes("shaarli-archive");
const isArchiveTag = (tag) => tag === "shaarli-archive" || tag === "shaarli-archiver";
const isNoteTag = (tag) => tag === "note" || tag === "shaarli-note" || tag === "#note";
const isTodoTag = (tag) => tag === "todo" || tag === "shaarli-todo" || tag === "#todo";
const isNoteView = activeTags.some(isNoteTag) || hasNoteActiveMenu || domChipTags.some(isNoteTag);
const isTodoView = activeTags.some(isTodoTag) || hasTodoActiveMenu || domChipTags.some(isTodoTag);
const isArchiveView = activeTags.some(isArchiveTag) || hasArchiveActiveMenu || domChipTags.some(isArchiveTag);
const linkList = document.getElementById("links-list");
const container = document.querySelector(".content-container");
@@ -194,9 +198,9 @@ document.addEventListener("DOMContentLoaded", function () {
const checked = String(todoMatch[1]).toLowerCase() === "x";
html.push(
`<li class="md-todo-item${checked ? " is-checked" : ""}">`
+ `<span class="md-todo-box" aria-hidden="true"><i class="mdi mdi-check"></i></span>`
+ `<span class="md-todo-text">${renderInline(todoMatch[2])}</span>`
+ "</li>",
+ `<span class="md-todo-box" aria-hidden="true"><i class="mdi mdi-check"></i></span>`
+ `<span class="md-todo-text">${renderInline(todoMatch[2])}</span>`
+ "</li>",
);
return;
}
@@ -409,9 +413,9 @@ document.addEventListener("DOMContentLoaded", function () {
initBookmarkPaletteButtons();
}
if (typeof organizePinnedBookmarks === "function") {
window.requestAnimationFrame(organizePinnedBookmarks);
}
if (typeof organizePinnedBookmarks === "function") {
window.requestAnimationFrame(organizePinnedBookmarks);
}
// Always init Pinned Items logic (sorting and listeners)
// This function is defined at the end of the file
@@ -466,7 +470,7 @@ document.addEventListener("DOMContentLoaded", function () {
// Charger les backgrounds dynamiquement, puis initialiser les vues
initThemeModeBackgroundSync();
if (typeof loadBackgroundOptions === "function") {
loadBackgroundOptions()
.then(() => {
@@ -500,7 +504,7 @@ const NOTE_COLOR_OPTIONS = [
{
key: "default",
label: "Par défaut",
light: "#ffffff",
light: "#f8fafc",
dark: "#20293A"
},
{
@@ -605,13 +609,15 @@ const NOTE_BACKGROUND_TAG_PREFIX = "notebg-";
function isTechnicalTag(tag) {
if (typeof tag !== "string") return false;
const t = tag.trim();
const t = tag.trim().toLowerCase();
if (!t) return false;
if (t === "note") return true;
if (t === "note" || t === "#note") return true;
if (t === "shaarli-note") return true;
if (t === "todo" || t === "#todo") return true;
if (t === "shaarli-todo") return true;
if (t === "shaarli-pin") return true;
if (t === "brain-dump") return true;
if (t.startsWith(NOTE_FONT_COLOR_TAG_PREFIX)) return true;
if (t.startsWith(NOTE_COLOR_TAG_PREFIX)) return true;
if (t.startsWith(NOTE_FILTER_TAG_PREFIX)) return true;
@@ -694,6 +700,16 @@ function removeTagFromEntity(editUrl, tag) {
});
}
function deleteEntitySilently(deleteUrl) {
if (!deleteUrl || deleteUrl === "#") return Promise.reject("Invalid delete URL");
return fetch(deleteUrl)
.then((response) => {
if (!response.ok) throw new Error("Delete request failed");
return response;
});
}
let tagDisplayRemovalInitialized = false;
function initTagDisplayAndRemoval() {
if (tagDisplayRemovalInitialized) return;
@@ -1136,7 +1152,7 @@ function getElementVisualFontColor(element) {
}
function refreshNoteFilterVisuals() {
document.querySelectorAll(".note-card, .note-modal, .link-outer").forEach((element) => {
document.querySelectorAll(".note-card, .note-modal, .link-outer, .note-input-container").forEach((element) => {
applyNoteVisualState(element, {
color: getElementVisualColor(element),
filter: getElementVisualFilter(element),
@@ -1238,7 +1254,7 @@ function initThemeModeBackgroundSync() {
if (nextTheme === lastTheme) return;
lastTheme = nextTheme;
refreshNoteBackgroundVisuals();
refreshNoteFilterVisuals();
refreshBackgroundPalettes();
});
@@ -1388,17 +1404,12 @@ function ensureBackgroundStudioPanel() {
if (action === "set-defaults") {
if (mode === "draft") {
panelEl.dataset.color = "default";
panelEl.dataset.filter = "none";
panelEl.dataset.background = "none";
panelEl.dataset.fontColor = "auto";
applyDraft({ color: "default", filter: "none", background: "none", fontColor: "auto" });
applyDraft({ color: "default" });
renderBackgroundStudioPanel(panelEl);
} else if (mode === "modal") {
setModalNoteColor("default");
setModalNoteFilter("none");
} else {
setNoteColor(entityId, "default", editUrl);
setNoteFilter(entityId, "none", editUrl);
}
return;
}
@@ -1814,7 +1825,7 @@ function applyNoteVisualState(element, note) {
if (colorValue) {
element.style.backgroundColor = colorValue;
element.style.borderColor = "transparent";
element.style.removeProperty("border-color");
} else {
element.style.removeProperty("background-color");
}
@@ -2323,7 +2334,7 @@ function initTodoView(linkList, container) {
<div class="palette-popup note-modal-palette" id="todo-modal-color-popup"></div>
</div>
<a href="#" id="todo-modal-edit" title="Modifier"><i class="mdi mdi-pencil-outline"></i></a>
<button type="button" id="todo-modal-delete" title="Supprimer"><i class="mdi mdi-dots-vertical"></i></button>
<button type="button" id="todo-modal-delete" title="Supprimer"><i class="mdi mdi-delete-outline"></i></button>
</div>
<button type="button" class="note-modal-close-btn" id="todo-modal-close">Fermer</button>
</div>
@@ -2403,10 +2414,19 @@ function initTodoView(linkList, container) {
});
modalOverlay.querySelector("#todo-modal-delete").addEventListener("click", () => {
if (!confirm("Supprimer cette tâche ?")) return;
const modalCard = modalOverlay.querySelector(".note-modal");
const deleteUrl = modalCard.dataset.deleteUrl;
const todoId = modalCard.dataset.todoId;
if (deleteUrl && deleteUrl !== "#") {
window.location.href = deleteUrl;
deleteEntitySilently(deleteUrl)
.then(() => {
window.location.href = "/?searchtags=shaarli-todo";
})
.catch((err) => {
console.error("Delete failed:", err);
alert("Erreur lors de la suppression.");
});
}
});
@@ -2884,6 +2904,13 @@ function renderTodos(container, todos, viewMode) {
const actions = document.createElement("div");
actions.className = "note-hover-actions";
const pinCorner = document.createElement("a");
pinCorner.href = todo.pinUrl;
pinCorner.title = todo.isPinned ? "Unpin" : "Pin";
pinCorner.className = `note-pin-corner ${todo.isPinned ? "active" : ""}`;
pinCorner.innerHTML = `<i class="mdi mdi-pin${todo.isPinned ? "" : "-outline"}"></i>`;
inner.appendChild(pinCorner);
const paletteBtnId = `palette-${todo.id}`;
actions.innerHTML = `
@@ -2891,11 +2918,25 @@ function renderTodos(container, todos, viewMode) {
<button title="Couleur" id="${paletteBtnId}"><i class="mdi mdi-palette-outline"></i></button>
</div>
<div class="spacer"></div>
<a href="${todo.pinUrl}" title="${todo.isPinned ? "Unpin" : "Pin"}" class="${todo.isPinned ? "active" : ""}"><i class="mdi mdi-pin${todo.isPinned ? "" : "-outline"}"></i></a>
<a href="${todo.editUrl}" title="Edit"><i class="mdi mdi-pencil-outline"></i></a>
<button title="Plus" onclick="window.location.href='${todo.deleteUrl}'"><i class="mdi mdi-dots-vertical"></i></button>
<a href="${todo.editUrl}" title="Modifier"><i class="mdi mdi-pencil-outline"></i></a>
<button title="Supprimer" class="todo-delete-btn"><i class="mdi mdi-delete-outline"></i></button>
`;
const deleteBtn = actions.querySelector(".todo-delete-btn");
deleteBtn?.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
if (!confirm("Supprimer cette tâche ?")) return;
deleteEntitySilently(todo.deleteUrl)
.then(() => {
window.location.href = "/?searchtags=shaarli-todo";
})
.catch((err) => {
console.error("Delete failed:", err);
alert("Erreur lors de la suppression.");
});
});
const paletteBtn = actions.querySelector(`#${paletteBtnId}`);
paletteBtn.addEventListener("click", (e) => {
e.preventDefault();
@@ -3841,7 +3882,7 @@ function initNoteView(linkList, container) {
<button type="button" title="Image"><i class="mdi mdi-image-outline"></i></button>
<button type="button" id="note-modal-archive" title="Archiver"><i class="mdi mdi-archive-arrow-down-outline"></i></button>
<a href="#" id="note-modal-edit" title="Modifier"><i class="mdi mdi-pencil-outline"></i></a>
<button type="button" id="note-modal-delete" title="Supprimer"><i class="mdi mdi-dots-vertical"></i></button>
<button type="button" id="note-modal-delete" title="Supprimer"><i class="mdi mdi-delete-outline"></i></button>
</div>
<button type="button" class="note-modal-close-btn" id="note-modal-close">Fermer</button>
</div>
@@ -3945,10 +3986,19 @@ function initNoteView(linkList, container) {
});
modalOverlay.querySelector("#note-modal-delete").addEventListener("click", () => {
if (!confirm("Supprimer cette note ?")) return;
const modalCard = modalOverlay.querySelector(".note-modal");
const deleteUrl = modalCard.dataset.deleteUrl;
const noteId = modalCard.dataset.noteId;
if (deleteUrl && deleteUrl !== "#") {
window.location.href = deleteUrl;
deleteEntitySilently(deleteUrl)
.then(() => {
window.location.href = "/?searchtags=note";
})
.catch((err) => {
console.error("Delete failed:", err);
alert("Erreur lors de la suppression.");
});
}
});
@@ -4046,7 +4096,7 @@ function initArchiveView(linkList, container) {
const notes = links.map((link) => parseNoteFromLink(link));
// Filter only archived notes
const archivedNotes = notes.filter((note) => (note.tags || []).includes("shaarli-archive"));
const archivedNotes = notes.filter((note) => (note.tags || []).some((t) => t === "shaarli-archive" || t === "shaarli-archiver"));
// Initial Render (Grid)
renderNotes(contentArea, archivedNotes, "grid", true); // true = archive mode
@@ -4085,7 +4135,7 @@ function initArchiveView(linkList, container) {
<button type="button" title="Image"><i class="mdi mdi-image-outline"></i></button>
<button type="button" id="note-modal-unarchive" title="Désarchiver"><i class="mdi mdi-archive-arrow-up-outline"></i></button>
<a href="#" id="note-modal-edit" title="Modifier"><i class="mdi mdi-pencil-outline"></i></a>
<button type="button" id="note-modal-delete" title="Supprimer"><i class="mdi mdi-dots-vertical"></i></button>
<button type="button" id="note-modal-delete" title="Supprimer"><i class="mdi mdi-delete-outline"></i></button>
</div>
<button type="button" class="note-modal-close-btn" id="note-modal-close">Fermer</button>
</div>
@@ -4171,10 +4221,19 @@ function initArchiveView(linkList, container) {
});
modalOverlay.querySelector("#note-modal-delete").addEventListener("click", () => {
if (!confirm("Supprimer cette note ?")) return;
const modalCard = modalOverlay.querySelector(".note-modal");
const deleteUrl = modalCard.dataset.deleteUrl;
const noteId = modalCard.dataset.noteId;
if (deleteUrl && deleteUrl !== "#") {
window.location.href = deleteUrl;
deleteEntitySilently(deleteUrl)
.then(() => {
window.location.href = "/?searchtags=shaarli-archive";
})
.catch((err) => {
console.error("Delete failed:", err);
alert("Erreur lors de la suppression.");
});
}
});
@@ -4293,10 +4352,10 @@ function renderNotes(container, notes, viewMode, isArchiveMode = false) {
let visibleNotes;
if (isArchiveMode) {
// In archive mode: show only notes with shaarli-archive tag
visibleNotes = notes.filter((note) => (note.tags || []).includes("shaarli-archive"));
visibleNotes = notes.filter((note) => (note.tags || []).some((t) => t === "shaarli-archive" || t === "shaarli-archiver"));
} else {
// In normal notes mode: hide archived notes
visibleNotes = notes.filter((note) => !(note.tags || []).includes("shaarli-archive"));
visibleNotes = notes.filter((note) => !(note.tags || []).some((t) => t === "shaarli-archive" || t === "shaarli-archiver"));
}
// Sort: Pinned items first
@@ -4348,7 +4407,7 @@ function renderNotes(container, notes, viewMode, isArchiveMode = false) {
if (note.descHtml || note.descText || note._noteMarkdown) {
const body = document.createElement("div");
body.className = "note-body";
if (note._noteMarkdown !== undefined) {
body.innerHTML = renderMarkdown(note._noteMarkdown);
} else {
@@ -4359,7 +4418,7 @@ function renderNotes(container, notes, viewMode, isArchiveMode = false) {
body.innerHTML = renderMarkdown(textToRender);
}
}
inner.appendChild(body);
}
@@ -4379,6 +4438,13 @@ function renderNotes(container, notes, viewMode, isArchiveMode = false) {
const actions = document.createElement("div");
actions.className = "note-hover-actions";
const pinCorner = document.createElement("a");
pinCorner.href = note.pinUrl;
pinCorner.title = note.isPinned ? "Unpin" : "Pin";
pinCorner.className = `note-pin-corner ${note.isPinned ? "active" : ""}`;
pinCorner.innerHTML = `<i class="mdi mdi-pin${note.isPinned ? "" : "-outline"}"></i>`;
inner.appendChild(pinCorner);
// Palette Button Logic
const paletteBtnId = `palette-${note.id}`;
const archiveBtnId = `archive-${note.id}`;
@@ -4393,11 +4459,25 @@ function renderNotes(container, notes, viewMode, isArchiveMode = false) {
<button title="Archiver" id="${archiveBtnId}"><i class="mdi mdi-archive-arrow-down-outline"></i></button>
<div class="spacer"></div>
<!-- Real Actions -->
<a href="${note.pinUrl}" title="${note.isPinned ? "Unpin" : "Pin"}" class="${note.isPinned ? "active" : ""}"><i class="mdi mdi-pin${note.isPinned ? "" : "-outline"}"></i></a>
<button type="button" class="note-open-editor-btn" title="Modifier"><i class="mdi mdi-pencil-outline"></i></button>
<button title="Plus" onclick="window.location.href='${note.deleteUrl}'"><i class="mdi mdi-dots-vertical"></i></button>
<button title="Supprimer" class="note-delete-btn"><i class="mdi mdi-delete-outline"></i></button>
`;
const deleteBtn = actions.querySelector(".note-delete-btn");
deleteBtn?.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
if (!confirm("Supprimer cette note ?")) return;
deleteEntitySilently(note.deleteUrl)
.then(() => {
window.location.href = isArchiveMode ? "/?searchtags=shaarli-archive" : "/?searchtags=note";
})
.catch((err) => {
console.error("Delete failed:", err);
alert("Erreur lors de la suppression.");
});
});
const openEditorBtn = actions.querySelector(".note-open-editor-btn");
openEditorBtn?.addEventListener("click", (e) => {
e.preventDefault();
@@ -5211,7 +5291,7 @@ function initPinnedItems() {
document.addEventListener(
"click",
function (e) {
const btn = e.target.closest('a[href*="do=pin"], .note-hover-actions a[href*="pin"], .link-actions a[href*="pin"]');
const btn = e.target.closest('a[href*="do=pin"], .note-hover-actions a[href*="pin"], .note-pin-corner[href*="pin"], .link-actions a[href*="pin"]');
if (btn) {
e.preventDefault();
e.stopPropagation();
@@ -5496,15 +5576,15 @@ function openColorPickerPanel({ mode, entityId, editUrl, type }) {
const bgPanel = document.getElementById("shaarli-bg-studio");
prevFontColorKey = bgPanel ? (bgPanel.dataset.fontColor || "auto") : "auto";
} else
if ((mode || "entity") === "modal") {
const modal = getOpenModalOverlay();
const modalCard = modal ? modal.querySelector(".note-modal") : null;
prevFontColorKey = (modalCard && modalCard.dataset.fontColor) ? modalCard.dataset.fontColor : "auto";
} else {
const noteCard = document.querySelector(`.note-card[data-id="${entityId}"]`);
const bookmarkCard = document.querySelector(`.link-outer[data-id="${entityId}"]`);
prevFontColorKey = (noteCard && noteCard.dataset.fontColor) ? noteCard.dataset.fontColor : ((bookmarkCard && bookmarkCard.dataset.fontColor) ? bookmarkCard.dataset.fontColor : "auto");
}
if ((mode || "entity") === "modal") {
const modal = getOpenModalOverlay();
const modalCard = modal ? modal.querySelector(".note-modal") : null;
prevFontColorKey = (modalCard && modalCard.dataset.fontColor) ? modalCard.dataset.fontColor : "auto";
} else {
const noteCard = document.querySelector(`.note-card[data-id="${entityId}"]`);
const bookmarkCard = document.querySelector(`.link-outer[data-id="${entityId}"]`);
prevFontColorKey = (noteCard && noteCard.dataset.fontColor) ? noteCard.dataset.fontColor : ((bookmarkCard && bookmarkCard.dataset.fontColor) ? bookmarkCard.dataset.fontColor : "auto");
}
panel.dataset.prevFontColorKey = prevFontColorKey;
} else {
panel.dataset.prevFontColorKey = "";
@@ -5518,24 +5598,24 @@ function openColorPickerPanel({ mode, entityId, editUrl, type }) {
prevColorKey = bgPanel.dataset.color || "default";
}
} else
if ((mode || "entity") === "modal") {
const modal = getOpenModalOverlay();
const modalCard = modal ? modal.querySelector(".note-modal") : null;
if (modalCard) {
const isCustom = modalCard.dataset.color === "custom";
const cc = modalCard.dataset.customColor || "";
prevColorKey = isCustom && cc ? `custom:${cc}` : getElementVisualColor(modalCard);
if ((mode || "entity") === "modal") {
const modal = getOpenModalOverlay();
const modalCard = modal ? modal.querySelector(".note-modal") : null;
if (modalCard) {
const isCustom = modalCard.dataset.color === "custom";
const cc = modalCard.dataset.customColor || "";
prevColorKey = isCustom && cc ? `custom:${cc}` : getElementVisualColor(modalCard);
}
} else {
const noteCard = document.querySelector(`.note-card[data-id="${entityId}"]`);
const bookmarkCard = document.querySelector(`.link-outer[data-id="${entityId}"]`);
const el = noteCard || bookmarkCard;
if (el) {
const isCustom = el.dataset.color === "custom";
const cc = el.dataset.customColor || "";
prevColorKey = isCustom && cc ? `custom:${cc}` : getElementVisualColor(el);
}
}
} else {
const noteCard = document.querySelector(`.note-card[data-id="${entityId}"]`);
const bookmarkCard = document.querySelector(`.link-outer[data-id="${entityId}"]`);
const el = noteCard || bookmarkCard;
if (el) {
const isCustom = el.dataset.color === "custom";
const cc = el.dataset.customColor || "";
prevColorKey = isCustom && cc ? `custom:${cc}` : getElementVisualColor(el);
}
}
panel.dataset.prevColorKey = prevColorKey;
} else {
panel.dataset.prevColorKey = "";
@@ -5732,10 +5812,11 @@ function openColorPickerPanel({ mode, entityId, editUrl, type }) {
setFromHex(defaultColor);
}
panel.style.display = "block";
panel.style.visibility = "hidden";
// Position the color picker panel
positionColorPickerPanel(panel, mode);
panel.style.display = "block";
panel.style.visibility = "visible";
panel.classList.add("open");
panel.setAttribute("aria-hidden", "false");
}
@@ -5751,20 +5832,26 @@ function positionColorPickerPanel(panel, mode) {
if (bgPanel && bgPanel.classList.contains("open")) {
const bgRect = bgPanel.getBoundingClientRect();
const panelRect = panel.getBoundingClientRect();
const panelWidth = Math.max(1, panelRect.width);
const panelHeight = Math.max(1, panelRect.height);
// Position to the right of the bg-studio panel
let left = bgRect.right + 10;
let top = bgRect.top;
// Check if it fits on the right
if (left + panel.offsetWidth > window.innerWidth - viewportPadding) {
if (left + panelWidth > window.innerWidth - viewportPadding) {
// Position to the left instead
left = bgRect.left - panel.offsetWidth - 10;
left = bgRect.left - panelWidth - 10;
}
// Ensure it stays within viewport
if (left < viewportPadding) left = viewportPadding;
if (top + panel.offsetHeight > window.innerHeight - viewportPadding) {
top = window.innerHeight - viewportPadding - panel.offsetHeight;
if (left + panelWidth > window.innerWidth - viewportPadding) {
left = window.innerWidth - viewportPadding - panelWidth;
}
if (top + panelHeight > window.innerHeight - viewportPadding) {
top = window.innerHeight - viewportPadding - panelHeight;
}
if (top < viewportPadding) top = viewportPadding;
@@ -5775,8 +5862,10 @@ function positionColorPickerPanel(panel, mode) {
} else {
// Center in viewport if bg panel not available
const panelRect = panel.getBoundingClientRect();
const left = Math.max(viewportPadding, (window.innerWidth - panelRect.width) / 2);
const top = Math.max(viewportPadding, (window.innerHeight - panelRect.height) / 2);
const clampedWidth = Math.max(1, panelRect.width);
const clampedHeight = Math.max(1, panelRect.height);
const left = Math.max(viewportPadding, Math.min((window.innerWidth - clampedWidth) / 2, window.innerWidth - viewportPadding - clampedWidth));
const top = Math.max(viewportPadding, Math.min((window.innerHeight - clampedHeight) / 2, window.innerHeight - viewportPadding - clampedHeight));
panel.style.left = `${Math.round(left)}px`;
panel.style.top = `${Math.round(top)}px`;
}
@@ -5899,7 +5988,7 @@ function setNoteColorVisual(noteId, colorKey) {
});
element.classList.add("note-color-custom");
element.style.backgroundColor = hex;
element.style.borderColor = "transparent";
element.style.removeProperty("border-color");
element.dataset.color = "custom";
element.dataset.customColor = hex;
const fg = getReadableForegroundForBackground(hex);
@@ -6038,7 +6127,7 @@ function setModalCustomNoteColor(color) {
const modalCard = modal.querySelector(".note-modal");
if (modalCard) {
modalCard.style.backgroundColor = color;
modalCard.style.borderColor = "transparent";
modalCard.style.removeProperty("border-color");
modalCard.dataset.color = "custom";
modalCard.dataset.customColor = color;
}