ux v1.40.1: room click removed — link icon on the room card instead

- rooms inert in View (default cursor); mdi:open-in-new after the room
  name (View, rooms with an area) navigates to the HA area
- smoke_room_link.mjs (7 checks); TESTING/CHANGELOG/UX-MODES same-commit
This commit is contained in:
Matysh
2026-07-23 17:46:11 +03:00
parent df9e158efb
commit 4b4df4b3a2
14 changed files with 141 additions and 33 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ PLANS_DIR = "houseplan/plans" # relative to the HA configuration directory
FILES_URL = "/houseplan_files/files"
FILES_DIR = "houseplan/files"
CONF_ADMIN_ONLY = "admin_only"
VERSION = "1.40.0"
VERSION = "1.40.1"
DEFAULT_CONFIG: dict = {
"spaces": [],
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -16,5 +16,5 @@
"issue_tracker": "https://github.com/Matysh/houseplan-card/issues",
"requirements": [],
"single_config_entry": true,
"version": "1.40.0"
"version": "1.40.1"
}
+38
View File
@@ -0,0 +1,38 @@
import { launch } from './serve.mjs';
const { page, browser } = await launch();
const res = await page.evaluate(async () => {
const out = {};
const c = window.__card;
const sr = () => c.shadowRoot || c.renderRoot;
// включить имена комнат
c._serverCfg = { ...c._serverCfg, spaces: c._serverCfg.spaces.map((s) => s.id !== c._space ? s : ({
...s, settings: { ...(s.settings || {}), show_names: true } })) };
c._setMode('view'); c.requestUpdate(); await c.updateComplete;
await new Promise((r) => setTimeout(r, 250));
// 1) комната не кликабельна: cursor default, обработчика клика нет
const room = sr().querySelector('.room');
out.roomCursor = getComputedStyle(room).cursor === 'default';
// 2) значок ссылки у комнат с зоной, кликабелен, ведёт в зону
const links = sr().querySelectorAll('.rlgo');
out.linksShown = links.length > 0;
const withArea = c._spaceModel().rooms.filter((r) => r.name && r.area).length;
out.linkPerArearoom = links.length === withArea;
const icon = links[0];
out.linkCursor = getComputedStyle(icon).cursor === 'pointer';
out.linkClickable = getComputedStyle(icon).pointerEvents === 'auto';
// навигация: перехват history
let navTo = null;
const orig = history.pushState.bind(history);
history.pushState = (a, b, url) => { navTo = url; };
icon.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
await c.updateComplete;
history.pushState = orig;
out.navigates = typeof navTo === 'string' && navTo.includes('/config/areas/area/');
// 3) комнаты без зоны — без значка (проверено соотношением выше); в разметке значков нет
c._setMode('plan'); await c.updateComplete;
out.noneInPlan = sr().querySelectorAll('.rlgo').length === 0;
c._setMode('view'); await c.updateComplete;
return out;
});
console.log(JSON.stringify(res, null, 1));
await browser.close();
File diff suppressed because one or more lines are too long
+21 -7
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## v1.40.1 — 2026-07-23
- Rooms are no longer clickable in View (default cursor, empty space does
nothing). Instead the room card shows a small **open-in-new icon** after
the name — clicking it opens the HA area. Rooms without an area (and all
editors) have no icon.
## v1.40.0 — 2026-07-23 (smart guides)
- **Alignment helper in every editor**: while drawing an outline, a cut or a
decor shape, and while dragging icons, room cards or decor, thin dashed
+4
View File
@@ -140,6 +140,10 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
(explicit ripple color still wins); off/white lights unchanged [auto]
- [ ] Alarm pulse (v1.27.0): leak/smoke/gas/CO/siren in 'on' pulse a red ring over any
display mode; clears on 'off'; unavailable never alarms [auto]; reduced-motion static
- [ ] Room link icon (v1.40.1): clicking empty room space in View does
nothing (default cursor); an open-in-new icon after the room name (rooms
with an HA area, View only) navigates to the area; no icon in editors or
on area-less rooms [auto]
- [ ] Smart guides (v1.40.0): while drawing (outline, cut, decor shapes) or
dragging (icons, room cards, decor) dashed accent guides appear from the
nearest object sharing the X and/or Y (max two, with a dot at the
+1 -1
View File
@@ -35,7 +35,7 @@ Allowed: pan/zoom (wheel, pinch, buttons), switching spaces, device tap
(info / more-info / toggle per settings), long-press → info card, opening tap →
door/lock info card (with an explicit Unlock/Lock button when a lock is bound —
the only way to operate a lock from the card; plan-icon taps never toggle locks),
room tap → HA area, hover tooltips (name, temperature, signal).
room-card link icon → HA area (room taps do nothing since v1.40.1), hover tooltips (name, temperature, signal).
Removed from this mode (they move, not die):
- icon dragging ("drag anywhere", v1.9 — consciously reversed),
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "houseplan-card",
"version": "1.40.0",
"version": "1.40.1",
"description": "Interactive house plan Lovelace card for Home Assistant",
"license": "MIT",
"type": "module",
+10 -5
View File
@@ -32,7 +32,7 @@ import './space-card';
import { cardStyles } from './styles';
import { langOf, t, type I18nKey } from './i18n';
const CARD_VERSION = '1.40.0';
const CARD_VERSION = '1.40.1';
const LS_KEY = 'houseplan_card_layout_v1';
const LS_CFG = 'houseplan_card_cfg_v1'; // cache of the server config+layout for instant rendering
const LS_ZOOM = 'houseplan_card_zoom_v1';
@@ -3223,15 +3223,15 @@ class HouseplanCard extends LitElement {
const shape = holes.length && myPoly
? svg`<path class="${cls}" style="${style}" fill-rule="evenodd"
d="${[myPoly, ...holes].map(pathD).join(' ')}"
@click=${() => this._clickRoom(r)} @mousemove=${tip}
@mousemove=${tip}
@mouseleave=${() => (this._tip = null)}></path>`
: r.poly
? svg`<polygon class="${cls}" style="${style}" points="${r.poly.map((p) => p.join(',')).join(' ')}"
@click=${() => this._clickRoom(r)} @mousemove=${tip}
@mousemove=${tip}
@mouseleave=${() => (this._tip = null)}></polygon>`
: svg`<rect class="${cls}" style="${style}"
x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" rx="${Math.min(r.w!, r.h!) * 0.03}"
@click=${() => this._clickRoom(r)} @mousemove=${tip}
@mousemove=${tip}
@mouseleave=${() => (this._tip = null)}></rect>`;
const trimmed = openCuts.length && myPoly
? outlineWithout(myPoly, openCuts, this._gridPitch * 0.02)
@@ -3510,7 +3510,12 @@ class HouseplanCard extends LitElement {
@pointermove=${(e: PointerEvent) => this._labelMove(e, r, space.id)}
@pointerup=${() => this._labelUp(r)}
@pointercancel=${() => this._labelUp(r)}
><span class="rlname">${r.name}</span>
><span class="rlname">${r.name}${!this._markup && r.area
? html`<ha-icon class="rlgo" icon="mdi:open-in-new"
title=${this._t('room.open_area')}
@click=${(e: Event) => { e.stopPropagation(); this._clickRoom(r); }}
@pointerdown=${(e: Event) => e.stopPropagation()}></ha-icon>`
: nothing}</span>
${rows.length ? html`<span class="rlmetrics">${rows}</span>` : nothing}
${this._mode === 'plan'
? ['tl', 'tr', 'bl', 'br'].map(
+2 -1
View File
@@ -300,5 +300,6 @@
"marker.from_ha_option": "Pick from the HA list",
"marker.show_entities": "Show entities",
"marker.show_entities_tip": "Adds not only devices to the list, but all their entities too",
"marker.pick_ph": "Choose a device…"
"marker.pick_ph": "Choose a device…",
"room.open_area": "Open the HA area"
}
+2 -1
View File
@@ -300,5 +300,6 @@
"marker.from_ha_option": "Выбрать из списка HA",
"marker.show_entities": "Отображать сущности",
"marker.show_entities_tip": "Добавляет в список не только устройства, но и все их сущности",
"marker.pick_ph": "Выберите устройство…"
"marker.pick_ph": "Выберите устройство…",
"room.open_area": "Открыть зону в HA"
}
+12 -1
View File
@@ -189,7 +189,7 @@ export const cardStyles = css`
}
.room {
transition: 0.12s;
cursor: pointer;
cursor: default; /* v1.40.1: rooms are not clickable — the label's link icon is */
}
.room.overlay {
fill: transparent;
@@ -377,6 +377,17 @@ export const cardStyles = css`
gap: 0.15em;
text-align: center;
}
.rlname { display: inline-flex; align-items: center; gap: 0.25em; }
.rlgo {
--mdc-icon-size: 0.85em;
display: inline-flex;
opacity: 0.55;
}
.stage.mode-view .rlgo {
pointer-events: auto;
cursor: pointer;
}
.stage.mode-view .rlgo:hover { opacity: 1; }
.roomlabel .rlmetrics {
display: flex;
align-items: center;