From 1a47f217ca91417beeac8033ddc8975c270eb85e Mon Sep 17 00:00:00 2001 From: sidgaikwad Date: Fri, 4 Sep 2026 12:19:50 +0530 Subject: [PATCH 1/2] fix(demo): make the page responsive and follow the theme control Two problems, both in the demo's own chrome. styles.css had no @media query at all. The sidebar was a hard 240px that could not shrink, so on a 375px phone the editor got ~135px and the editor's own Save/Cancel controls were off-screen entirely. The sidebar now overlays the editor below 768px with a dismissable backdrop, and App.tsx starts it closed at those widths via matchMedia. The Light/Dark control drove options.theme but the page around it was hardcoded: html/body light, topbar and sidebar dark, preview card white. Switching to dark produced a dark editor in light chrome, and switching to light still left a permanently dark sidebar. All chrome colours now come from CSS custom properties keyed off a data-theme attribute that App.tsx sets from the same theme state the editor gets. Verified at 375x812 and 1280x800. --- demo/src/App.tsx | 26 +++++++- demo/src/styles.css | 146 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 140 insertions(+), 32 deletions(-) diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 527f79c..e705ebc 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import ImageEditor, { ImageEditorRef, @@ -16,6 +16,10 @@ const SAMPLE_IMAGES = [ const MAX_UPLOAD_BYTES = 20 * 1024 * 1024; +// Matches the @media breakpoint in styles.css, where the sidebar becomes an +// overlay. Starting it open at these widths hides the editor behind it. +const WIDE_VIEWPORT = '(min-width: 768px)'; + const allToolsEnabled = () => Object.fromEntries(TOOL_NAMES.map((tool) => [tool, true])) as Record< ToolName, @@ -30,10 +34,19 @@ export default function App() { const [locale, setLocale] = useState('en'); const [tools, setTools] = useState>(allToolsEnabled); - const [sidebarOpen, setSidebarOpen] = useState(true); + const [sidebarOpen, setSidebarOpen] = useState( + () => window.matchMedia(WIDE_VIEWPORT).matches + ); const [saved, setSaved] = useState(null); const [status, setStatus] = useState('Loading editor…'); + // Drive the page chrome off the same theme the editor gets, so the + // control demonstrates the real thing rather than a dark shell that never + // changes. + useEffect(() => { + document.documentElement.dataset.theme = theme; + }, [theme]); + // Invalidates in-flight file reads so a slow read can never overwrite a // newer image choice (upload or sample) after the fact. const readTokenRef = useRef(0); @@ -109,6 +122,15 @@ export default function App() {
+ {sidebarOpen && ( +