diff --git a/public/app.js b/public/app.js index 712f2af..0b6c63e 100644 --- a/public/app.js +++ b/public/app.js @@ -20,6 +20,7 @@ const OPENAI_TRANSCRIPTION_MODELS = [ ]; const MOONSHINE_MODELS = ["tiny", "small", "medium"]; const MIC_STORAGE_KEY = "autopreso.mic"; +const PANEL_HIDDEN_STORAGE_KEY = "autopreso.panelHidden"; const STARTER_STAGING_ELEMENTS = []; @@ -57,6 +58,14 @@ function saveStoredMic(mic) { localStorage.setItem(MIC_STORAGE_KEY, JSON.stringify(mic)); } +function loadStoredPanelHidden() { + try { + return localStorage.getItem(PANEL_HIDDEN_STORAGE_KEY) === "1"; + } catch { + return false; + } +} + function App() { const [api, setApi] = React.useState(null); const [mode, setMode] = React.useState("staging"); @@ -74,6 +83,7 @@ function App() { const [sttError, setSttError] = React.useState(false); const [expandedRow, setExpandedRow] = React.useState(null); const [mic, setMic] = React.useState(loadStoredMic); + const [panelHidden, setPanelHidden] = React.useState(loadStoredPanelHidden); const [analyser, setAnalyser] = React.useState(null); const [resetConfirming, setResetConfirming] = React.useState(false); const [resetting, setResetting] = React.useState(false); @@ -107,6 +117,12 @@ function App() { React.useEffect(() => { listeningRef.current = listening; }, [listening]); + + React.useEffect(() => { + try { + localStorage.setItem(PANEL_HIDDEN_STORAGE_KEY, panelHidden ? "1" : "0"); + } catch {} + }, [panelHidden]); const [isFullscreen, setIsFullscreen] = React.useState(false); React.useEffect(() => { @@ -649,10 +665,31 @@ function App() { return React.createElement( "main", - { className: `shell mode-${mode}`, ref: shellRef }, + { + className: `shell mode-${mode}${panelHidden ? " panel-hidden" : ""}`, + ref: shellRef, + }, React.createElement( "section", { className: "canvas-wrap", ref: canvasWrapRef }, + React.createElement( + "button", + { + type: "button", + className: "panel-toggle", + onClick: () => setPanelHidden((v) => !v), + title: panelHidden ? "Show settings panel" : "Hide settings panel", + "aria-label": panelHidden + ? "Show settings panel" + : "Hide settings panel", + "aria-expanded": !panelHidden, + }, + React.createElement( + "span", + { className: "panel-toggle-icon", "aria-hidden": "true" }, + panelHidden ? "‹" : "›", + ), + ), React.createElement(Excalidraw, { excalidrawAPI: setApi, initialData: { diff --git a/public/style.css b/public/style.css index 9a3160a..07bcb6f 100644 --- a/public/style.css +++ b/public/style.css @@ -22,6 +22,12 @@ body { grid-template-columns: minmax(0, 1fr) 360px; height: 100vh; width: 100vw; + overflow: hidden; + transition: grid-template-columns 240ms ease; +} + +.shell.panel-hidden { + grid-template-columns: minmax(0, 1fr) 0; } .canvas-wrap { @@ -31,6 +37,38 @@ body { overflow: hidden; } +.panel-toggle { + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + z-index: 50; + width: 18px; + height: 56px; + padding: 0; + border-radius: 8px 0 0 8px; + background: rgba(255, 253, 248, 0.92); + color: #6d675e; + border: 1px solid #dedbd2; + border-right: none; + font-weight: 600; + font-size: 14px; + line-height: 1; + box-shadow: -2px 2px 8px rgba(30, 30, 30, 0.06); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); + transition: background 160ms ease, color 160ms ease; +} + +.panel-toggle:hover { + background: #fffdf8; + color: #1e1e1e; +} + +.panel-toggle-icon { + display: inline-block; +} + .stage-overlay { position: absolute; left: 0; @@ -96,6 +134,15 @@ body { padding: 22px; overflow: auto; position: relative; + min-width: 0; + min-height: 0; + transition: opacity 200ms ease; +} + +.shell.panel-hidden .panel { + opacity: 0; + pointer-events: none; + overflow: hidden; } .brand h1 { @@ -646,13 +693,40 @@ button:disabled { grid-template-rows: minmax(0, 1fr) auto; } + .shell.panel-hidden { + grid-template-columns: 1fr; + grid-template-rows: minmax(0, 1fr) 0; + } + .canvas-wrap { height: 62vh; } + .shell.panel-hidden .canvas-wrap { + height: 100vh; + } + .panel { height: 38vh; border-left: 0; border-top: 1px solid #dedbd2; } + + .panel-toggle { + top: auto; + right: auto; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 56px; + height: 18px; + border-radius: 8px 8px 0 0; + border: 1px solid #dedbd2; + border-bottom: none; + box-shadow: 0 -2px 8px rgba(30, 30, 30, 0.06); + } + + .panel-toggle .panel-toggle-icon { + transform: rotate(90deg); + } }