From c027aaed3493313993ed4760a903a0d9b986d434 Mon Sep 17 00:00:00 2001 From: Fritz Date: Wed, 27 May 2026 18:25:19 +1000 Subject: [PATCH 1/3] feat: overlay properties panel, window polish, and help/docs menu - Properties panel now overlays the button grid instead of pushing it left so the mouse stays over the clicked button after flyout opens - Remove maximize button; set minWidth=960, minHeight=640 - Set window title to 'Tech Stack Studios - Streamdeck' (locked against page override) - Set taskbar icon to tech_stack_streamdeck.png (dev: public/, prod: dist/) - Replace static gear button with a Help & Documentation dropdown menu containing User Manual, Installation Guide, and Release Notes links --- electron/main.cjs | 12 +++++++++ src/App.css | 68 ++++++++++++++++++++++++++++++++++++++++++++--- src/App.jsx | 63 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 134 insertions(+), 9 deletions(-) diff --git a/electron/main.cjs b/electron/main.cjs index 0cacf81..c35f070 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -221,9 +221,18 @@ function sendToRenderer(channel, data) { } function createWindow() { + const iconPath = app.isPackaged + ? path.join(__dirname, '../dist/tech_stack_streamdeck.png') + : path.join(__dirname, '../public/tech_stack_streamdeck.png') + mainWindow = new BrowserWindow({ width: 1280, height: 800, + minWidth: 960, + minHeight: 640, + title: 'Tech Stack Studios - Streamdeck', + maximizable: false, + icon: iconPath, autoHideMenuBar: true, backgroundColor: '#1a1a1a', webPreferences: { @@ -245,6 +254,9 @@ function createWindow() { mainWindow = null }) + // Prevent the HTML page title from overriding the window title + mainWindow.on('page-title-updated', e => { e.preventDefault() }) + // Hide to tray on close unless a real quit was requested mainWindow.on('close', e => { if (!isQuitting) { e.preventDefault(); mainWindow.hide(); console.log('[App] Window hidden to tray') } diff --git a/src/App.css b/src/App.css index a0498bd..ee3c0cd 100644 --- a/src/App.css +++ b/src/App.css @@ -286,11 +286,69 @@ user-select: text; } +/* ─── Help / Documentation menu ─────────────────────────── */ +.help-menu-wrapper { + position: relative; +} + +.icon-btn.active { + background: #252525; + color: #bbb; +} + +.help-menu { + position: absolute; + top: calc(100% + 6px); + right: 0; + min-width: 200px; + background: #252525; + border: 1px solid #333; + border-radius: 8px; + padding: 6px 4px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); + z-index: 200; +} + +.help-menu-section-label { + padding: 4px 10px 6px; + font-size: 11px; + font-weight: 600; + color: #555; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.help-menu-item { + display: flex; + align-items: center; + gap: 8px; + width: 100%; + padding: 8px 10px; + border-radius: 5px; + background: none; + border: none; + color: #e0e0e0; + font-size: 13px; + cursor: pointer; + transition: background 0.1s; + text-align: left; +} + +.help-menu-item:hover { + background: #303030; +} + +.help-menu-item svg { + flex-shrink: 0; + color: #666; +} + /* ─── Workspace ──────────────────────────────────────────── */ .workspace { display: flex; flex: 1; overflow: hidden; + position: relative; } /* ─── Actions panel ──────────────────────────────────────── */ @@ -724,18 +782,22 @@ /* ─── Properties panel ───────────────────────────────────── */ .properties-panel { + position: absolute; + right: 0; + top: 0; + bottom: 0; width: 280px; - flex-shrink: 0; background: #1c1c1c; border-left: 1px solid #262626; display: flex; flex-direction: column; - animation: panel-in 0.14s ease; + z-index: 10; + animation: panel-in 0.18s ease; } @keyframes panel-in { from { - transform: translateX(16px); + transform: translateX(100%); opacity: 0; } to { diff --git a/src/App.jsx b/src/App.jsx index c941d1e..34ec1cc 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1462,6 +1462,62 @@ function PluginInspector({ action, onChange, pluginManifests = [] }) { ) } +// ─── Help / Documentation menu ────────────────────────────── +const HELP_LINKS = [ + { label: 'User Manual', url: 'https://github.com/FritzBlignaut/tech-stack-streamdeck/wiki/User-Manual' }, + { label: 'Installation Guide', url: 'https://github.com/FritzBlignaut/tech-stack-streamdeck/wiki/Installation-Guide' }, + { label: 'Release Notes', url: 'https://github.com/FritzBlignaut/tech-stack-streamdeck/releases' }, +] + +function HelpMenu() { + const [open, setOpen] = useState(false) + const ref = useRef(null) + + useEffect(() => { + if (!open) return + const handler = (e) => { + if (ref.current && !ref.current.contains(e.target)) setOpen(false) + } + document.addEventListener('mousedown', handler) + return () => document.removeEventListener('mousedown', handler) + }, [open]) + + return ( +
+ + + {open && ( +
+
Documentation
+ {HELP_LINKS.map(({ label, url }) => ( + + ))} +
+ )} +
+ ) +} + function PropertiesPanel({ keyIndex, onClose, config, onChange, iconSize, profiles, pageCount, onEnterFolder, pluginManifests = [] }) { const fileInputRef = useRef(null) const pressedFileInputRef = useRef(null) @@ -2606,12 +2662,7 @@ export default function App() { - + {appVersion && v{appVersion}-{__GIT_HASH__}} From 4ff738d7e8fe458226ee25d8af3ddbba4b6df13a Mon Sep 17 00:00:00 2001 From: Fritz Date: Wed, 27 May 2026 18:29:37 +1000 Subject: [PATCH 2/3] fix: prevent window maximize on Linux via maximize event handler --- electron/main.cjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/electron/main.cjs b/electron/main.cjs index c35f070..fe3d879 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -232,6 +232,7 @@ function createWindow() { minHeight: 640, title: 'Tech Stack Studios - Streamdeck', maximizable: false, + fullscreenable: false, icon: iconPath, autoHideMenuBar: true, backgroundColor: '#1a1a1a', @@ -257,6 +258,9 @@ function createWindow() { // Prevent the HTML page title from overriding the window title mainWindow.on('page-title-updated', e => { e.preventDefault() }) + // On Linux the window manager can maximize despite maximizable:false — force it back + mainWindow.on('maximize', () => mainWindow.unmaximize()) + // Hide to tray on close unless a real quit was requested mainWindow.on('close', e => { if (!isQuitting) { e.preventDefault(); mainWindow.hide(); console.log('[App] Window hidden to tray') } From 168614936344f4e1be27dca00aa186a3dca37864 Mon Sep 17 00:00:00 2001 From: Fritz Date: Wed, 27 May 2026 18:32:05 +1000 Subject: [PATCH 3/3] revert: remove fullscreenable and maximize event handler --- electron/main.cjs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/electron/main.cjs b/electron/main.cjs index fe3d879..c35f070 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -232,7 +232,6 @@ function createWindow() { minHeight: 640, title: 'Tech Stack Studios - Streamdeck', maximizable: false, - fullscreenable: false, icon: iconPath, autoHideMenuBar: true, backgroundColor: '#1a1a1a', @@ -258,9 +257,6 @@ function createWindow() { // Prevent the HTML page title from overriding the window title mainWindow.on('page-title-updated', e => { e.preventDefault() }) - // On Linux the window manager can maximize despite maximizable:false — force it back - mainWindow.on('maximize', () => mainWindow.unmaximize()) - // Hide to tray on close unless a real quit was requested mainWindow.on('close', e => { if (!isQuitting) { e.preventDefault(); mainWindow.hide(); console.log('[App] Window hidden to tray') }