From 404c03610867736e5197412cca44f0a14169cfcd Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Mon, 20 Apr 2026 10:51:48 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20impl=C3=A9menter=20syst=C3=A8me=20th?= =?UTF-8?q?=C3=A8mes=20complet=20avec=2014=20th=C3=A8mes=20pr=C3=A9d=C3=A9?= =?UTF-8?q?finis=20(DEFAULT/GitHub/Linear/Spotify/Notion/Discord/Dracula/O?= =?UTF-8?q?neDark/TokyoNight/Nord/NightOwl/Anthracite/Cyberpunk/NavyElegan?= =?UTF-8?q?ce/Earthy),=20panel=20gestion=20th=C3=A8mes=20dans=20tools.html?= =?UTF-8?q?=20avec=20grid=20previews=20et=20s=C3=A9lection=20interactive,?= =?UTF-8?q?=20synchronisation=20bidirectionnelle=20via=20bookmark=20shaari?= =?UTF-8?q?t=5Fconfig=20(fetch/save=20JSON=20config),=20enforcement=20dark?= =?UTF-8?q?-only=20pour=20th=C3=A8mes=20sans=20support=20light=20mode=20(d?= =?UTF-8?q?isable=20toggle=20sidebar,=20auto-force=20dark),=20ajout=20data?= =?UTF-8?q?-theme-id=20attribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shaarli-pro/css/themes.css | 469 +++++++++++++++++++++++++++++++++++++ shaarli-pro/includes.html | 17 +- shaarli-pro/js/script.js | 63 ++++- shaarli-pro/tools.html | 314 +++++++++++++++++++++++++ 4 files changed, 860 insertions(+), 3 deletions(-) create mode 100644 shaarli-pro/css/themes.css diff --git a/shaarli-pro/css/themes.css b/shaarli-pro/css/themes.css new file mode 100644 index 0000000..56c7abd --- /dev/null +++ b/shaarli-pro/css/themes.css @@ -0,0 +1,469 @@ +/* === Système de design ShaarIt - 16 Thèmes === */ + +/* Typographie globale (s'applique à tous) */ +:root { + --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + --text-xs: 0.75rem; + --text-sm: 0.875rem; + --text-base: 1rem; + --text-lg: 1.125rem; + --text-xl: 1.25rem; + --text-2xl: 1.5rem; + + --radius-xs: 4px; + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 16px; + --radius-xl: 28px; + --radius-full: 9999px; + + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); +} + +/* 1. DEFAULT (ShaarIt) - DARK (Par défaut si pas de light) */ +:root, :root[data-theme-id="DEFAULT"] { + --primary: #00D4AA; + --on-primary: #0A1628; + --primary-container: #243447; + --on-primary-container: #4EECC4; + + --secondary: #0EA5E9; + --on-secondary: #0A1628; + --secondary-container: #2A3F54; + --on-secondary-container: #38BDF8; + + --tertiary: #4EECC4; + --on-tertiary: #0A1628; + + --background: #0A1628; + --on-background: #E2E8F0; + + --surface: #0D1B2A; + --on-surface: #E2E8F0; + + --surface-variant: #1B2838; + --on-surface-variant: #94A3B8; + + --outline: #64748B; + --outline-variant: #2A3F54; + + --error: #EF4444; + --on-error: #FFFFFF; + --error-container: #450A0A; + --on-error-container: #FCA5A5; +} + +/* 1. DEFAULT (ShaarIt) - LIGHT */ +:root[data-theme="light"][data-theme-id="DEFAULT"] { + --primary: #006B5A; + --on-primary: #FFFFFF; + --primary-container: #B2F5E6; + --on-primary-container: #00201A; + + --secondary: #0077B6; + --on-secondary: #FFFFFF; + --secondary-container: #D0E8FF; + --on-secondary-container: #001E36; + + --tertiary: #00897B; + --on-tertiary: #FFFFFF; + + --background: #F8FAFA; + --on-background: #1A1C1E; + + --surface: #FFFFFF; + --on-surface: #1A1C1E; + + --surface-variant: #E7F0EE; + --on-surface-variant: #404944; + + --outline: #707974; + --outline-variant: #C0C9C4; + + --error: #BA1A1A; + --on-error: #FFFFFF; + --error-container: #FFDAD6; + --on-error-container: #410002; +} + +/* 2. GITHUB - DARK */ +:root[data-theme-id="GITHUB"] { + --primary: #58A6FF; + --on-primary: #0D1117; + --primary-container: #1F2937; + --on-primary-container: #79C0FF; + + --secondary: #3FB950; + --on-secondary: #0D1117; + --secondary-container: #1C2D22; + --on-secondary-container: #56D364; + + --tertiary: #D2A8FF; + --on-tertiary: #0D1117; + + --background: #0D1117; + --on-background: #C9D1D9; + + --surface: #161B22; + --on-surface: #C9D1D9; + + --surface-variant: #21262D; + --on-surface-variant: #8B949E; + + --outline: #30363D; + --outline-variant: #21262D; + + --error: #F85149; + --on-error: #FFFFFF; + --error-container: #490202; + --on-error-container: #FFA198; +} + +/* 2. GITHUB - LIGHT */ +:root[data-theme="light"][data-theme-id="GITHUB"] { + --primary: #0969DA; + --on-primary: #FFFFFF; + --primary-container: #DDF4FF; + --on-primary-container: #0A3069; + + --secondary: #1A7F37; + --on-secondary: #FFFFFF; + --secondary-container: #DAFBE1; + --on-secondary-container: #0E4F1F; + + --tertiary: #8250DF; + --on-tertiary: #FFFFFF; + + --background: #FFFFFF; + --on-background: #1F2328; + + --surface: #F6F8FA; + --on-surface: #1F2328; + + --surface-variant: #EAEEF2; + --on-surface-variant: #656D76; + + --outline: #D0D7DE; + --outline-variant: #E1E4E8; + + --error: #CF222E; + --on-error: #FFFFFF; + --error-container: #FFEBE9; + --on-error-container: #82071E; +} + +/* 3. LINEAR - DARK */ +:root[data-theme-id="LINEAR"] { + --primary: #5E6AD2; + --on-primary: #FFFFFF; + --primary-container: #2A2B3D; + --on-primary-container: #8B8FE8; + + --secondary: #4EA7FC; + --on-secondary: #12131A; + --secondary-container: #1E2A3A; + --on-secondary-container: #7DC4FF; + + --tertiary: #E8A861; + --on-tertiary: #12131A; + + --background: #12131A; + --on-background: #EEEFF2; + + --surface: #1B1C24; + --on-surface: #EEEFF2; + + --surface-variant: #22232E; + --on-surface-variant: #8A8F98; + + --outline: #3B3D4A; + --outline-variant: #2A2B3D; + + --error: #EB5757; + --on-error: #FFFFFF; + --error-container: #3D1515; + --on-error-container: #FF9B9B; +} + +/* 4. SPOTIFY - DARK */ +:root[data-theme-id="SPOTIFY"] { + --primary: #1DB954; + --on-primary: #000000; + --primary-container: #1A3D27; + --on-primary-container: #1ED760; + + --secondary: #1DB954; + --on-secondary: #000000; + + --tertiary: #B3B3B3; + --on-tertiary: #000000; + + --background: #000000; + --on-background: #FFFFFF; + + --surface: #121212; + --on-surface: #FFFFFF; + + --surface-variant: #1A1A1A; + --on-surface-variant: #B3B3B3; + + --outline: #333333; + --outline-variant: #282828; + + --error: #E22134; +} + +/* 5. NOTION - DARK */ +:root[data-theme-id="NOTION"] { + --primary: #529CCA; + --on-primary: #191919; + + --secondary: #E07A5F; + --on-secondary: #191919; + + --tertiary: #81B29A; + --on-tertiary: #191919; + + --background: #191919; + --on-background: #E0E0E0; + + --surface: #202020; + --on-surface: #E0E0E0; + + --surface-variant: #2B2B2B; + --on-surface-variant: #9B9B9B; + + --outline: #3E3E3E; +} + +/* 6. DISCORD - DARK */ +:root[data-theme-id="DISCORD"] { + --primary: #5865F2; + --on-primary: #FFFFFF; + + --secondary: #57F287; + --on-secondary: #1E2124; + + --tertiary: #FEE75C; + --on-tertiary: #1E2124; + + --background: #313338; + --on-background: #DBDEE1; + + --surface: #2B2D31; + --on-surface: #DBDEE1; + + --surface-variant: #383A40; + --on-surface-variant: #B5BAC1; + + --outline: #4E5058; +} + +/* 7. DRACULA - DARK */ +:root[data-theme-id="DRACULA"] { + --primary: #BD93F9; + --on-primary: #21222C; + + --secondary: #50FA7B; + --on-secondary: #21222C; + + --tertiary: #FF79C6; + --on-tertiary: #21222C; + + --background: #282A36; + --on-background: #F8F8F2; + + --surface: #21222C; + --on-surface: #F8F8F2; + + --surface-variant: #343746; + --on-surface-variant: #BFBFBF; + + --outline: #6272A4; +} + +/* 8. ONE DARK PRO - DARK */ +:root[data-theme-id="ONE_DARK_PRO"] { + --primary: #61AFEF; + --on-primary: #1E2127; + + --secondary: #98C379; + --on-secondary: #1E2127; + + --tertiary: #E5C07B; + --on-tertiary: #1E2127; + + --background: #282C34; + --on-background: #ABB2BF; + + --surface: #21252B; + --on-surface: #ABB2BF; + + --surface-variant: #2C313A; + --on-surface-variant: #8B929E; + + --outline: #3E4452; +} + +/* 9. TOKYO NIGHT - DARK */ +:root[data-theme-id="TOKYO_NIGHT"] { + --primary: #7AA2F7; + --on-primary: #1A1B26; + + --secondary: #9ECE6A; + --on-secondary: #1A1B26; + + --tertiary: #BB9AF7; + --on-tertiary: #1A1B26; + + --background: #1A1B26; + --on-background: #C0CAF5; + + --surface: #16171F; + --on-surface: #C0CAF5; + + --surface-variant: #24283B; + --on-surface-variant: #9AA5CE; + + --outline: #3B4261; +} + +/* 10. NORD - DARK */ +:root[data-theme-id="NORD"] { + --primary: #88C0D0; + --on-primary: #2E3440; + + --secondary: #A3BE8C; + --on-secondary: #2E3440; + + --tertiary: #EBCB8B; + --on-tertiary: #2E3440; + + --background: #2E3440; + --on-background: #ECEFF4; + + --surface: #3B4252; + --on-surface: #D8DEE9; + + --surface-variant: #434C5E; + --on-surface-variant: #D8DEE9; + + --outline: #4C566A; +} + +/* 11. NIGHT OWL - DARK */ +:root[data-theme-id="NIGHT_OWL"] { + --primary: #7FDBCA; + --on-primary: #011627; + + --secondary: #ADDB67; + --on-secondary: #011627; + + --tertiary: #C792EA; + --on-tertiary: #011627; + + --background: #011627; + --on-background: #D6DEEB; + + --surface: #0B2942; + --on-surface: #D6DEEB; + + --surface-variant: #112B45; + --on-surface-variant: #9FAFC2; + + --outline: #1D3B58; +} + +/* 12. ANTHRACITE - DARK */ +:root[data-theme-id="ANTHRACITE"] { + --primary: #BB86FC; + --on-primary: #121212; + + --secondary: #03DAC6; + --on-secondary: #121212; + + --tertiary: #CF6679; + --on-tertiary: #121212; + + --background: #121212; + --on-background: #E1E1E1; + + --surface: #1E1E1E; + --on-surface: #E1E1E1; + + --surface-variant: #2C2C2C; + --on-surface-variant: #AAAAAA; + + --outline: #3D3D3D; +} + +/* 13. CYBERPUNK - DARK */ +:root[data-theme-id="CYBERPUNK"] { + --primary: #00FFFF; + --on-primary: #0A0A14; + + --secondary: #FF00FF; + --on-secondary: #0A0A14; + + --tertiary: #FFFF00; + --on-tertiary: #0A0A14; + + --background: #0A0A14; + --on-background: #E0E0F0; + + --surface: #12121E; + --on-surface: #E0E0F0; + + --surface-variant: #1A1A2E; + --on-surface-variant: #A0A0C0; + + --outline: #2A2A44; +} + +/* 14. NAVY ELEGANCE - DARK */ +:root[data-theme-id="NAVY_ELEGANCE"] { + --primary: #D4AF37; + --on-primary: #0B1929; + + --secondary: #C0C0C0; + --on-secondary: #0B1929; + + --tertiary: #87CEEB; + --on-tertiary: #0B1929; + + --background: #0B1929; + --on-background: #E0E4EA; + + --surface: #0F2035; + --on-surface: #E0E4EA; + + --surface-variant: #162A42; + --on-surface-variant: #A0AABB; + + --outline: #1E3550; +} + +/* 15. EARTHY - DARK */ +:root[data-theme-id="EARTHY"] { + --primary: #81C784; + --on-primary: #1A1510; + + --secondary: #D4A574; + --on-secondary: #1A1510; + + --tertiary: #A5D6A7; + --on-tertiary: #1A1510; + + --background: #1A1510; + --on-background: #E0D8CF; + + --surface: #231E18; + --on-surface: #E0D8CF; + + --surface-variant: #2E2720; + --on-surface-variant: #ADA49A; + + --outline: #3D342B; +} diff --git a/shaarli-pro/includes.html b/shaarli-pro/includes.html index 25cbf98..f6d07af 100644 --- a/shaarli-pro/includes.html +++ b/shaarli-pro/includes.html @@ -10,10 +10,22 @@ + {if="$pageName=='editlink' || $pageName=='addlink' || $pageName=='editlinkbatch'"} diff --git a/shaarli-pro/js/script.js b/shaarli-pro/js/script.js index 7ae76ce..a11e63f 100644 --- a/shaarli-pro/js/script.js +++ b/shaarli-pro/js/script.js @@ -36,12 +36,26 @@ document.addEventListener('DOMContentLoaded', () => { const themeIconLight = document.getElementById('theme-icon-light'); const themeLabelSpan = document.querySelector('.theme-toggle-label span'); + function checkThemeRestrictions() { + const themeId = localStorage.getItem('shaarit_theme_id') || 'DEFAULT'; + const darkOnlyThemes = ['LINEAR', 'SPOTIFY', 'NOTION', 'DISCORD', 'DRACULA', 'ONE_DARK_PRO', 'TOKYO_NIGHT', 'NORD', 'NIGHT_OWL', 'ANTHRACITE', 'CYBERPUNK', 'NAVY_ELEGANCE', 'EARTHY']; + return darkOnlyThemes.indexOf(themeId) !== -1; + } + function updateTheme(theme) { + // Enforce dark mode if the theme only supports dark + if (checkThemeRestrictions()) { + theme = 'dark'; + } + document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('theme', theme); if (themeCheckbox) { themeCheckbox.checked = theme === 'dark'; + // Disable the checkbox if restricted to dark mode + themeCheckbox.disabled = checkThemeRestrictions(); + themeCheckbox.closest('.theme-switch').style.opacity = themeCheckbox.disabled ? '0.5' : '1'; } if (themeIconLight) { themeIconLight.className = theme === 'dark' ? 'mdi mdi-weather-night' : 'mdi mdi-weather-sunny'; @@ -51,13 +65,19 @@ document.addEventListener('DOMContentLoaded', () => { } } + // Handle themeChanged event fired by tools.html + window.addEventListener('themeChanged', () => { + updateTheme(localStorage.getItem('theme') || 'dark'); + }); + // Init Theme - const savedTheme = localStorage.getItem('theme') || + let savedTheme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); updateTheme(savedTheme); if (themeCheckbox) { themeCheckbox.addEventListener('change', () => { + if (checkThemeRestrictions()) return; // Extra safety const next = themeCheckbox.checked ? 'dark' : 'light'; updateTheme(next); }); @@ -3287,4 +3307,45 @@ document.addEventListener('DOMContentLoaded', () => { updateSummary(); renderDays(); })(); + + // ===== Sync Theme from Bookmark in Background ===== + setTimeout(() => { + // Run sync after a slight delay to avoid blocking initial load + if (!window.shaarli || !window.shaarli.basePath) return; + + fetch(window.shaarli.basePath + '/?searchtags=shaarit_config') + .then(res => res.text()) + .then(text => { + const parser = new DOMParser(); + const doc = parser.parseFromString(text, 'text/html'); + const linkCard = doc.querySelector('.linklist-item'); + if (linkCard) { + const descEl = linkCard.querySelector('.link-description p'); + if (descEl) { + try { + const config = JSON.parse(descEl.textContent.trim()); + const remoteThemeId = config.theme; + const localThemeId = localStorage.getItem('shaarit_theme_id') || 'DEFAULT'; + + if (remoteThemeId && remoteThemeId !== localThemeId) { + localStorage.setItem('shaarit_theme_id', remoteThemeId); + document.documentElement.setAttribute('data-theme-id', remoteThemeId); + + // Enforce light/dark constraints based on new theme + const darkOnlyThemes = ['LINEAR', 'SPOTIFY', 'NOTION', 'DISCORD', 'DRACULA', 'ONE_DARK_PRO', 'TOKYO_NIGHT', 'NORD', 'NIGHT_OWL', 'ANTHRACITE', 'CYBERPUNK', 'NAVY_ELEGANCE', 'EARTHY']; + if (darkOnlyThemes.indexOf(remoteThemeId) !== -1) { + localStorage.setItem('theme', 'dark'); + document.documentElement.setAttribute('data-theme', 'dark'); + } + + window.dispatchEvent(new Event('themeChanged')); + console.log('[shaarit] Theme synced from bookmark:', remoteThemeId); + } + } catch(e) {} + } + } + }) + .catch(err => console.log('[shaarit] Background theme sync failed:', err)); + }, 1500); + }); diff --git a/shaarli-pro/tools.html b/shaarli-pro/tools.html index f9d8af8..0978a31 100644 --- a/shaarli-pro/tools.html +++ b/shaarli-pro/tools.html @@ -14,6 +14,16 @@
{'Settings'|t}
+ + +