mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
244 lines
12 KiB
Markdown
244 lines
12 KiB
Markdown
# Touch support policy
|
||
|
||
Approved by the owner on **2026-08-08**. This document is the source of truth
|
||
for product scope, implementation trade-offs, documentation and release
|
||
acceptance on touch devices.
|
||
|
||
## Product contract
|
||
|
||
House Plan is a **touch-first product in View and kiosk**, but its editors are
|
||
**desktop-first administration tools**.
|
||
|
||
This contract applies equally to the primary `/houseplan` sidebar panel and to
|
||
optional dashboard cards. The panel menu button remains available on every
|
||
width with a 44 × 44 px target; Home Assistant kiosk state does not silently
|
||
enable House Plan's separate card kiosk mode.
|
||
|
||
| Surface | Desktop browser with mouse/keyboard | Touch/coarse-pointer device |
|
||
|---|---|---|
|
||
| View | Fully supported | **Fully supported; must be convenient and reliable** |
|
||
| Sidebar panel shell and drawer access | Fully supported | **Fully supported** |
|
||
| Kiosk | Supported | **Primary supported environment** |
|
||
| View dialogs and safe device actions | Fully supported | **Fully supported** |
|
||
| Plan editor | **Reference editing environment** | Best effort; partial, awkward or missing operations are allowed |
|
||
| Device editor | **Reference editing environment** | Best effort |
|
||
| Background editor | **Reference editing environment** | Best effort |
|
||
|
||
Users must be told to create and maintain plans in a desktop browser. A tablet
|
||
or phone may expose the editor tabs, and individual operations may work, but
|
||
editor parity with desktop is not promised.
|
||
|
||
## What “fully supported View” means
|
||
|
||
On phones, tablets, wall panels and HA Companion apps, the ordinary View must:
|
||
|
||
- render the plan and current states correctly;
|
||
- on a phone (≤ 480 px) keep the header to one row of at most 56 px — space
|
||
tabs, zoom and one gear whose menu holds every other header action, each
|
||
item a 44 px target (#616);
|
||
- support convenient pan, pinch zoom and space switching;
|
||
- treat a linked stair as a floor-navigation target only after a clean tap;
|
||
pan, pinch, long press, swipe and cancellation tails must stay inert;
|
||
- reserve floor switching for an inward horizontal gesture that starts in the
|
||
48 CSS px strip of an edge with a neighbouring space; a drag elsewhere and
|
||
an unavailable edge must pan the plan;
|
||
- fit the whole plan after two clean taps on background, room fill or a passive
|
||
room label. A single room tap fits only after the 350 ms second-tap window,
|
||
with no intermediate camera motion; keyboard room activation stays immediate;
|
||
- provide a touch path for essential information that desktop exposes through
|
||
hover;
|
||
- open and close View dialogs without clipping their essential content or
|
||
actions;
|
||
- perform supported device actions safely and predictably;
|
||
- remain usable after backgrounding, resize, orientation changes and warm
|
||
remount;
|
||
- preserve kiosk gestures and prevent accidental editor interactions.
|
||
|
||
During every intermediate pan or pinch frame, walls, floors, room fills,
|
||
hatching, lighting and markers must remain continuously painted. The scene SVGs
|
||
stay on one promoted compositor path from the first movement until the terminal
|
||
frame; a budgeted redraw or an unrelated Home Assistant state update must never
|
||
flash white, become transparent or momentarily expose the stage background.
|
||
This contract applies equally to browsers and HA Companion WebViews.
|
||
`smoke_daycycle_layer_budget` additionally proves that the first camera move on
|
||
a 1 cm/grid-point day-cycle plan switches its filtered paper silhouette to the
|
||
screen-bounded fallback, leaves no implicit overlap-promoted plan layer, and
|
||
samples the compositor-presented pinch frames. A fresh idle frame still matches
|
||
the accepted `day-cycle-*` goldens; the real-device beta pass remains the field
|
||
acceptance for WebView-specific tile loss (#582).
|
||
|
||
Once a second touch joins an input sequence, that whole sequence is navigation
|
||
only, whichever contact began on a device marker. Marker tap, long press,
|
||
confirmation, service calls and touch-generated context menu stay blocked
|
||
through every release, cancellation or lost capture and through any delayed
|
||
browser compatibility activation. A new pointer down after the old contacts
|
||
have ended starts a deliberate input sequence immediately; users never have to
|
||
wait before the next single tap or long press. A later real mouse pointerdown or
|
||
keyboard context-menu key is likewise fresh intent and preserves the desktop
|
||
context-menu contract.
|
||
|
||
The summary panel, both halves of its control, and its simple settings form are
|
||
supported View surfaces: each control has a 44 × 44 px or larger target, panel
|
||
scrolling owns its touch gesture instead of zooming the plan, and the settings
|
||
dialog retains reachable content and actions on a narrow viewport. The panel
|
||
may hide because its measured House Plan stage is too small; this is responsive
|
||
safety, not loss of the user's per-card show preference.
|
||
|
||
A touch-only failure in View is a product defect, not an accepted limitation of
|
||
the editor policy.
|
||
|
||
## Pointer modality and hover ownership
|
||
|
||
Hover is instance-local and follows the latest real pointer input. It is
|
||
enabled only after a mouse event when the browser also reports fine,
|
||
hover-capable hardware. Touch and pen input immediately clear transient room
|
||
and device hover, including tooltips; browser-generated compatibility mouse
|
||
events must not restore it. A later real mouse move on a hybrid device restores
|
||
desktop hover without a reload. Space/mode changes, page hiding and remounts
|
||
also discard transient hover. Keyboard focus and explicit click/tap surfaces
|
||
remain independent of this visual hover gate.
|
||
|
||
In View, a device reached with visible keyboard focus opens the same anchored
|
||
device tooltip as mouse hover. It follows focus from marker to marker and closes
|
||
on blur, space/mode changes, page hiding or remount. Touch and pen still never
|
||
open it and immediately clear it on hybrid hardware.
|
||
|
||
When device markers are packed more tightly than their 44 × 44 px minimum
|
||
targets, the marker visibly painted under the pointer owns that point. Only an
|
||
otherwise empty overlap of invisible target floors is resolved by the nearest
|
||
marker core. This same screen-space owner is held for the complete pointer
|
||
sequence, so hover, tap, long press, context menu and Devices-editor drag cannot
|
||
switch to a neighbour between press and release. Saved marker coordinates and
|
||
the visible layout are not moved to manufacture separation.
|
||
|
||
The default-on **Show the room information window on hover** preference applies
|
||
only after this pointer-modality gate has enabled real mouse hover. Turning it
|
||
off leaves the room highlight and device tooltips unchanged; it does not add a
|
||
touch or pen replacement for the room window.
|
||
|
||
## What “best-effort editors” means
|
||
|
||
On a coarse-pointer or no-hover device, an editor operation may:
|
||
|
||
- have less convenient hit targets or gestures;
|
||
- require a workflow that is practical only with a mouse and keyboard;
|
||
- omit a desktop-only shortcut or precision interaction;
|
||
- be hidden or disabled when no safe touch interaction exists;
|
||
- have a documented layout or usability limitation;
|
||
- be intentionally deferred when touch parity is disproportionately expensive.
|
||
|
||
This is an explicit scope decision. New editor features are designed and
|
||
accepted against the desktop reference environment first. Touch editor support
|
||
is added when it is cheap, robust and does not complicate the desktop model.
|
||
|
||
## Safety floor that still applies to touch editors
|
||
|
||
“Best effort” never permits:
|
||
|
||
- data corruption or silent loss of saved plan data;
|
||
- an unsafe Home Assistant service call;
|
||
- bypassing permissions or destructive confirmation;
|
||
- leaving the card permanently stuck outside View;
|
||
- an editor exception that breaks ordinary View or kiosk;
|
||
- saving unintended geometry merely because a pinch, pointer cancellation or
|
||
second touch was misread as a click.
|
||
|
||
If a desktop interaction cannot be translated safely to touch, prefer a clear
|
||
disabled/absent action and a desktop recommendation over a deceptively working
|
||
control.
|
||
|
||
The shared editor context tray follows this safety floor: its visible surface
|
||
owns its pointer events, narrow action rows scroll internally, and a press used
|
||
only to dismiss an explicit group/palette is consumed instead of falling
|
||
through to the plan. Pinch/pan outside the tray remains scene-owned. This is a
|
||
safety guarantee, not a promise of full touch parity for editor precision work.
|
||
|
||
The Plan editor's Walls chain follows the same floor. One clean tap may append
|
||
one segment; pan, pinch, a second pointer, `pointercancel` and a suppressed
|
||
synthetic click never append, finish or convert the chain. An open chain
|
||
finishes as ordinary walls only through an explicit finish action: a
|
||
tool/editor/floor change, `Esc`, the tray's Reset, route/hash departure or
|
||
rejecting every closed face (docs/WALL-THICKNESS.md §11, Finishing a chain).
|
||
Junction hover is best effort on coarse pointers; click resolution remains
|
||
authoritative.
|
||
With no active chain, a clean tap inside an exact bounded wall face may offer a
|
||
room without drawing another segment; the tap is resolved again at commit time.
|
||
Desktop `Shift` bypasses that offer and constrains drawing to an exact 45° ray;
|
||
touch has no separate modifier gesture. A pan, pinch, cancellation or second
|
||
pointer never accepts a face, applies a small-gap repair or creates a room.
|
||
|
||
Stair placement and transforms remain best-effort editor interactions on
|
||
touch, but the safety floor is strict: cancellation and navigation gestures do
|
||
not create, move, save or follow a stair. A long press in View does not activate
|
||
its target floor, and the next deliberate tap is re-armed immediately.
|
||
|
||
During a View/editor visual transition the moving stage is inert while the
|
||
header tabs remain available. A pinch, cancelled pointer or synthetic click
|
||
cannot operate stale geometry; leaving the editor is always a single safe
|
||
action. The decorative smoothness of the editor chrome remains best effort on
|
||
coarse-pointer devices, while the correct final View frame is release-blocking.
|
||
|
||
## Deliberate degradation rule
|
||
|
||
When an editor change would be expensive to implement correctly for touch, the
|
||
change may ship as desktop-only or with reduced touch behaviour if all of the
|
||
following are true:
|
||
|
||
1. View and kiosk are unaffected.
|
||
2. Plan data and device actions remain safe.
|
||
3. Desktop editing is complete and tested.
|
||
4. The touch limitation is deliberate, described in the user-facing
|
||
limitations and, where useful, next to the affected workflow.
|
||
5. Existing automated touch-editor coverage is explicitly updated or
|
||
reclassified in the same change; it is not silently ignored.
|
||
6. The release notes mention the limitation when it is material to users.
|
||
|
||
An accidental regression is not made acceptable merely by calling it
|
||
best-effort after discovery.
|
||
|
||
## Input classification
|
||
|
||
Do not classify support from screen width alone.
|
||
|
||
- `pointer: coarse`, no hover, touch pointer events and mobile/Companion
|
||
environments are touch scenarios.
|
||
- A narrow desktop window with a fine pointer remains a desktop editing
|
||
scenario.
|
||
- Hybrid laptops must keep both View paths usable. Their editors may use the
|
||
desktop path when a fine pointer and keyboard are actually available.
|
||
- Stylus editing is best effort unless a specific feature explicitly promises
|
||
it.
|
||
|
||
## Testing and release gates
|
||
|
||
Release-blocking guarantees:
|
||
|
||
1. View on desktop.
|
||
2. View and kiosk on representative touch/mobile environments.
|
||
3. All editors on desktop with mouse/keyboard.
|
||
4. The touch-editor safety floor above.
|
||
|
||
Touch-editor feature parity is not a general release gate. Targeted tests may
|
||
still protect individual touch workflows that the product intentionally keeps;
|
||
removing such a guarantee requires an explicit scope/documentation change, not
|
||
just deletion of the failing test.
|
||
|
||
Stable-release manual coverage must include at least one phone/Companion View
|
||
and one wall-tablet/kiosk View. Editor smoke coverage on touch is scoped to
|
||
safe entry/exit, no accidental mutation during multi-touch, and any separately
|
||
promised workflow.
|
||
|
||
## Documentation rule
|
||
|
||
Every user-facing description of the editors must recommend desktop for plan
|
||
creation and maintenance. Documentation must not imply full touch-editor
|
||
support merely because the tabs are visible on a tablet. New editor feature
|
||
specifications and code reviews must state one of:
|
||
|
||
- `Touch editor: supported`;
|
||
- `Touch editor: best effort / intentionally degraded`;
|
||
- `Touch editor: not exposed`.
|
||
|
||
If touch work is omitted because of cost, that is an accepted product decision
|
||
only after it is written down.
|