From 1313f78b935b05623a4f97f074f0115ccb685cd9 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Tue, 21 Apr 2026 11:37:58 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20ajouter=20support=20background=20images?= =?UTF-8?q?=20+=20filtres=20CSS=20overlay=20sur=20note=20cards=20avec=20cl?= =?UTF-8?q?asses=20.note-has-bg=20(background-image=20cover/center),=207?= =?UTF-8?q?=20filtres=20::after=20pseudo=20(glass=20backdrop-blur=202px,?= =?UTF-8?q?=20vignette=20radial-gradient=20dark=20edges,=20lined=20repeati?= =?UTF-8?q?ng=2028px=20horizontal,=20grid=2028px=20squared,=20noise=20SVG?= =?UTF-8?q?=20fractalNoise=200.06=20opacity,=20dots=20radial=2014px,=20str?= =?UTF-8?q?ipes=20diagonal=20-45deg),=20z-index=20layering=20.note-inner/h?= =?UTF-8?q?over-actions=20au-dessus=20overlay,=20et=20sync=20panel=20datas?= =?UTF-8?q?et=20(color/background/filter/fontColor)=20apr=C3=A8s=20chaque?= =?UTF-8?q?=20action=20set?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shaarli-pro/css/custom_views.css | 99 ++++++++++++++++++++++++++++++++ shaarli-pro/js/custom_views.js | 35 +++++++++-- 2 files changed, 130 insertions(+), 4 deletions(-) diff --git a/shaarli-pro/css/custom_views.css b/shaarli-pro/css/custom_views.css index 68f2d18..9cb648f 100644 --- a/shaarli-pro/css/custom_views.css +++ b/shaarli-pro/css/custom_views.css @@ -1580,4 +1580,103 @@ body.view-notes .notes-masonry:empty::after { .bg-studio-clear:hover { background: color-mix(in srgb, var(--text-main) 10%, transparent); color: var(--special-view-strong); +} + +/* ========================================================= + Note / Todo card — background image display + ========================================================= */ +.note-card.note-has-bg { + background-image: var(--note-bg-image, none) !important; + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.note-modal.note-has-bg { + background-image: var(--note-bg-image, none) !important; + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +/* ========================================================= + Note / Todo card — CSS filter overlays (::after pseudo) + ========================================================= */ +.note-card { + position: relative; +} + +.note-card.note-filter-glass::after, +.note-card.note-filter-vignette::after, +.note-card.note-filter-lined::after, +.note-card.note-filter-grid::after, +.note-card.note-filter-noise::after, +.note-card.note-filter-dots::after, +.note-card.note-filter-stripes::after { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + z-index: 0; + border-radius: inherit; +} + +/* Filter: Glass — frosted glass tint */ +.note-card.note-filter-glass::after { + background: rgba(255, 255, 255, 0.06); + backdrop-filter: blur(2px); + -webkit-backdrop-filter: blur(2px); +} + +/* Filter: Vignette — dark edges */ +.note-card.note-filter-vignette::after { + background: radial-gradient(ellipse at center, transparent 45%, rgba(0, 0, 0, 0.42) 100%); +} + +/* Filter: Lined — horizontal ruled lines */ +.note-card.note-filter-lined::after { + background-image: repeating-linear-gradient( + to bottom, + transparent 0px, + transparent 27px, + rgba(128, 128, 128, 0.18) 27px, + rgba(128, 128, 128, 0.18) 28px + ); +} + +/* Filter: Grid — squared grid */ +.note-card.note-filter-grid::after { + background-image: + repeating-linear-gradient(to right, rgba(128, 128, 128, 0.15) 0px, rgba(128, 128, 128, 0.15) 1px, transparent 1px, transparent 28px), + repeating-linear-gradient(to bottom, rgba(128, 128, 128, 0.15) 0px, rgba(128, 128, 128, 0.15) 1px, transparent 1px, transparent 28px); +} + +/* Filter: Noise — subtle stipple effect */ +.note-card.note-filter-noise::after { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E"); + background-repeat: repeat; +} + +/* Filter: Dots — dot pattern */ +.note-card.note-filter-dots::after { + background-image: radial-gradient(circle, rgba(128, 128, 128, 0.3) 1px, transparent 1px); + background-size: 14px 14px; +} + +/* Filter: Stripes — diagonal lines */ +.note-card.note-filter-stripes::after { + background-image: repeating-linear-gradient( + -45deg, + transparent 0px, + transparent 8px, + rgba(128, 128, 128, 0.12) 8px, + rgba(128, 128, 128, 0.12) 9px + ); +} + +/* Keep card inner content above the filter overlay */ +.note-card .note-inner, +.note-card .note-hover-actions { + position: relative; + z-index: 1; } \ No newline at end of file diff --git a/shaarli-pro/js/custom_views.js b/shaarli-pro/js/custom_views.js index 7863b00..462dfe4 100644 --- a/shaarli-pro/js/custom_views.js +++ b/shaarli-pro/js/custom_views.js @@ -1358,8 +1358,12 @@ function ensureBackgroundStudioPanel() { renderBackgroundStudioPanel(panelEl); } else if (mode === "modal") { setModalNoteColor(key); + panelEl.dataset.color = key; + renderBackgroundStudioPanel(panelEl); } else { setNoteColor(entityId, key, editUrl); + panelEl.dataset.color = key; + renderBackgroundStudioPanel(panelEl); } return; } @@ -1372,23 +1376,31 @@ function ensureBackgroundStudioPanel() { renderBackgroundStudioPanel(panelEl); } else if (mode === "modal") { setModalNoteBackground(key); + panelEl.dataset.background = key; + renderBackgroundStudioPanel(panelEl); } else { setNoteBackground(entityId, key, editUrl); + panelEl.dataset.background = key; + renderBackgroundStudioPanel(panelEl); } return; } if (action === "set-filter") { const filterKey = actionBtn.dataset.filter || "none"; + const normalizedFilter = normalizeFilterKey(filterKey || "") || "none"; if (mode === "draft") { - const normalized = normalizeFilterKey(filterKey || "") || "none"; - panelEl.dataset.filter = normalized; - applyDraft({ filter: normalized }); + panelEl.dataset.filter = normalizedFilter; + applyDraft({ filter: normalizedFilter }); renderBackgroundStudioPanel(panelEl); } else if (mode === "modal") { setModalNoteFilter(filterKey); + panelEl.dataset.filter = normalizedFilter; + renderBackgroundStudioPanel(panelEl); } else { setNoteFilter(entityId, filterKey, editUrl); + panelEl.dataset.filter = normalizedFilter; + renderBackgroundStudioPanel(panelEl); } return; } @@ -1404,12 +1416,19 @@ function ensureBackgroundStudioPanel() { if (action === "set-defaults") { if (mode === "draft") { panelEl.dataset.color = "default"; - applyDraft({ color: "default" }); + panelEl.dataset.background = "none"; + applyDraft({ color: "default", background: "none" }); renderBackgroundStudioPanel(panelEl); } else if (mode === "modal") { setModalNoteColor("default"); + panelEl.dataset.color = "default"; + panelEl.dataset.background = "none"; + renderBackgroundStudioPanel(panelEl); } else { setNoteColor(entityId, "default", editUrl); + panelEl.dataset.color = "default"; + panelEl.dataset.background = "none"; + renderBackgroundStudioPanel(panelEl); } return; } @@ -1421,8 +1440,12 @@ function ensureBackgroundStudioPanel() { renderBackgroundStudioPanel(panelEl); } else if (mode === "modal") { setModalNoteFontColor("auto"); + panelEl.dataset.fontColor = "auto"; + renderBackgroundStudioPanel(panelEl); } else { setNoteFontColor(entityId, "auto", editUrl); + panelEl.dataset.fontColor = "auto"; + renderBackgroundStudioPanel(panelEl); } return; } @@ -1445,8 +1468,12 @@ function ensureBackgroundStudioPanel() { renderBackgroundStudioPanel(panelEl); } else if (mode === "modal") { setModalNoteFontColor(fontColorKey); + panelEl.dataset.fontColor = fontColorKey; + renderBackgroundStudioPanel(panelEl); } else { setNoteFontColor(entityId, fontColorKey, editUrl); + panelEl.dataset.fontColor = fontColorKey; + renderBackgroundStudioPanel(panelEl); } return; }