Skip to content

fix(demo): make the page responsive and follow the theme control - #59

Merged
lucasbesen merged 2 commits into
unlayer:mainfrom
sidgaikwad:fix/demo-responsive-and-theme
Sep 8, 2026
Merged

fix(demo): make the page responsive and follow the theme control#59
lucasbesen merged 2 commits into
unlayer:mainfrom
sidgaikwad:fix/demo-responsive-and-theme

Conversation

@sidgaikwad

Copy link
Copy Markdown
Contributor

Fixes #39.

1. The demo was not responsive

styles.css contained no @media query at all. .sidebar was a hard width: 240px; flex-shrink: 0, so on a 375px phone the editor got ~135px — and because useState(true) opened the sidebar by default, the first paint on mobile was the broken one.

Before (375×812): sidebar occupied ~64% of the viewport, the editor was a sliver, and the editor's own Save/Cancel controls were off-screen entirely.

After (same viewport): sidebar starts closed, editor gets the full 375px, tool rail and Save/Cancel all reachable.

Below 768px the sidebar now overlays the editor (position: absolute, min(280px, 85vw)) with a dismissable backdrop, rather than squeezing it. App.tsx starts it closed at those widths via matchMedia, keyed to the same breakpoint.

Measured in the running demo:

375×812 1280×800
sidebar open by default false true
sidebar position absolute (overlay) static (in flow)
editor width, sidebar closed 375
editor width, sidebar open 375 (unchanged — overlaid) 1040
backdrop shown display: none

Desktop layout is unchanged.

2. The theme control didn't theme the page

The Light/Dark selector drove options.theme, but the surrounding page was hardcoded — html/body light, .topbar and .sidebar dark, .preview white. Switching to dark gave a dark editor inside light chrome; switching to light still left a permanently dark sidebar. Since the demo is what people look at to judge whether theming works, it undersold it.

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 receives:

themeAttr:  light  ->  dark
body bg:    rgb(255,255,255)  ->  rgb(15,17,21)
topbar bg:  follows to rgb(22,24,29)

Verification

Ran against the live demo at both viewports; tsc --noEmit and vite build clean; Prettier clean.

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.
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

@sidgaikwad is attempting to deploy a commit to the Unlayer Team on Vercel.

A member of the Team first needs to authorize it.

@ivoIturrieta

Copy link
Copy Markdown
Collaborator

In landscape mobile view, the saved preview grows taller than the viewport and its Close/Download controls disappear above the screen. Please constrain the preview height and keep its header accessible.

The preview panel is anchored to the bottom of the screen with no height
bound, so an image taller than the viewport grew upward and took the
header with it. In landscape on a phone (667x375) the panel was 477px
tall and its top sat at -110px, putting Download and Close off-screen with
no way to dismiss it.

Bound the panel to the viewport, make it a flex column, pin the header so
it never shrinks, and let the image take the remaining space with
object-fit: contain so it scales instead of overflowing.

dvh with a vh fallback, so mobile browser chrome is accounted for.

Verified at 667x375, 667x300, 375x812 and 1280x800.
@sidgaikwad

Copy link
Copy Markdown
Contributor Author

Good catch — reproduced and fixed in 1110f77.

Reproduced at 667×375 (iPhone SE landscape, which is under the 768px breakpoint so the full-width panel rules apply):

previewHeight: 477   viewport height: 375
previewTop:   -110   headerTop: -97   headerFullyVisible: false

The panel is anchored bottom: 8px with no height bound, so an image taller than the viewport grows upward — taking Download and Close off the top with no way to dismiss it.

Fix: bound the panel to the viewport and let the image absorb the difference.

  • .previewmax-height: calc(100dvh - 16px) (with a 100vh fallback first, so older browsers still get a bound), plus display: flex; flex-direction: column
  • .preview-headerflex: none, so Close and Download can never be squeezed out
  • .preview imgflex: 1 1 auto; min-height: 0; object-fit: contain, so it scales down instead of overflowing while keeping its aspect ratio

dvh specifically because mobile browser chrome otherwise makes 100vh taller than the visible area — the exact situation where this bites.

Verified across four viewports, measuring the real geometry rather than eyeballing:

viewport panel top panel height fits header visible
667×375 (the reported case) 8 359
667×300 (extreme short) 8 284
375×812 (portrait) 525 279
1280×800 (desktop) 253

Close and Download were individually confirmed inside the viewport in the landscape cases.

On desktop the image still measures an aspect ratio of exactly 1.500 — the source ratio — so nothing is letterboxed or distorted when there is room. It only letterboxes when the height bound actually engages, which is the intended trade.

CSS-only change, +19 lines; demo typecheck, build and Prettier all clean.

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
react-image-editor Ready Ready Preview Sep 8, 2026 7:14pm UTC

Request Review

@lucasbesen
lucasbesen merged commit a708faf into unlayer:main Sep 8, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

demo: not responsive on mobile, and the page chrome ignores the theme toggle

3 participants