fix: Improve visual styling for transmitting/triggering (#2490)
This commit is contained in:
committed by
dermotduffy
parent
090138a01e
commit
f21a46297a
@@ -114,6 +114,8 @@ Allows overriding of any CSS value, can be used to tweak theming parameters.
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| Any CSS key. Overriding the [Advanced Camera Card](https://github.com/dermotduffy/advanced-camera-card/blob/main/src/scss/themes/base.scss) CSS variables allows changing individual theming parameters, e.g. `--advanced-camera-card-menu-override-background` | Any CSS value, e.g. `red` or `rgba(10, 11, 12, 0.64)`. |
|
||||
|
||||
> [!WARNING] Changes to CSS keys are not considered breaking changes and may not have an associated [major version change](../developing.md?id=release-philosophy).
|
||||
|
||||
## `triggers`
|
||||
|
||||
The `triggers` block controls how the card reacts when a camera is triggered
|
||||
|
||||
@@ -445,6 +445,8 @@ export class AdvancedCameraCardLiveCarousel extends LitElement {
|
||||
<!-- -->
|
||||
${this._renderNextPrevious('right', neighbors)}
|
||||
</advanced-camera-card-carousel>
|
||||
<div class="status-glow status-glow--trigger"></div>
|
||||
<div class="status-glow status-glow--transmitting"></div>
|
||||
<advanced-camera-card-ptz
|
||||
.hass=${this.hass}
|
||||
.config=${this.liveConfig.controls.ptz}
|
||||
|
||||
@@ -35,3 +35,82 @@
|
||||
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
|
||||
// Triggered and transmitting cameras are highlighted with a soft inset glow,
|
||||
// drawn by an overlay stacked above the camera feed. The overlays come before
|
||||
// the carousel controls in source order, so they stack above the feed but
|
||||
// below the controls; `pointer-events: none` keeps them inert. The glow is an
|
||||
// interior effect, so it coexists with the grid selection border (see
|
||||
// media-grid.scss) without competing for the `border` property.
|
||||
//
|
||||
// The two states differ by colour and rhythm: triggered is an amber glow that
|
||||
// pulses fully out and back (a "something happened" beacon), transmitting is a
|
||||
// red glow that breathes gently without ever fully fading ("you are live").
|
||||
// Transmitting wins: while it is active the trigger overlay is faded out.
|
||||
|
||||
// Triggered: pulse from nothing to a full amber glow and back.
|
||||
@keyframes trigger-vignette-pulse {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: inset 0 0 var(--advanced-camera-card-trigger-glow-size) transparent;
|
||||
}
|
||||
50% {
|
||||
box-shadow: inset 0 0 var(--advanced-camera-card-trigger-glow-size)
|
||||
var(--advanced-camera-card-trigger-glow-color);
|
||||
}
|
||||
}
|
||||
|
||||
// Transmitting: breathe between a softer and a fuller glow — never fully fades,
|
||||
// so the camera always reads as live.
|
||||
@keyframes transmitting-vignette-pulse {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: inset 0 0 calc(var(--advanced-camera-card-transmitting-glow-size) * 0.55)
|
||||
var(--advanced-camera-card-transmitting-glow-color);
|
||||
}
|
||||
50% {
|
||||
box-shadow: inset 0 0 var(--advanced-camera-card-transmitting-glow-size)
|
||||
var(--advanced-camera-card-transmitting-glow-color);
|
||||
}
|
||||
}
|
||||
|
||||
.status-glow {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
|
||||
// Hidden by default; activation/deactivation is a plain opacity fade. Each
|
||||
// overlay carries its own static box-shadow (not scoped to the
|
||||
// `[triggered]`/`[transmitting]` selectors) so the glow stays painted in its
|
||||
// own colour throughout the fade-out, after its animation has been removed.
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.status-glow--trigger {
|
||||
box-shadow: inset 0 0 var(--advanced-camera-card-trigger-glow-size)
|
||||
var(--advanced-camera-card-trigger-glow-color);
|
||||
}
|
||||
|
||||
.status-glow--transmitting {
|
||||
box-shadow: inset 0 0 var(--advanced-camera-card-transmitting-glow-size)
|
||||
var(--advanced-camera-card-transmitting-glow-color);
|
||||
}
|
||||
|
||||
:host([triggered]) .status-glow--trigger {
|
||||
opacity: 1;
|
||||
animation: trigger-vignette-pulse 5s infinite;
|
||||
}
|
||||
|
||||
// Transmitting takes precedence: while it is active the trigger overlay is
|
||||
// faded out. This rule follows the `[triggered]` rule with equal specificity,
|
||||
// so it wins the cascade.
|
||||
:host([transmitting]) .status-glow--trigger {
|
||||
opacity: 0;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
:host([transmitting]) .status-glow--transmitting {
|
||||
opacity: 1;
|
||||
animation: transmitting-vignette-pulse 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@@ -1,61 +1,8 @@
|
||||
@use 'basic-block.scss';
|
||||
@use 'locked.scss';
|
||||
|
||||
@keyframes warning-pulse {
|
||||
0% {
|
||||
border-color: var(--trigger-border-color-base);
|
||||
}
|
||||
50% {
|
||||
border-color: var(--trigger-border-color);
|
||||
}
|
||||
100% {
|
||||
border-color: var(--trigger-border-color-base);
|
||||
}
|
||||
}
|
||||
|
||||
advanced-camera-card-live-carousel {
|
||||
--trigger-border-color: var(--advanced-camera-card-trigger-border-color);
|
||||
--trigger-border-color-base: var(
|
||||
--advanced-camera-card-trigger-border-color-base,
|
||||
black
|
||||
);
|
||||
|
||||
transition: border-color 0.3s ease-out;
|
||||
}
|
||||
|
||||
// `:host >` matches the carousel only in single display mode (in grid mode it
|
||||
// is nested inside `media-grid`). The single-mode carousel has no border of its
|
||||
// own, so reserve a transparent one so border changes (e.g. trigger) only
|
||||
// recolour. In grid mode the border is supplied (already width-reserved) by
|
||||
// `media-grid`.
|
||||
:host > advanced-camera-card-live-carousel {
|
||||
box-sizing: border-box;
|
||||
border: solid 2px transparent;
|
||||
}
|
||||
|
||||
advanced-camera-card-live-carousel[triggered] {
|
||||
animation: warning-pulse 5s infinite;
|
||||
}
|
||||
// The `:host` prefix raises specificity to (0,2,1), above `media-grid`'s
|
||||
// `::slotted([selected])` border (0,1,1). In grid mode that rule lives in an
|
||||
// inner shadow tree and would otherwise win the cross-tree cascade tie,
|
||||
// leaving the transmitting border the wrong colour. `[triggered]` needs no
|
||||
// such treatment — animated values always beat the regular cascade.
|
||||
:host advanced-camera-card-live-carousel[transmitting] {
|
||||
// `animation: none` cancels any concurrent trigger pulse to ensure
|
||||
// transmitting takes precedence.
|
||||
animation: none;
|
||||
border-color: var(--advanced-camera-card-transmitting-border-color);
|
||||
}
|
||||
// While locked, dim and disable interaction on the non-selected cameras in the
|
||||
// grid so input stays on the selected camera (e.g. during a call).
|
||||
:host([locked]) advanced-camera-card-live-carousel[unselected] {
|
||||
@include locked.style;
|
||||
}
|
||||
|
||||
advanced-camera-card-live-carousel[selected] {
|
||||
--trigger-border-color-base: var(
|
||||
--advanced-camera-card-trigger-border-color-base,
|
||||
var(--advanced-camera-card-foreground-primary)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -245,15 +245,16 @@
|
||||
/*********
|
||||
* Trigger
|
||||
*********/
|
||||
--advanced-camera-card-trigger-border-color: var(--advanced-camera-card-warning-color);
|
||||
--advanced-camera-card-trigger-border-color-base: unset;
|
||||
--advanced-camera-card-trigger-glow-color: var(--advanced-camera-card-active-color);
|
||||
--advanced-camera-card-trigger-glow-size: 16px;
|
||||
|
||||
/**************
|
||||
* Transmitting
|
||||
**************/
|
||||
--advanced-camera-card-transmitting-border-color: var(
|
||||
--advanced-camera-card-transmitting-glow-color: var(
|
||||
--advanced-camera-card-warning-color
|
||||
);
|
||||
--advanced-camera-card-transmitting-glow-size: 28px;
|
||||
|
||||
/*****
|
||||
* Grid
|
||||
|
||||
Reference in New Issue
Block a user