From d68879cb871876b867ad493ff03f7365c8bba53b Mon Sep 17 00:00:00 2001 From: Mathias Elle Date: Tue, 10 Feb 2026 12:47:43 +0100 Subject: [PATCH] feat: implement dark/light mode theme selection and admin configuration section --- src/Block/Inspector.php | 10 +++ src/Model/Config/Source/InspectorTheme.php | 22 ++++++ src/etc/acl.xml | 16 ++++ src/etc/adminhtml/system.xml | 27 +++++++ src/etc/config.xml | 5 ++ src/view/frontend/templates/inspector.phtml | 4 +- src/view/frontend/web/css/inspector.css | 86 +++++++++++++++++++-- src/view/frontend/web/js/inspector.js | 37 +++++---- 8 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 src/Model/Config/Source/InspectorTheme.php create mode 100644 src/etc/acl.xml create mode 100644 src/etc/adminhtml/system.xml diff --git a/src/Block/Inspector.php b/src/Block/Inspector.php index 1e6b37f..8c80358 100644 --- a/src/Block/Inspector.php +++ b/src/Block/Inspector.php @@ -81,6 +81,16 @@ public function getJsUrl(): string return $this->getViewFileUrl('OpenForgeProject_MageForge::js/inspector.js'); } + /** + * Get configured theme + * + * @return string + */ + public function getTheme(): string + { + return (string) $this->scopeConfig->getValue('mageforge/inspector/theme') ?: 'dark'; + } + /** * Render block HTML * diff --git a/src/Model/Config/Source/InspectorTheme.php b/src/Model/Config/Source/InspectorTheme.php new file mode 100644 index 0000000..df7a58e --- /dev/null +++ b/src/Model/Config/Source/InspectorTheme.php @@ -0,0 +1,22 @@ +> + */ + public function toOptionArray(): array + { + return [ + ['value' => 'dark', 'label' => (string) __('Dark')], + ['value' => 'light', 'label' => (string) __('Light')], + ['value' => 'auto', 'label' => (string) __('Auto (System Preference)')], + ]; + } +} diff --git a/src/etc/acl.xml b/src/etc/acl.xml new file mode 100644 index 0000000..2c26999 --- /dev/null +++ b/src/etc/acl.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/etc/adminhtml/system.xml b/src/etc/adminhtml/system.xml new file mode 100644 index 0000000..87096a2 --- /dev/null +++ b/src/etc/adminhtml/system.xml @@ -0,0 +1,27 @@ + + + + + + +
+ + mageforge + OpenForgeProject_MageForge::config_inspector + + + + + Magento\Config\Model\Config\Source\Yesno + dev/mageforge_inspector/enabled + + + + OpenForgeProject\MageForge\Model\Config\Source\InspectorTheme + mageforge/inspector/theme + Choose between Dark, Light, or Auto (System Preference) theme. + + +
+
+
diff --git a/src/etc/config.xml b/src/etc/config.xml index 53b3473..bec36f2 100644 --- a/src/etc/config.xml +++ b/src/etc/config.xml @@ -7,5 +7,10 @@ 0 + + + dark + + diff --git a/src/view/frontend/templates/inspector.phtml b/src/view/frontend/templates/inspector.phtml index 4fcedb0..b1d9eb0 100644 --- a/src/view/frontend/templates/inspector.phtml +++ b/src/view/frontend/templates/inspector.phtml @@ -44,6 +44,8 @@ -
+
diff --git a/src/view/frontend/web/css/inspector.css b/src/view/frontend/web/css/inspector.css index ccc6b71..b812e47 100644 --- a/src/view/frontend/web/css/inspector.css +++ b/src/view/frontend/web/css/inspector.css @@ -33,6 +33,12 @@ --mageforge-bg-dark: rgba(15, 23, 42, 0.98); --mageforge-bg-dark-alt: rgba(30, 41, 59, 0.98); --mageforge-border-color: rgba(148, 163, 184, 0.15); + + /* Glass/Overlay Variables */ + --mageforge-surface-glass: rgba(255, 255, 255, 0.05); + --mageforge-surface-glass-hover: rgba(255, 255, 255, 0.08); /* slightly lighter for hover */ + --mageforge-border-glass: rgba(255, 255, 255, 0.1); + --mageforge-shadow-glow: rgba(255, 255, 255, 0.05); } .mageforge-inspector { @@ -157,8 +163,8 @@ right: 12px; width: 28px; height: 28px; - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--mageforge-surface-glass); + border: 1px solid var(--mageforge-border-glass); border-radius: 6px; color: var(--mageforge-color-slate-400); font-size: 16px; @@ -502,9 +508,9 @@ display: inline-block; transition: all 0.2s ease; padding: 6px 10px; - background: rgba(255, 255, 255, 0.03); + background: var(--mageforge-surface-glass); /* ~3% opacity */ border-radius: 6px; - border: 1px solid rgba(255, 255, 255, 0.08); + border: 1px solid var(--mageforge-border-glass); /* ~8% opacity */ width: 100%; box-sizing: border-box; font-family: 'SF Mono', 'Monaco', 'Consolas', monospace; @@ -512,8 +518,8 @@ } .mageforge-info-value:hover { - background: rgba(255, 255, 255, 0.06); - border-color: rgba(255, 255, 255, 0.15); + background: var(--mageforge-surface-glass-hover); + border-color: var(--mageforge-border-color); /* fallback or stronger border */ transform: translateY(-1px); } @@ -589,7 +595,7 @@ } .mageforge-code-tag { - background: rgba(255,255,255,0.05); + background: var(--mageforge-surface-glass); padding: 2px 6px; border-radius: 4px; font-family: monospace; @@ -671,3 +677,69 @@ from { stroke-dashoffset: 500; } to { stroke-dashoffset: 0; } } + +/* ============================================================================ + Theme Overrides + ========================================================================== */ + +/* Explicit Light Mode */ +.mageforge-inspector[data-theme="light"] { + --mageforge-bg-dark: rgba(255, 255, 255, 0.98); + --mageforge-bg-dark-alt: rgba(248, 250, 252, 0.98); + --mageforge-border-color: rgba(0, 0, 0, 0.12); + + --mageforge-color-slate-100: #0f172a; /* Slate 900 */ + --mageforge-color-slate-200: #1e293b; /* Slate 800 */ + --mageforge-color-slate-300: #334155; /* Slate 700 */ + --mageforge-color-slate-400: #64748b; /* Slate 500 */ + --mageforge-color-slate-500: #94a3b8; /* Slate 400 */ + + /* Glass Overlays - Inverted for light mode */ + --mageforge-surface-glass: rgba(0, 0, 0, 0.05); + --mageforge-surface-glass-hover: rgba(0, 0, 0, 0.08); + --mageforge-border-glass: rgba(0, 0, 0, 0.1); + --mageforge-shadow-glow: rgba(0, 0, 0, 0.05); +} + +/* Auto Mode - Light Preference */ +@media (prefers-color-scheme: light) { + .mageforge-inspector[data-theme="auto"] { + --mageforge-bg-dark: rgba(255, 255, 255, 0.98); + --mageforge-bg-dark-alt: rgba(248, 250, 252, 0.98); + --mageforge-border-color: rgba(0, 0, 0, 0.12); + + --mageforge-color-slate-100: #0f172a; + --mageforge-color-slate-200: #1e293b; + --mageforge-color-slate-300: #334155; + --mageforge-color-slate-400: #64748b; + --mageforge-color-slate-500: #94a3b8; + + /* Glass Overlays - Inverted for light mode */ + --mageforge-surface-glass: rgba(0, 0, 0, 0.05); + --mageforge-surface-glass-hover: rgba(0, 0, 0, 0.08); + --mageforge-border-glass: rgba(0, 0, 0, 0.1); + --mageforge-shadow-glow: rgba(0, 0, 0, 0.05); + } +} + +/* Fix for hardcoded white text in light mode */ +.mageforge-inspector[data-theme="light"] .mageforge-text-white { + color: var(--mageforge-color-slate-100); +} + +@media (prefers-color-scheme: light) { + .mageforge-inspector[data-theme="auto"] .mageforge-text-white { + color: var(--mageforge-color-slate-100); + } + + .mageforge-inspector[data-theme="auto"].mageforge-inspector-float-button, + .mageforge-inspector[data-theme="auto"] .mageforge-inspector-float-button { + color: white; /* Button should stay white */ + } +} + +.mageforge-inspector[data-theme="light"].mageforge-inspector-float-button, +.mageforge-inspector[data-theme="light"] .mageforge-inspector-float-button { + color: white; +} + diff --git a/src/view/frontend/web/js/inspector.js b/src/view/frontend/web/js/inspector.js index 16da717..1a63f90 100644 --- a/src/view/frontend/web/js/inspector.js +++ b/src/view/frontend/web/js/inspector.js @@ -269,6 +269,12 @@ document.addEventListener('alpine:init', () => { createHighlightBox() { this.highlightBox = document.createElement('div'); this.highlightBox.className = 'mageforge-inspector mageforge-inspector-highlight'; + + // Propagate theme from root element to injected body element + if (this.$el && this.$el.hasAttribute('data-theme')) { + this.highlightBox.setAttribute('data-theme', this.$el.getAttribute('data-theme')); + } + this.highlightBox.style.display = 'none'; document.body.appendChild(this.highlightBox); @@ -280,6 +286,12 @@ document.addEventListener('alpine:init', () => { createInfoBadge() { this.infoBadge = document.createElement('div'); this.infoBadge.className = 'mageforge-inspector mageforge-inspector-info-badge'; + + // Propagate theme from root element to injected body element + if (this.$el && this.$el.hasAttribute('data-theme')) { + this.infoBadge.setAttribute('data-theme', this.$el.getAttribute('data-theme')); + } + this.infoBadge.style.display = 'none'; // Create arrow element @@ -296,6 +308,12 @@ document.addEventListener('alpine:init', () => { createFloatingButton() { this.floatingButton = document.createElement('button'); this.floatingButton.className = 'mageforge-inspector mageforge-inspector-float-button'; + + // Propagate theme from root element to injected body element + if (this.$el && this.$el.hasAttribute('data-theme')) { + this.floatingButton.setAttribute('data-theme', this.$el.getAttribute('data-theme')); + } + this.floatingButton.type = 'button'; this.floatingButton.title = 'Activate Inspector (Ctrl+Shift+I)'; @@ -304,19 +322,12 @@ document.addEventListener('alpine:init', () => { // Icon + Text with unique gradient ID this.floatingButton.innerHTML = ` - - - - - - - - - - - - - + + + + + + MageForge Inspector `;