feat(dialogs): финал #600 — мёртвые стили, парные кадры, документация, потолки

Завершение четырёх серий по референсу docs/design/600-settings-dialogs/:

- из eager-листов dialogs.styles.ts и chrome.styles.ts сняты стили прежней
  разметки диалогов (.bindsel/.bindharow/.entcheck, .ctrlchip*, .markerhelp*,
  .helpfieldlabel, .markerradios, .markerlightdisabled, .markerbadgetechnical,
  .markerglowvalue, .fileupload, .descin, .pdfedit/.pdftag, .gsrow,
  .ripple-*row, .radaradditional, .togglehint, футеры marker/room) — 5,8 КБ
  исходника; с разметки сняты уже пустые классы;
- «Additional actions» карточки Details — подзаголовок и строка действий
  набора, без раскрывашки (radar-section.ts, только additional-placement);
- Q3 уточнён по кадру: hp-device-preview стоит без обёртки — у него свой
  заголовок «Display preview · Now», второй над ним удваивался; пустое
  состояние — блок на тинте;
- §6.1: «?» у комнаты стоит у поля Home Assistant area, а не у заголовка
  Basics; подписи сегмента заливки — None · Zigbee · Lights · Temperature ·
  Custom (два коротких ключа room.fill_seg_*), источники — «Average of the
  room’s sensors / Specific device or entity», режим свечения — «Colour and
  brightness» (тексты прежних ключей укорочены под сегменты);
- подпись поля с «?» и без стоят на одной линии в сетке (min-height 32 по
  кнопке hp-help); иконка внутри подсказки — inline;
- парные кадры: demo/capture_design_pairs_600.mjs снимает четыре диалога в
  двух темах на 560 в состояниях макетов → docs/design/…/pairs/ (8 PNG,
  палитра 256, ~0,5 МБ); ACCEPTANCE.md — статус по диалогам, расхождения с
  референсом по каждому со ссылкой на пункт SPEC и принятые адаптации (шапка
  hp-dialog по §3, тумблеры набора по К7, секции радара/пылесоса по §7.2);
- changelog EN/RU («Не выпущено»), USER-GUIDE ru/en: раздел «Как устроены
  диалоги настроек», таблица настроек пространства по новым карточкам,
  диалог комнаты, диалог устройства, ссылка «Как у пространства»;
- бюджет: стартовый граф 289 853 — потолок 291 600 → 290 900 (снятые стили);
  ленивый редакторский 243 149 — итоговый потолок 243 900 с разбором по
  сериям в bundle-budget.mjs.

Golden: 11 сцен диалогов (device-dialog-*, room-temperature-dialog-*,
toggle-entity-dialog-*, device-help-popover-light-ru,
general-color-popover-desktop-en, settings-help-zoom-200-*,
device-ripple-color-popover-mobile-ru, space-room-color-popover-desktop-ru)
прогнаны диагностически (capture, HP_ALLOW_FOREIGN_CAPTURE, только
artifacts/): харнесс проходит все пути без исключений, кадры «different» —
эталоны переснимаются на Linux CI / машине владельца по #455.
Скриншоты документации (06-device-editor, 06-device-display-preview и др.)
устарели по отпечатку — пересъёмка перед кандидатом беты (#479).

Гейты: typecheck, build, bundle:sync (три копии байт в байт), npm test
2793 pass по четырём частям, mutation-gate --check, check-inputs --coverage,
фокусные смоки четырёх форм и смоки диалога устройства.

Issue: #600
User-Visible: yes
This commit is contained in:
Claude
2026-09-20 13:01:07 +03:00
parent 6598af51d9
commit c3e64dc60a
76 changed files with 848 additions and 697 deletions
+19 -17
View File
@@ -684,7 +684,7 @@ export function renderMarkerDialog(this: HouseplanEditorRuntime): TemplateResult
: valueSourceMissing
? note(t('marker.value_source_missing_hint'), 'warning')
: selectedValueSourceCandidate
? html`<code class="hpf-mono markerbadgetechnical">${selectedValueSourceCandidate.technical}</code>`
? html`<code class="hpf-mono">${selectedValueSourceCandidate.technical}</code>`
: undefined,
})}</div>`
: nothing}
@@ -736,7 +736,7 @@ export function renderMarkerDialog(this: HouseplanEditorRuntime): TemplateResult
: displayWantsValue(d.display) && badgeSourceKey === innerValueSourceKey
? note(t('marker.value_badge_duplicate'), 'info')
: selectedBadgeCandidate
? html`<code class="hpf-mono markerbadgetechnical">${selectedBadgeCandidate.technical}</code>`
? html`<code class="hpf-mono">${selectedBadgeCandidate.technical}</code>`
: undefined,
})}
${field({
@@ -757,20 +757,22 @@ export function renderMarkerDialog(this: HouseplanEditorRuntime): TemplateResult
})}
` : nothing}
</div>
${tintBlock({
title: t('marker.preview.title'), tag: st('marker.preview_now'),
body: previewPresentation
? html`<hp-device-preview
.hass=${this.host.hass}
.presentation=${previewPresentation}
.registry=${this.host._haRegistry}
.deviceName=${d.name.trim() || previewDevice?.name || curLabel || ''}>
</hp-device-preview>`
: html`<div class="devicepreview-empty">
${previewPresentation
// Q3 (решение владельца): hp-device-preview целиком — у него свой
// заголовок «Display preview · Now» и свой блок на тинте, обёртка не нужна.
? html`<hp-device-preview
.hass=${this.host.hass}
.presentation=${previewPresentation}
.registry=${this.host._haRegistry}
.deviceName=${d.name.trim() || previewDevice?.name || curLabel || ''}>
</hp-device-preview>`
: tintBlock({
title: t('marker.preview.title'),
body: html`<div class="devicepreview-empty">
<ha-icon icon="mdi:eye-outline"></ha-icon>
<span>${t('marker.preview.select_source')}</span>
</div>`,
})}
})}
${subsection({ title: t('marker.size_label'), help: shelp('marker.size.help') })}
${fieldGrid([
html`<div class="hpf-field markersize">
@@ -825,8 +827,8 @@ export function renderMarkerDialog(this: HouseplanEditorRuntime): TemplateResult
label: t('marker.manuals_label'),
control: html`
${d.pdfs.length
? html`<div class="hpf-chips pdfedit">
${d.pdfs.map((p) => html`<span class="hpf-chip pdftag"><ha-icon icon="mdi:file-pdf-box" aria-hidden="true"></ha-icon>
? html`<div class="hpf-chips">
${d.pdfs.map((p) => html`<span class="hpf-chip"><ha-icon icon="mdi:file-pdf-box" aria-hidden="true"></ha-icon>
<a href="${safeUrl(this.host._display(p.url)) || '#'}" target="_blank" rel="noreferrer noopener">${p.name}</a>
<button type="button" aria-label=${`${t('btn.delete')}: ${p.name}`} title=${t('btn.delete')}
@click=${() => this._removeMarkerPdf(p.url)}><ha-icon icon="mdi:close"></ha-icon></button></span>`)}
@@ -852,7 +854,7 @@ export function renderMarkerDialog(this: HouseplanEditorRuntime): TemplateResult
<div class="body hpf-form">
${basics}${tap}${light}${appearance}${details}
</div>
<div class="row dialog-action-footer hpf-footer markerfooter" slot="footer">
<div class="row dialog-action-footer hpf-footer" slot="footer">
<div class="dialog-action-group markeractions">
${d.devId
? html`<button class="btn ghost" type="button"
@@ -874,7 +876,7 @@ export function renderMarkerDialog(this: HouseplanEditorRuntime): TemplateResult
${footerStatus(problems.length
? { action: textLink(st('dialog.review_fields', { n: String(problems.length) }), reviewFirst) }
: { text: edit && dirty ? st('dialog.unsaved') : '' })}
<div class="dialog-action-group dialog-action-commit markersaveactions">
<div class="dialog-action-group dialog-action-commit">
<button class="btn ghost" data-hp="dialog-cancel" ?disabled=${d.busy} @click=${requestClose}>${t('btn.cancel')}</button>
<button class="btn on" data-hp="dialog-confirm" @click=${() => { forgetMarkerBaseline(this.host); void this._saveMarker(); }}
?disabled=${!canSave} title=${saveTitle}>
+8 -4
View File
@@ -152,7 +152,7 @@ export function renderRoomSettingsDialog(this: HouseplanEditorRuntime): Template
${formCard({
id: 'basics',
title: t('room.group_basics'),
help: this._help('room.group_basics.help'),
// §6.1: «?» стоит у зоны — пояснение про свободные зоны относится к ней, а не к карточке
body: fieldGrid([
field({
label: t('room.name_label'), htmlFor: 'room-name',
@@ -162,7 +162,7 @@ export function renderRoomSettingsDialog(this: HouseplanEditorRuntime): Template
@input=${(e: Event) => { host._nameSel = (e.target as HTMLInputElement).value; host.requestUpdate(); }} />`,
}),
field({
label: t('room.area_label'), htmlFor: 'room-area',
label: t('room.area_label'), htmlFor: 'room-area', help: this._help('room.group_basics.help'),
control: html`<select id="room-area" class="hpf-select"
@change=${(e: Event) => {
host._areaSel = (e.target as HTMLSelectElement).value;
@@ -194,7 +194,11 @@ export function renderRoomSettingsDialog(this: HouseplanEditorRuntime): Template
name: 'rfill',
value: host._roomFill as RoomFillMode,
ariaLabel: t('room.fill_label'),
options: ROOM_FILL_MODES.map((value) => ({ value, label: t(`fill.${value}` as I18nKey) })),
// Короткие подписи там, где полные не помещаются в пять сегментов (§6.1: None | Zigbee | Lights | Temperature | Custom)
options: ROOM_FILL_MODES.map((value) => ({
value,
label: value === 'lqi' ? st('room.fill_seg_lqi') : value === 'custom' ? st('room.fill_seg_custom') : t(`fill.${value}` as I18nKey),
})),
onChange: (value) => setFill(value),
}),
})}
@@ -277,7 +281,7 @@ export function renderRoomSettingsDialog(this: HouseplanEditorRuntime): Template
<div class="hpf-tint hpf-preview">${host._renderCardPreview(spaceDisplay.cardFontScale, host._roomNameScale, host._roomLabelScale)}</div>`,
})}
</div>
<div class="row dialog-action-footer hpf-footer roomfooter" slot="footer">
<div class="row dialog-action-footer hpf-footer" slot="footer">
${!edit && !host._pendingSplit
? html`<div class="dialog-action-group">
<button class="btn ghost" data-hp="dialog-confirm" @click=${() => this._keepClosedAsPartitions()}>
+3 -3
View File
@@ -775,8 +775,8 @@
"room.temp_range.help.aria": "Informationen zum Komfortbereich des Raums",
"room.temp_src_label": "Temperaturquelle",
"room.hum_src_label": "Luftfeuchtigkeitsquelle",
"room.src_average": "Durchschnitt über die Sensoren des Raums (Standard)",
"room.src_pick": "Ein bestimmtes HA-Gerät oder Entität",
"room.src_average": "Durchschnitt der Raumsensoren",
"room.src_pick": "Bestimmtes Gerät oder Entität",
"room.src_ph": "Quelle wählen…",
"toast.room_updated": "Raum aktualisiert",
"space.card_font": "Schriftgröße der Raumkarten",
@@ -861,7 +861,7 @@
"marker.glow_mode.help.aria": "Hilfe: Leuchtfarbe und Helligkeit",
"marker.glow_mode_auto": "Von Quelle",
"marker.glow_mode_color": "Farbe einstellen",
"marker.glow_mode_fixed": "Farbe und Helligkeit einstellen",
"marker.glow_mode_fixed": "Farbe und Helligkeit",
"marker.glow_color": "Leuchtfarbe",
"marker.glow_brightness": "Helligkeit",
"marker.glow_disabled_never": "Leuchteinstellungen sind nicht verfügbar, da dieser Marker ausdrücklich keine Lichtquelle ist.",
+3 -3
View File
@@ -775,8 +775,8 @@
"room.temp_range.help.aria": "About the room comfort range",
"room.temp_src_label": "Temperature source",
"room.hum_src_label": "Humidity source",
"room.src_average": "Average over the room's sensors (default)",
"room.src_pick": "A specific HA device or entity",
"room.src_average": "Average of the room’s sensors",
"room.src_pick": "Specific device or entity",
"room.src_ph": "Choose a source…",
"toast.room_updated": "Room updated",
"space.card_font": "Room-card font size",
@@ -861,7 +861,7 @@
"marker.glow_mode.help.aria": "Help: glow colour and brightness",
"marker.glow_mode_auto": "From source",
"marker.glow_mode_color": "Set colour",
"marker.glow_mode_fixed": "Set colour and brightness",
"marker.glow_mode_fixed": "Colour and brightness",
"marker.glow_color": "Glow colour",
"marker.glow_brightness": "Brightness",
"marker.glow_disabled_never": "Glow settings are unavailable because this marker is explicitly not a light source.",
+3 -3
View File
@@ -775,8 +775,8 @@
"room.temp_range.help.aria": "À propos de la plage de confort de la pièce",
"room.temp_src_label": "Source de température",
"room.hum_src_label": "Source d’humidité",
"room.src_average": "Moyenne des capteurs de la pièce (par défaut)",
"room.src_pick": "Un appareil ou une entité HA spécifique",
"room.src_average": "Moyenne des capteurs de la pièce",
"room.src_pick": "Appareil ou entité spécifique",
"room.src_ph": "Choisir une source…",
"toast.room_updated": "Pièce mise à jour",
"space.card_font": "Taille de police des cartes",
@@ -861,7 +861,7 @@
"marker.glow_mode.help.aria": "Aide : couleur et luminosité du halo",
"marker.glow_mode_auto": "Depuis la source",
"marker.glow_mode_color": "Définir la couleur",
"marker.glow_mode_fixed": "Définir la couleur et la luminosité",
"marker.glow_mode_fixed": "Couleur et luminosité",
"marker.glow_color": "Couleur du halo",
"marker.glow_brightness": "Luminosité",
"marker.glow_disabled_never": "Les paramètres du halo sont indisponibles car ce marqueur est explicitement défini comme n’étant pas une source lumineuse.",
+3 -3
View File
@@ -775,8 +775,8 @@
"room.temp_range.help.aria": "О диапазоне комфорта комнаты",
"room.temp_src_label": "Источник температуры",
"room.hum_src_label": "Источник влажности",
"room.src_average": "Средняя по датчикам комнаты (по умолчанию)",
"room.src_pick": "Конкретное устройство или сущность HA",
"room.src_average": "Среднее по датчикам комнаты",
"room.src_pick": "Конкретное устройство или сущность",
"room.src_ph": "Выберите источник…",
"toast.room_updated": "Комната обновлена",
"space.card_font": "Размер шрифта карточек",
@@ -861,7 +861,7 @@
"marker.glow_mode.help.aria": "Подсказка: цвет и яркость свечения",
"marker.glow_mode_auto": "Из источника",
"marker.glow_mode_color": "Задать цвет",
"marker.glow_mode_fixed": "Задать цвет и яркость",
"marker.glow_mode_fixed": "Цвет и яркость",
"marker.glow_color": "Цвет свечения",
"marker.glow_brightness": "Яркость",
"marker.glow_disabled_never": "Настройки свечения недоступны: маркер явно исключён из источников света.",
+3 -2
View File
@@ -81,10 +81,11 @@
"marker.icon_custom_hint": "Eigenes Symbol für diesen Marker.",
"marker.display.help": "Wie das Marker-Gesicht auf Zustand und Aktivität reagiert. Die Wert-Modi ersetzen das Symbol durch einen Home-Assistant-Wert.",
"marker.display.help.aria": "Hilfe: Anzeigemodus",
"marker.preview_now": "Jetzt",
"marker.size.help": "Skaliert und dreht nur diesen Marker auf dem Plan. Die Tippfläche wächst mit dem Symbol.",
"marker.size.help.aria": "Hilfe: Symbolgröße und Drehung",
"marker.size_short": "Größe",
"marker.error_binding": "Wählen Sie ein Gerät oder eine Entität zum Verknüpfen.",
"marker.error_glow_radius": "Geben Sie einen Radius größer als 0 ein oder lassen Sie das Feld leer."
"marker.error_glow_radius": "Geben Sie einen Radius größer als 0 ein oder lassen Sie das Feld leer.",
"room.fill_seg_lqi": "Zigbee",
"room.fill_seg_custom": "Eigene"
}
+3 -2
View File
@@ -81,10 +81,11 @@
"marker.icon_custom_hint": "Custom icon for this marker.",
"marker.display.help": "How the marker face reacts to state and activity. The value modes replace the icon with a Home Assistant value.",
"marker.display.help.aria": "Help: display mode",
"marker.preview_now": "Now",
"marker.size.help": "Scales and rotates only this marker on the plan. The tap area grows with the icon.",
"marker.size.help.aria": "Help: icon size and rotation",
"marker.size_short": "Size",
"marker.error_binding": "Choose a device or entity to bind.",
"marker.error_glow_radius": "Enter a radius greater than 0, or leave it empty."
"marker.error_glow_radius": "Enter a radius greater than 0, or leave it empty.",
"room.fill_seg_lqi": "Zigbee",
"room.fill_seg_custom": "Custom"
}
+3 -2
View File
@@ -81,10 +81,11 @@
"marker.icon_custom_hint": "Icône personnalisée pour ce marqueur.",
"marker.display.help": "Comment la face du marqueur réagit à l’état et à l’activité. Les modes valeur remplacent l’icône par une valeur Home Assistant.",
"marker.display.help.aria": "Aide : mode d’affichage",
"marker.preview_now": "Maintenant",
"marker.size.help": "Redimensionne et fait pivoter uniquement ce marqueur sur le plan. La zone de toucher grandit avec l’icône.",
"marker.size.help.aria": "Aide : taille et rotation de l’icône",
"marker.size_short": "Taille",
"marker.error_binding": "Choisissez un appareil ou une entité à lier.",
"marker.error_glow_radius": "Saisissez un rayon supérieur à 0 ou laissez le champ vide."
"marker.error_glow_radius": "Saisissez un rayon supérieur à 0 ou laissez le champ vide.",
"room.fill_seg_lqi": "Zigbee",
"room.fill_seg_custom": "Perso"
}
+3 -2
View File
@@ -81,10 +81,11 @@
"marker.icon_custom_hint": "Своя иконка для этого маркера.",
"marker.display.help": "Как лицо маркера реагирует на состояние и активность. Режимы значения заменяют иконку значением из Home Assistant.",
"marker.display.help.aria": "Справка: режим отображения",
"marker.preview_now": "Сейчас",
"marker.size.help": "Масштабирует и поворачивает только этот маркер на плане. Область нажатия растёт вместе с иконкой.",
"marker.size.help.aria": "Справка: размер и поворот иконки",
"marker.size_short": "Размер",
"marker.error_binding": "Выберите устройство или сущность для привязки.",
"marker.error_glow_radius": "Введите радиус больше 0 или оставьте поле пустым."
"marker.error_glow_radius": "Введите радиус больше 0 или оставьте поле пустым.",
"room.fill_seg_lqi": "Zigbee",
"room.fill_seg_custom": "Свой цвет"
}
-6
View File
@@ -236,12 +236,6 @@ const chromeCoreStyles = css`
color: var(--hp-muted);
margin-bottom: var(--sp-3);
}
.togglehint {
overflow-wrap: anywhere;
}
.togglehint > div + div {
margin-top: var(--sp-1);
}
/* Keep the last editor bar mounted while the row collapses. This makes
both entering and leaving an editor change the card geometry gradually;
the header ResizeObserver keeps the stage fitted throughout. */
-192
View File
@@ -249,31 +249,6 @@ export const dialogsStyles = css`
.oprow b { margin-left: auto; }
.oprow.ok b { color: #66d17a; }
.oprow.warn b { color: var(--hp-open); }
.bindharow {
display: flex;
align-items: center;
gap: var(--sp-5);
flex-wrap: wrap;
}
.bindharow .entcheck { opacity: 0.9; }
.ctrlchips { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: var(--sp-2) 0; }
.ctrlchip {
display: inline-flex; align-items: center; gap: var(--sp-2);
background: var(--hp-accent); color: var(--text-primary-color, #fff);
border-radius: var(--rad-l); padding: var(--sp-2) var(--sp-4); font-size: var(--fs-s);
}
.ctrlchip ha-icon { --mdc-icon-size: 14px; cursor: pointer; }
.ctrllist { display: flex; flex-direction: column; gap: var(--sp-1); margin-top: var(--sp-2); }
.ctrlopt {
display: flex; align-items: center; gap: var(--sp-4); text-align: left;
border: 0; background: transparent; color: var(--hp-txt);
padding: var(--sp-3) var(--sp-4); border-radius: var(--rad-s); cursor: pointer; font-family: inherit; font-size: var(--fs-m);
}
:host([data-pointer-hover]) .ctrlopt:hover {
background: var(--secondary-background-color, rgba(128,128,128,0.15));
}
.ctrlopt .sub { color: var(--hp-muted); font-size: var(--fs-s); margin-left: auto; }
.ctrlopt ha-icon { --mdc-icon-size: 16px; }
.ctrlstates { display: flex; flex-direction: column; gap: var(--sp-2); }
.ctrlstate { display: inline-flex; align-items: center; gap: var(--sp-3); color: var(--hp-muted); }
.ctrlstate.on { color: var(--hp-txt); }
@@ -297,16 +272,6 @@ export const dialogsStyles = css`
opacity: 0.85;
}
.cardpreview .cpmeta ha-icon { --mdc-icon-size: 1.05em; }
.iconauto {
display: flex;
align-items: center;
gap: var(--sp-3);
font-size: var(--fs-s);
margin: var(--sp-2) 0 0;
}
.iconauto ha-icon { --mdc-icon-size: 18px; }
.iconauto span { flex: 1; }
.iconauto .btn { min-height: 32px; padding: 0 var(--sp-3); }
hp-dialog .dfill {
display: inline-flex;
align-items: center;
@@ -391,17 +356,6 @@ export const dialogsStyles = css`
align-items: center;
gap: var(--sp-4);
}
.gsrow > hp-color-opacity {
min-width: min(100%, 210px);
justify-content: space-between;
}
.ripple-colorrow > hp-color-opacity {
width: 100%;
justify-content: space-between;
}
.ripple-sizerow > .opl {
min-width: 0;
}
.colorrow input[type='range'] { flex: 1; }
.colorrow .tempin { width: 70px; flex: none; }
/* beat the generic hp-dialog .body .namein { width:100% } rule */
@@ -457,14 +411,6 @@ export const dialogsStyles = css`
box-sizing: border-box;
width: 100%;
}
.radaradditional {
margin-top: var(--sp-5);
}
.radaradditional summary {
cursor: pointer;
font-weight: 600;
}
.radaradditional .btn { margin-top: var(--sp-3); }
.radarinspection {
display: grid;
gap: 6px;
@@ -528,31 +474,6 @@ export const dialogsStyles = css`
dominant-baseline: middle;
pointer-events: none;
}
.markerhelpfield { margin-top: var(--sp-4); }
.markerhelplabel {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--sp-1);
margin-bottom: var(--sp-1);
}
.markerhelplabel > label { min-width: 0; overflow-wrap: anywhere; }
.helpfieldlabel {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--sp-1);
min-width: 0;
margin-top: var(--sp-3);
color: var(--hp-muted);
font-size: var(--fs-s);
}
.helpfieldlabel.compact { margin-top: 0; }
hp-dialog .body .helpfieldlabel > label {
min-width: 0;
margin-top: 0;
overflow-wrap: anywhere;
}
.help-inline-label {
display: inline-flex;
align-items: center;
@@ -564,27 +485,11 @@ export const dialogsStyles = css`
margin-top: 0;
overflow-wrap: anywhere;
}
.markerradios { display: grid; gap: var(--sp-1); min-width: 0; }
.markerlightgroup .srcrow > span:first-of-type {
min-width: 0;
white-space: normal;
overflow-wrap: anywhere;
}
.markerglowvalue { margin: var(--sp-3) 0; flex-wrap: wrap; }
.markerglowvalue hp-color-opacity { flex: none; }
.markerlightdisabled {
display: flex;
align-items: center;
gap: var(--sp-2);
margin-top: var(--sp-2) !important;
}
.markerlightdisabled ha-icon { --mdc-icon-size: 18px; flex: none; }
.markerbadgetechnical {
min-width: 0;
margin: var(--sp-1) 0 var(--sp-2) !important;
overflow-wrap: anywhere;
}
.markerbadgetechnical code { white-space: normal; }
.planrow {
display: flex;
align-items: center;
@@ -652,8 +557,6 @@ export const dialogsStyles = css`
.filebtn {
cursor: pointer;
}
.fileupload { display: inline-flex; min-width: 0; }
.fileupload > input { display: none; }
.btn.danger {
border-color: #b3402a;
color: #ff7a5c;
@@ -695,48 +598,6 @@ export const dialogsStyles = css`
font-size: var(--fs-l);
line-height: 1.3;
}
.descin {
width: 100%;
box-sizing: border-box;
background: var(--hp-bg);
border: 1px solid var(--hp-line);
color: var(--hp-txt);
border-radius: var(--rad-s);
padding: var(--sp-3) var(--sp-4);
font-size: var(--fs-m);
font-family: inherit;
resize: vertical;
/* flex column of the dialog body squeezes textareas — keep a usable height */
min-height: 92px;
flex-shrink: 0;
line-height: 1.35;
}
.bindsel {
display: flex;
flex-direction: column;
gap: var(--sp-3);
border: 1px solid var(--hp-line);
border-radius: var(--rad-m);
padding: var(--sp-4);
}
.bindsel .opt {
display: flex;
align-items: center;
gap: var(--sp-3);
border: 1px solid var(--hp-line);
background: transparent;
color: var(--hp-txt);
border-radius: var(--rad-s);
padding: var(--sp-3) var(--sp-4);
cursor: pointer;
font-size: var(--fs-m);
font-family: inherit;
}
.bindsel .opt.on {
background: var(--hp-accent);
color: var(--text-primary-color, #fff);
border-color: var(--hp-accent);
}
.curbind {
display: flex;
align-items: center;
@@ -1036,37 +897,6 @@ export const dialogsStyles = css`
color: var(--hp-muted);
cursor: default;
}
.pdfedit {
display: flex;
flex-wrap: wrap;
gap: var(--sp-3);
align-items: center;
}
.pdftag {
display: inline-flex;
align-items: center;
gap: var(--sp-2);
border: 1px solid var(--hp-line);
border-radius: var(--rad-s);
padding: var(--sp-2) var(--sp-3);
font-size: var(--fs-s);
}
.pdftag a {
color: var(--hp-txt);
text-decoration: none;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.pdftag .x {
--mdc-icon-size: 15px;
cursor: pointer;
color: var(--hp-muted);
}
:host([data-pointer-hover]) .pdftag .x:hover {
color: #ff7a5c;
}
.entlist {
display: flex;
flex-direction: column;
@@ -1181,11 +1011,6 @@ export const dialogsStyles = css`
}
:host([data-pointer-hover]) .rrow .ract:hover { color: var(--hp-txt); }
:host([data-pointer-hover]) .rrow .ract.del:hover { color: #ff7a5c; }
.gsrow .gsl {
min-width: 150px;
font-size: var(--fs-m);
color: var(--hp-muted);
}
.optimize-live {
display: grid;
justify-items: start;
@@ -1493,15 +1318,6 @@ export const dialogsStyles = css`
margin-left: auto;
justify-content: flex-end;
}
hp-dialog .row.markerfooter {
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
hp-dialog .row.roomfooter {
align-items: center;
flex-wrap: wrap;
}
/* Device info can have Edit + Open in HA + Close. It uses a wide dialog;
wrapping remains as a phone fallback, but without a flex spacer (which
used to strand Edit alone on the first line). */
@@ -1522,14 +1338,6 @@ export const dialogsStyles = css`
padding: var(--sp-4) var(--sp-5);
}
}
.markeractions,
.markersaveactions {
display: flex;
align-items: center;
gap: var(--sp-4);
}
.markeractions:empty { display: none; }
.markersaveactions { margin-left: auto; }
.device-inbox {
display: flex;
flex-direction: column;
+3 -2
View File
@@ -166,7 +166,7 @@ function extrasCss(options: FormKitCssOptions): string {
.${p}-sub h4 { margin: 0; font-size: 1rem; line-height: 1.4; font-weight: 600; }
.${p}-field { display: grid; gap: 7px; min-width: 0; }
.${p}-field > .${p}-label,
.${p}-labelrow { display: flex; align-items: center; gap: 4px; min-height: 28px; font-size: .875rem; font-weight: 600; color: var(${tokens.muted}); }
.${p}-labelrow { display: flex; align-items: center; gap: 4px; min-height: 32px; font-size: .875rem; font-weight: 600; color: var(${tokens.muted}); }
.${p}-labelrow > label { cursor: pointer; }
.${p}-hint { margin: 0; font-size: .875rem; line-height: 1.5; color: var(${tokens.muted}); }
.${p}-error { margin: 0; font-size: .875rem; line-height: 1.5; color: var(${tokens.danger}); }
@@ -413,7 +413,7 @@ function extrasCss(options: FormKitCssOptions): string {
.${p}-range-ends { display: flex; justify-content: space-between; padding-right: 122px; margin-top: -8px; font-size: .875rem; color: var(${tokens.muted}); }
.${p}-headline { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.${p}-north { display: grid; grid-template-columns: minmax(0, 1fr) 44px; gap: 7px 16px; align-items: center; }
.${p}-north > .${p}-labelrow { grid-area: 1 / 1; min-height: 28px; }
.${p}-north > .${p}-labelrow { grid-area: 1 / 1; min-height: 32px; }
.${p}-north > .${p}-select, .${p}-north > .${p}-unit, .${p}-north > .${p}-input { grid-area: 2 / 1; }
.${p}-north > .${p}-north-n { grid-area: 1 / 2; text-align: center; font-size: .875rem; line-height: 28px; color: var(${tokens.muted}); }
.${p}-compass { grid-area: 2 / 2; box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border: 1px solid var(${tokens.line}); border-radius: 50%; background: var(${tokens.canvas}); color: var(${tokens.accent}); }
@@ -462,6 +462,7 @@ function extrasCss(options: FormKitCssOptions): string {
.${p}-iconpreview { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 44px; width: 44px; height: 44px; border: 1px solid var(${tokens.line}); border-radius: 7px; background: var(${tokens.canvas}); color: var(${tokens.muted}); }
.${p}-mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .8125rem; }
.${p}-hint > .${p}-link { padding: 0; }
.${p}-hint ha-icon { --mdc-icon-size: 16px; display: inline-flex; vertical-align: -3px; }
.${p}-actionrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.${p}-note { display: flex; align-items: flex-start; gap: 6px; }
.${p}-note > ha-icon { --mdc-icon-size: 16px; flex: 0 0 auto; margin-top: 2px; }