Files
houseplan-card/src/styles/chrome.styles.ts
T
2026-09-08 18:49:36 +03:00

395 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** Editor chrome: toolbars, tabs, menus and hints (#266, split from styles.ts). */
import { css, type CSSResultGroup } from 'lit';
const chromeCoreStyles = css`
.hdr {
position: sticky;
top: var(--header-height, 56px);
z-index: 20;
background: var(--card-background-color, var(--hp-bg));
border-radius: var(--ha-card-border-radius, 12px) var(--ha-card-border-radius, 12px) 0 0;
}
.tabs {
display: flex;
gap: var(--sp-2);
background: rgba(127, 127, 127, 0.12);
padding: var(--sp-2);
border-radius: var(--rad-l);
flex-wrap: wrap;
}
.tab {
border: 0;
background: transparent;
color: var(--hp-muted);
display: inline-flex;
align-items: center;
padding: var(--sp-3) var(--sp-5);
border-radius: var(--rad-m);
font-size: var(--fs-m);
font-weight: 600;
cursor: pointer;
transition: 0.15s;
font-family: inherit;
}
:host([data-pointer-hover]) .tab:hover {
color: var(--hp-txt);
}
.tab.active {
background: var(--hp-accent);
color: var(--text-primary-color, #fff);
}
/* docs/CANVAS.md §4.1: objects an order of magnitude away from the plan
do not decide the opening view — one quiet chip says so and offers to
take them in. Never a modal (owner). */
.farhint {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: var(--sp-4);
z-index: 12;
display: flex;
align-items: center;
gap: var(--sp-2);
max-width: calc(100% - var(--sp-8));
background: var(--card-background-color, var(--hp-bg));
opacity: 0.94;
color: var(--hp-txt);
border: 1px solid var(--divider-color, #33404d);
border-radius: var(--rad-m);
padding: var(--sp-1) var(--sp-3);
font-size: var(--fs-s);
}
.farhint ha-icon {
--mdc-icon-size: 18px;
color: var(--hp-warn, #e2a03f);
flex: none;
}
.farhint span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.dropbtn {
display: flex;
align-items: center;
gap: var(--sp-4);
width: 100%;
text-align: left;
border: 1px solid var(--hp-muted);
border-radius: var(--rad-m);
background: transparent;
color: var(--hp-txt);
padding: var(--sp-4) 10px;
cursor: pointer;
font-family: inherit;
font-size: var(--fs-m);
margin-top: var(--sp-3);
}
.dropbtn .ref { color: var(--hp-muted); font-size: var(--fs-s); margin-left: auto; }
.dropbtn ha-icon { --mdc-icon-size: 18px; margin-left: var(--sp-2); }
.dropbtn.open { border-color: var(--hp-accent); }
.droppanel {
border: 1px solid var(--hp-accent);
border-top: none;
border-radius: 0 0 var(--rad-m) var(--rad-m);
padding: var(--sp-3);
margin-top: -4px;
}
.hdr.kioskhide { display: none; }
.decorbar .dcolor {
width: 30px; height: 26px; padding: 0; border: none; background: none; cursor: pointer;
}
.decorbar .dwidth {
font-family: inherit; font-size: var(--fs-s); border-radius: var(--rad-s);
background: var(--hp-bg2, transparent); color: var(--hp-txt); border: 1px solid var(--hp-muted);
padding: var(--sp-2) var(--sp-3);
}
.decorbar .bdhint {
font-size: var(--fs-s);
color: var(--hp-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.decorbar .dfill {
display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-s); cursor: pointer;
}
.decorbar .dfill input[type="checkbox"] {
width: 16px;
height: 16px;
flex: none;
margin: 0;
padding: 0;
}
.decorbar hp-color-opacity { flex: 0 0 auto; }
.modes {
display: inline-flex;
gap: var(--sp-1);
background: rgba(127, 127, 127, 0.12);
border-radius: var(--rad-l);
padding: var(--sp-2);
}
.modetab {
display: inline-flex;
align-items: center;
gap: var(--sp-3);
border: 0;
background: transparent;
color: var(--hp-muted);
padding: var(--sp-3) 10px; /* 10px h-padding kept: +2px would wrap the header modes row */
border-radius: var(--rad-m);
font-size: var(--fs-m);
font-weight: 600;
cursor: pointer;
font-family: inherit;
transition: background-color 0.14s ease, color 0.14s ease, transform 0.14s ease;
}
.modetab:active { transform: scale(0.97); }
.modetab ha-icon { --mdc-icon-size: 15px; }
/* issue #220: a tab can be dragged to a new position in the editors */
.tab[data-reorderable] { cursor: grab; }
.tab.dragging { cursor: grabbing; opacity: 0.55; }
.tab.drop-before { box-shadow: inset 2px 0 0 0 var(--primary-color, #03a9f4); }
.tab.drop-after { box-shadow: inset -2px 0 0 0 var(--primary-color, #03a9f4); }
.modetab .closex {
--mdc-icon-size: 13px;
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
min-width: 24px;
min-height: 24px;
/* Keep the old 13 × 13 flex footprint (+2 px left margin) while the
pointer target grows around it. Header width, height and wrapping do
not move; only near-misses that used to hit the active tab reach X. */
margin: -5.5px -5.5px -5.5px -3.5px;
opacity: 0.75;
cursor: pointer;
border-radius: var(--rad-s);
}
:host([data-pointer-hover]) .modetab .closex:hover { opacity: 1; }
.editbar .barclose {
box-sizing: border-box;
width: 40px;
height: 40px;
padding: 0;
margin: 0;
min-width: 40px;
min-height: 40px;
justify-content: center;
gap: 0;
line-height: 0;
}
.editbar .barclose ha-icon { flex: none; margin: 0; }
.modetab.active {
background: var(--hp-accent);
color: var(--text-primary-color, #fff);
}
@media (max-width: 720px) {
.modetab .ml { display: none; }
}
.editbar {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: stretch;
border-bottom: 1px solid var(--hp-line);
font-size: var(--fs-m);
}
.editbar-tools {
display: flex;
align-items: center;
gap: 10px;
padding: var(--sp-4) var(--sp-5);
flex-wrap: wrap;
min-width: 0;
outline: none;
}
.editbar-end {
display: flex;
align-items: center;
padding: var(--sp-4) var(--sp-5);
border-inline-start: 1px solid var(--hp-line);
background: var(--card-background-color, var(--hp-bg));
position: relative;
z-index: 2;
}
.tab .tabedit {
--mdc-icon-size: 13px;
display: inline-flex;
align-items: center;
margin-left: var(--sp-3);
opacity: 0.4;
}
:host([data-pointer-hover]) .tab:hover .tabedit {
opacity: 0.9;
}
.tab.tabadd {
padding: var(--sp-3) var(--sp-4);
}
.tab.tabadd ha-icon {
--mdc-icon-size: 15px;
}
.rhint {
font-size: var(--fs-s);
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. */
.editorchrome {
display: block;
height: 0;
opacity: 0;
visibility: hidden;
overflow: hidden;
}
.editorchrome:not(.open) {
pointer-events: none;
}
.editorchrome.open {
height: auto;
opacity: 1;
visibility: visible;
overflow: visible;
}
.editorchrome.transitioning {
overflow: hidden;
will-change: height;
pointer-events: none;
}
/* The toolbar is already visible while its height is interpolating. Its
explicit navigation control must remain usable even though all editing
tools stay frozen until the transition settles. */
.editorchrome.transitioning .barclose {
pointer-events: auto;
}
.editorchrome-inner {
min-height: 0;
transform-origin: top center;
}
.editorchrome.transitioning .editorchrome-inner {
will-change: opacity;
}
@media (prefers-reduced-motion: reduce) {
.modetab { transition: none; }
}
.editbar .warn {
color: #ffc14d;
}
.editbar .sname {
font-weight: 600;
}
.editbar input {
width: 74px;
background: transparent;
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);
}
.editbar label,
.editbar .hint {
color: var(--hp-muted);
font-size: var(--fs-s);
}
.editbar .drawwall {
display: inline-flex;
align-items: center;
gap: var(--sp-3);
white-space: nowrap;
}
.editbar .wallsgroup {
display: inline-flex;
align-items: center;
gap: 10px;
white-space: nowrap;
}
.editbar .drawwall input {
width: 4.2em;
}
.editbar .drawwall .opl {
color: var(--hp-muted);
font-size: var(--fs-s);
}
.menuwrap {
position: fixed;
inset: 0;
z-index: 80;
}
.menu {
position: fixed;
background: var(--hp-bg);
border: 1px solid var(--hp-accent);
border-radius: var(--rad-l);
box-shadow: var(--shadow-2);
min-width: 210px;
max-width: 300px;
overflow: hidden;
transform: translate(0, 8px);
}
.menu .hd {
padding: var(--sp-4) var(--sp-5);
font-weight: 600;
font-size: var(--fs-m);
border-bottom: 1px solid var(--hp-line);
display: flex;
align-items: center;
gap: var(--sp-3);
}
.menu .hd ha-icon,
.menu .it.all ha-icon {
color: var(--hp-accent);
--mdc-icon-size: 16px;
}
.menu .it {
padding: var(--sp-4) var(--sp-5);
font-size: var(--fs-m);
cursor: pointer;
display: flex;
align-items: center;
gap: var(--sp-4);
}
.menu .it ha-icon {
--mdc-icon-size: 16px;
color: var(--hp-muted);
}
:host([data-pointer-hover]) .menu .it:hover {
background: rgba(127, 127, 127, 0.15);
}
.menu .it.all {
color: var(--hp-accent);
font-weight: 600;
}
.tip {
position: fixed;
pointer-events: none;
background: var(--hp-bg);
border: 1px solid var(--hp-accent);
color: var(--hp-txt);
padding: var(--sp-3) 10px;
border-radius: var(--rad-m);
font-size: var(--fs-m);
box-shadow: var(--shadow-2);
z-index: 60;
max-width: 260px;
}
.tip .m {
color: var(--hp-muted);
font-size: var(--fs-s);
display: block;
}
`;
/** #437 summary CSS lives with its lazy runtime in summary-panel-style.ts. */
export const chromeStyles: CSSResultGroup = chromeCoreStyles;