Skip to content

feat: pop-up / modal overlays — fit more controls onto small wall panels - #88

Merged
jeremiaa merged 3 commits into
jeremiaa:mainfrom
deespater:popups_support
Aug 30, 2026
Merged

feat: pop-up / modal overlays — fit more controls onto small wall panels#88
jeremiaa merged 3 commits into
jeremiaa:mainfrom
deespater:popups_support

Conversation

@deespater

Copy link
Copy Markdown
Contributor

Why

Small wall panels are wonderful but cramped. On a Sonoff NSPanel Pro (480×480)
there just isn't room to lay out every scene, light, cover and sensor at once — a
board that fits also has to stay readable from across the room. You end up
choosing between a clean glanceable display and having your controls one tap away.

Overlays solve that. A Buttons widget can sit hidden on top of the view and
pop up on demand as a modal panel, so the base screen stays calm — clock,
weather, the two things you actually want to see — while a whole grid of controls
is one tap away and gone again the moment you're done. On a 480×480 panel this
effectively multiplies the usable surface: several full "pages" of buttons living
on one view, each summoned when needed.

This already almost worked with the existing stack/hide features — three small
gaps were in the way. This PR closes them.

What this adds

  1. Hidden widgets are click-through. A hidden widget dropped pointer-events
    on its inner content, but the outer react-grid-item wrapper covering the cell
    kept pointer-events: auto and swallowed every tap — so a hidden panel blocked
    whatever sat beneath it. Now the hidden state reaches the wrapper too, and taps
    fall straight through to the widget below. (This is what makes an overlay you
    can leave "parked" on top of the view viable at all.)

  2. A button can hide its own widget after acting. New per-button option
    Hide this widget after action (optional delay; works on tap and long press).
    The button runs its action, then hides the whole widget it lives in — so a
    control inside an overlay closes the overlay as it fires.

  3. Tap outside the buttons to close. New Buttons-widget option in
    Layout → Visibility. A tap on the widget's area that doesn't land on a button
    dismisses the overlay — the familiar "tap the backdrop" of a modal, and the
    escape hatch when it was opened by mistake.

Example: two control drawers on a 480×480 panel

magic_frame_overlay.mp4

A Sonoff NSPanel Pro (480×480): weather on top, two triggers — Gate and
Vacuum — below. Each opens a hidden Buttons overlay (Gate → Open / Hold;
Vacuum → All rooms / Living room / Kitchen / Bedroom). Every option fires
its Home Assistant action and closes the drawer in the same tap. Six controls on a
panel that shows two at rest.

Implementation notes

  • The live view passes each widget its own layout id; the Buttons widget uses it
    to target itself through the existing WIDGET_ACTION → hide path — no new
    view-side plumbing.
  • Buttons carry a data-mf-button marker so the backdrop-tap handler can tell a
    button tap from a background tap.
  • New config (selfHide / selfHideDelay + longPress* variants,
    hideOnOutsideTap) rides the Buttons widget's existing passthrough schema, so
    it survives save / duplicate / rename like every other slot field. No schema
    migration.

Docs

wiki/stacking-and-visibility.md gains a Pop-ups and modal overlays section
(building, opening, and both ways of closing), and the "hidden" explanation now
notes that taps pass through.

Compatibility

No behaviour change for existing layouts: all new options default off, and the
click-through fix only affects widgets that are already hidden (which were already
meant not to respond to taps).

Notes

  • I've tried to follow the existing code style and conventions throughout.
  • I kept the new UI strings bilingual through the i18n system (German source +
    English in en.ts) — the German is AI-assisted, so please double-check that
    those translations read naturally.

A hidden widget is now fully click-through: taps pass straight through it
to whatever sits underneath. That makes real pop-ups possible — lay a
full-screen widget over a button, start it hidden, and the button beneath
stays tappable to bring the panel up on demand.

Previously the outer react-grid-item wrapper kept pointer-events: auto and
swallowed the tap, so a covered button could never reveal the panel.

Also documents the pop-up pattern in the stacking & visibility wiki.
… after acting

A button slot can now hide its own widget once its action has run, with an
optional delay. That turns a Buttons widget into a modal overlay: laid over the
view and hidden on load, opened by a show/toggle from elsewhere, and closed by a
button inside it that acts and then dismisses the whole overlay.

The view hands each widget its own id, so the button targets itself through the
existing WIDGET_ACTION → hide path — no new plumbing on the view side. The config
rides the button's passthrough schema (selfHide / selfHideDelay and the longPress*
variants), so it survives save, duplicate and rename like every other slot field.
Available for tap and long press independently.

Docs: the stacking & visibility wiki now covers pop-up / modal overlays.
A Buttons widget used as a modal overlay can now be closed without pressing any
button: a new "Tap outside the buttons to close" switch (Layout → Visibility)
hides the whole widget when a tap lands on it but not on a button — the escape
hatch for an overlay opened by mistake.

A tap counts as "on a button" when it hits an element marked data-mf-button;
anything else on the widget's own area dismisses it through the existing
WIDGET_ACTION → hide path, targeting itself. The config (hideOnOutsideTap) rides
the button's passthrough schema, and is declared on the editor's widget-config
type so the Layout tab can read it.

Docs: the stacking & visibility wiki now describes both ways to close an overlay.
@deespater

Copy link
Copy Markdown
Contributor Author

Attached preconfigured view for testing

magicframe-backup-2026-08-22.json

@jeremiaa
jeremiaa merged commit 8bedcec into jeremiaa:main Aug 30, 2026
@jeremiaa

Copy link
Copy Markdown
Owner

merged as-is, out in v1.5.3.

the click-through fix is the quiet star here - a hidden widget swallowing taps was a real bug that bit anyone stacking widgets, pop-ups or not. and the self-hide path riding the existing WIDGET_ACTION plumbing instead of new view-side state is exactly how it should be done.

checked your german strings - all four read naturally, nothing to fix. "buttons" is what the widget is called in the german ui anyway, so that worry was unfounded.

thanks - video, docs, compatibility notes, the lot. contributions like this are easy to merge.

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.

2 participants