feat: Add richer card theme support (#1809)

This commit is contained in:
Dermot Duffy
2025-01-07 19:54:13 -08:00
committed by GitHub
parent f7ecb91578
commit 278560b5ac
65 changed files with 1187 additions and 352 deletions
+4 -4
View File
@@ -1,6 +1,7 @@
ha-icon-button.button {
color: var(--secondary-color, white);
background-color: rgba(0, 0, 0, 0.6);
ha-icon-button {
color: var(--frigate-card-button-color);
background-color: var(--frigate-card-button-background);
border-radius: 50%;
padding: 0px;
margin: 3px;
@@ -8,5 +9,4 @@ ha-icon-button.button {
/* Buttons can always be clicked */
pointer-events: auto;
opacity: 0.9;
}
+3 -1
View File
@@ -1,3 +1,5 @@
@use './themes/base.scss';
:host {
display: block;
@@ -36,7 +38,7 @@ frigate-card-loading {
z-index: 1;
}
:host([dark]) {
:host([dimmable]:not([interaction])) {
filter: brightness(75%);
}
:host([panel]:not([casted])) {
+2 -4
View File
@@ -37,9 +37,8 @@ div.control-surround {
}
frigate-card-icon.control {
color: var(--secondary-color, white);
background-color: rgba(0, 0, 0, 0.7);
opacity: 0.5;
color: var(--frigate-card-button-color);
background-color: var(--frigate-card-button-background);
pointer-events: all;
--mdc-icon-size: #{$drawer-icon-size};
@@ -54,7 +53,6 @@ frigate-card-icon.control:hover {
// When the drawer is open or hovered make the button to close it more
// prominent.
opacity: 1;
background-color: black;
}
:host([location='left']) frigate-card-icon.control {
+1 -1
View File
@@ -98,7 +98,7 @@ div.upgrade span {
margin-right: 0px;
margin-bottom: 5px;
}
.submenu .controls ha-icon-button.button {
.submenu .controls ha-icon-button {
--mdc-icon-button-size: 32px;
--mdc-icon-size: calc(var(--mdc-icon-button-size) / 2);
}
+10
View File
@@ -12,3 +12,13 @@
width: 100%;
box-sizing: border-box;
}
svg path {
// !important is necessary to overcome the fill set on the path itself.
fill: currentColor !important;
}
:host([allow-override-non-active-styles]) state-badge {
--state-inactive-color: inherit;
--state-unavailable-color: inherit;
}
+3 -2
View File
@@ -9,8 +9,9 @@
pointer-events: none;
}
img {
width: 10%;
frigate-card-icon {
height: 50%;
width: auto;
animation: rotate 8s linear infinite;
}
+2 -1
View File
@@ -1,4 +1,5 @@
$bg-img: url('../images/camera-iris-transparent.svg');
// Use the outlined Iris logo since the background color is unknown.
$bg-img: url('../images/iris-background.svg');
:host {
background-color: var(--primary-background-color);
+22 -41
View File
@@ -15,6 +15,10 @@
overflow: visible;
}
:host([data-style='outside']) {
width: 100%;
}
/*******************************************************
* Non-hover styles should not interact with the pointer
*******************************************************/
@@ -45,15 +49,6 @@ div.opposing {
justify-content: flex-end;
}
/********************
* Outside menu style
********************/
:host([data-style='outside']) {
width: 100%;
background: var(--secondary-background-color);
}
/********************************************************
* Hack: Ensure host & div expand for column flex layouts
********************************************************/
@@ -126,24 +121,6 @@ div.opposing {
height: auto;
}
:host([data-style='overlay'][data-position='top'][data-alignment='left']),
:host([data-style='overlay'][data-position='bottom'][data-alignment='left']),
:host([data-style*='hover'][data-position='top'][data-alignment='left']),
:host([data-style*='hover'][data-position='bottom'][data-alignment='left']),
:host([data-style='hidden'][data-position='top'][data-alignment='left'][expanded]),
:host([data-style='hidden'][data-position='bottom'][data-alignment='left'][expanded]) {
background: linear-gradient(90deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
}
:host([data-style='overlay'][data-position='top'][data-alignment='right']),
:host([data-style='overlay'][data-position='bottom'][data-alignment='right']),
:host([data-style*='hover'][data-position='top'][data-alignment='right']),
:host([data-style*='hover'][data-position='bottom'][data-alignment='right']),
:host([data-style='hidden'][data-position='top'][data-alignment='right'][expanded]),
:host([data-style='hidden'][data-position='bottom'][data-alignment='right'][expanded]) {
background: linear-gradient(270deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
}
:host([data-style='overlay'][data-position='left']),
:host([data-style='overlay'][data-position='right']),
:host([data-style*='hover'][data-position='left']),
@@ -154,20 +131,24 @@ div.opposing {
height: 100%;
}
:host([data-style='overlay'][data-position='left'][data-alignment='top']),
:host([data-style='overlay'][data-position='right'][data-alignment='top']),
:host([data-style*='hover'][data-position='left'][data-alignment='top']),
:host([data-style*='hover'][data-position='right'][data-alignment='top']),
:host([data-style='hidden'][data-position='left'][data-alignment='top'][expanded]),
:host([data-style='hidden'][data-position='right'][data-alignment='top'][expanded]) {
background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
/************
* Menu theme
************/
// When the menu uses the hidden style, and is not expanded, the remaining
// permanent menu buttons use the menu background color instead of the button
// background color.
:host([data-style='hidden']:not([expanded])) ha-icon-button {
background: var(--frigate-card-menu-background);
}
:host([data-style='overlay'][data-position='left'][data-alignment='bottom']),
:host([data-style='overlay'][data-position='right'][data-alignment='bottom']),
:host([data-style*='hover'][data-position='left'][data-alignment='bottom']),
:host([data-style*='hover'][data-position='right'][data-alignment='bottom']),
:host([data-style='hidden'][data-position='left'][data-alignment='bottom'][expanded]),
:host([data-style='hidden'][data-position='right'][data-alignment='bottom'][expanded]) {
background: linear-gradient(0deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
// Icons in the menu are expected to follow Frigate card theming unless they are
// active (in which case we want to take advantage of the whatever styling is
// appropriate, e.g. light icon partially lit).
:host ha-icon-button {
--state-unavailable-color: var(--frigate-card-button-color);
--state-inactive-color: var(--frigate-card-button-color);
}
// Further theme related styling is dynamically applied by `menu.ts`, see
// `_renderPerInstanceStyle`.
+13 -20
View File
@@ -1,7 +1,7 @@
@use './button.scss';
:host {
--mdc-icon-size: calc(var(--frigate-card-status-bar-height) - 6px);
--mdc-icon-size: calc(var(--frigate-card-status-bar-height) / 2);
display: block;
width: 100%;
@@ -20,23 +20,10 @@
pointer-events: none;
}
/***************
* Outside style
***************/
/**********************
* Popup style behavior
**********************/
:host([data-style='outside']) {
color: var(--primary-text-color);
background: var(--secondary-background-color);
}
/*******************
* Non-outside style
*******************/
:host(:not([data-style='outside'])) {
color: white;
background: linear-gradient(90deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
}
:host([data-style='popup'][hide]) {
opacity: 0;
}
@@ -63,8 +50,6 @@
margin: 3px 5px;
align-content: center;
opacity: 0.7;
}
.item:first-child {
margin-left: 10px;
@@ -81,7 +66,8 @@
cursor: pointer;
}
img.item {
img.item,
frigate-card-icon.item {
display: block;
// To ensure images render somewhat reasonably looking their height is kept to
@@ -89,3 +75,10 @@ img.item {
height: var(--mdc-icon-size, 24px);
width: auto;
}
/************************
* Status bar theme hooks
************************/
// Further theme related styling is dynamically applied by `status-bar.ts`, see
// `_renderPerInstanceStyle`.
+11
View File
@@ -7,3 +7,14 @@
mwc-list-item {
z-index: 20;
}
ha-icon-button {
// The main submenu icon is expected to follow Frigate card theming unless it
// is are active (in which case we want to take advantage of the whatever
// styling is appropriate, e.g. light icon partially lit).
--state-unavailable-color: var(--frigate-card-button-color);
--state-inactive-color: var(--frigate-card-button-color);
color: var(--frigate-card-menu-button-inactive-color);
background-color: var(--frigate-card-menu-button-background);
}
+127
View File
@@ -0,0 +1,127 @@
@use 'dark.scss';
@use 'light.scss';
@use 'traditional.scss';
:host {
/*********
* General
*********/
--frigate-card-exterior: var(--secondary-background-color, black);
--frigate-card-background: var(--primary-background-color, white);
--frigate-card-foreground-primary: var(--primary-color, black);
--frigate-card-active-color: var(--accent-color, orange);
--frigate-card-warning-color: var(--error-color, red);
--frigate-card-text-color: var(--primary-text-color);
--frigate-card-divider-color: var(--divider-color);
--frigate-card-control-background: var(--app-header-background-color);
--frigate-card-control-background-transparent: color-mix(
in oklab,
var(--frigate-card-control-background),
transparent 60%
);
--frigate-card-control-foreground: var(--app-header-text-color);
/*********
* Buttons
*********/
// The color of buttons (in general, menu or otherwise).
--frigate-card-button-color: var(--frigate-card-control-foreground);
// The color of button background "circles".
--frigate-card-button-background: var(--frigate-card-control-background-transparent);
/******
* Menu
******/
// The color of an active icon in the menu.
--frigate-card-menu-button-active-color: var(--frigate-card-active-color);
// The color of an inactive icon in the menu.
--frigate-card-menu-button-inactive-color: var(--frigate-card-button-color);
// The color of a critical icon in the menu.
--frigate-card-menu-button-critical-color: var(
--error-color,
var(--frigate-card-warning-color)
);
// The background color of the button "circles" in the menu.
--frigate-card-menu-button-background: color-mix(
in oklab,
var(--frigate-card-menu-button-inactive-color),
transparent 60%
);
// The menu background color.
--frigate-card-menu-background: var(--frigate-card-control-background-transparent);
--frigate-card-menu-style-outside-background: var(--frigate-card-control-background);
// May be overridden by the user to force a particular color.
--frigate-card-menu-override-background: unset;
--frigate-card-menu-override-button-inactive-color: unset;
--frigate-card-menu-override-button-background: unset;
// Examples of precise theming for the menu:
// --frigate-card-menu-position-left-alignment-left-style-overlay-background: pink;
// --frigate-card-menu-position-left-background: purple;
// --frigate-card-menu-style-overlay-background: pink;
/************
* Status bar
************/
// May be overridden by the user to force a particular color.
--frigate-card-status-bar-override-background: unset;
--frigate-card-status-bar-override-color: unset;
// The color of items on the status bar.
--frigate-card-status-bar-color: var(--frigate-card-control-foreground);
// The background color of the outerlay above/below the card.
--frigate-card-status-bar-background: var(
--frigate-card-control-background-transparent
);
--frigate-card-status-bar-style-outside-background: var(
--frigate-card-control-background
);
/************
* Thumbnails
************/
--frigate-card-thumbnail-icon-color: var(--frigate-card-foreground-primary);
--frigate-card-thumbnail-border-color: var(--frigate-card-foreground-primary);
--frigate-card-thumbnail-background: var(--frigate-card-background);
--frigate-card-thumbnail-icon-favorite-color: color-mix(
in oklab,
gold,
transparent 25%
);
--frigate-card-thumbnail-text-color: var(--frigate-card-text-color);
/**********
* Timeline
**********/
--frigate-card-timeline-text-color: var(--frigate-card-text-color);
--frigate-card-timeline-item-color: var(--frigate-card-foreground-primary);
--frigate-card-timeline-tool-color: var(--frigate-card-foreground-primary);
--frigate-card-timeline-background: var(--frigate-card-background);
// style for the 'background' style of item (i.e. recordings).
--frigate-card-timeline-background-item-color: color-mix(
in oklab,
var(--frigate-card-timeline-item-color),
transparent 90%
);
--frigate-card-timeline-divider-color: var(--frigate-card-divider-color);
--frigate-card-timeline-target-bar-color: var(--frigate-card-active-color);
}
+11
View File
@@ -0,0 +1,11 @@
:host([themes~='dark']) {
// This file should include only, and exactly match, values from
// https://github.com/home-assistant/frontend/blob/dev/src/resources/styles-data.ts .
--primary-background-color: #111111;
--secondary-background-color: #282828;
--primary-text-color: #e1e1e1;
--divider-color: rgba(225, 225, 225, 0.12);
--app-header-background-color: #101e24;
--app-header-text-color: #e1e1e1;
}
+17
View File
@@ -0,0 +1,17 @@
:host([themes~='light']) {
// This file should include only, and exactly match, values from
// https://github.com/home-assistant/frontend/blob/dev/src/resources/ha-style.ts
--primary-background-color: #fafafa;
--secondary-background-color: #e5e5e5;
--primary-text-color: #212121;
--divider-color: rgba(0, 0, 0, 0.12);
--app-header-text-color: #ffffff;
// HA dynamically sets these values based on choice of primary/secondary
// colors and hex blending techniques. The card does not currently
// re-implement this logic, rather just uses the default static value.
// See: https://github.com/home-assistant/frontend/blob/dev/src/common/dom/apply_themes_on_element.ts
--app-header-background-color: #03a9f4;
}
+99
View File
@@ -0,0 +1,99 @@
@mixin background-gradient($var, $angle) {
#{$var}: linear-gradient(
$angle,
var(--frigate-card-menu-background),
var(--frigate-card-menu-background),
var(--frigate-card-menu-background),
color-mix(in oklab, var(--frigate-card-menu-background), transparent 100%)
);
}
:host([themes~='traditional']) {
/*********
* General
*********/
--frigate-card-control-background: black;
/******
* Menu
******/
--frigate-card-menu-button-active-color: var(--primary-color, white);
--frigate-card-menu-button-background: rgba(0, 0, 0, 0.6);
@include background-gradient(
'--frigate-card-menu-position-left-alignment-top-background',
180deg
);
@include background-gradient(
'--frigate-card-menu-position-left-alignment-bottom-background',
0deg
);
@include background-gradient(
'--frigate-card-menu-position-right-alignment-top-background',
180deg
);
@include background-gradient(
'--frigate-card-menu-position-right-alignment-bottom-background',
0deg
);
@include background-gradient(
'--frigate-card-menu-position-top-alignment-left-background',
90deg
);
@include background-gradient(
'--frigate-card-menu-position-top-alignment-right-background',
270deg
);
@include background-gradient(
'--frigate-card-menu-position-bottom-alignment-left-background',
90deg
);
@include background-gradient(
'--frigate-card-menu-position-bottom-alignment-right-background',
270deg
);
--frigate-card-menu-position-top-alignment-left-style-outside-background: var(
--secondary-background-color
);
--frigate-card-menu-position-top-alignment-right-style-outside-background: var(
--secondary-background-color
);
--frigate-card-menu-position-bottom-alignment-left-style-outside-background: var(
--secondary-background-color
);
--frigate-card-menu-position-bottom-alignment-right-style-outside-background: var(
--secondary-background-color
);
/************
* Status bar
************/
--frigate-card-status-bar-color: white;
@include background-gradient(
'--frigate-card-status-bar-position-top-background',
90deg
);
@include background-gradient(
'--frigate-card-status-bar-position-bottom-background',
90deg
);
--frigate-card-status-bar-position-top-style-outside-background: var(
--secondary-background-color
);
--frigate-card-status-bar-position-bottom-style-outside-background: var(
--secondary-background-color
);
--frigate-card-status-bar-position-top-style-outside-color: var(
--secondary-text-color
);
--frigate-card-status-bar-position-bottom-style-outside-color: var(
--secondary-text-color
);
}
+2
View File
@@ -5,6 +5,8 @@
width: 100%;
height: 100%;
background-color: var(--frigate-card-thumbnail-background);
--frigate-card-carousel-thumbnail-opacity: 1;
}
+1 -1
View File
@@ -5,7 +5,7 @@
width: 100%;
margin-left: 5px;
padding: 5px;
color: var(--primary-text-color);
color: var(--frigate-card-thumbnail-text-color);
overflow: hidden;
column-gap: 5%;
}
+4 -5
View File
@@ -15,7 +15,7 @@
}
:host([details]) {
border: 1px solid var(--primary-color);
border: 1px solid var(--frigate-card-thumbnail-border-color);
border-radius: var(
--frigate-card-css-border-radius,
var(--ha-card-border-radius, 4px)
@@ -24,7 +24,7 @@
// When details are enabled, use a background color so that the details have
// contrast with the background.
background-color: var(--primary-background-color, black);
background-color: var(--frigate-card-thumbnail-background);
}
:host(:hover) {
@@ -34,8 +34,7 @@
frigate-card-icon {
position: absolute;
border-radius: 50%;
opacity: 0.5;
color: var(--primary-color);
color: var(--frigate-card-thumbnail-icon-color);
cursor: pointer;
@@ -52,7 +51,7 @@ frigate-card-icon.star {
left: 3px;
}
frigate-card-icon.star.starred {
color: gold;
color: var(--frigate-card-thumbnail-icon-favorite-color);
}
frigate-card-icon.timeline {
+31 -21
View File
@@ -10,6 +10,8 @@
// So that absolute sidedrawer is relative to this host.
position: relative;
background-color: var(--frigate-card-timeline-background);
}
:host(:not([mini])) {
@@ -30,7 +32,7 @@ div.timeline {
}
.vis-text {
color: var(--primary-text-color) !important;
color: var(--frigate-card-timeline-text-color) !important;
}
.vis-timeline {
@@ -39,7 +41,7 @@ div.timeline {
.vis-labelset .vis-label {
// Group labels.
color: var(--primary-text-color);
color: var(--frigate-card-timeline-text-color);
}
:host([ribbon]:not([groups])) .vis-item:not(.vis-background) {
@@ -52,12 +54,11 @@ div.timeline {
// Ribbon timelines have a much shorter 'bar'.
height: 6px;
}
.vis-item {
border-color: var(--primary-color);
border-color: var(--frigate-card-timeline-item-color);
background: none;
color: var(--primary-text-color);
background-color: var(--primary-color);
color: var(--frigate-card-timeline-text-color);
background-color: var(--frigate-card-timeline-item-color);
transition:
background-color ease-in-out 1s,
@@ -65,13 +66,15 @@ div.timeline {
box-shadow ease-in-out 1s;
}
.vis-item.vis-selected {
border-color: var(--accent-color);
background-color: var(--accent-color);
box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 5px 1px var(--primary-color));
border-color: var(--frigate-card-active-color);
background-color: var(--frigate-card-active-color);
box-shadow: var(
--frigate-card-css-box-shadow,
0px 0px 5px 1px var(--frigate-card-active-color)
);
}
.vis-item.vis-background {
background-color: var(--primary-color);
opacity: 0.1;
background-color: var(--frigate-card-timeline-background-item-color);
}
// If there are no timeline groups shown (e.g. mini mode with a single camera),
@@ -103,16 +106,19 @@ div.timeline {
.vis-item.vis-cluster {
border-style: dotted;
color: var(--primary-text-color);
background-color: var(--primary-background-color);
box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 5px 1px var(--primary-color));
color: var(--frigate-card-timeline-text-color);
background-color: var(--frigate-card-timeline-background);
box-shadow: var(
--frigate-card-css-box-shadow,
0px 0px 5px 1px var(--frigate-card-timeline-item-color)
);
}
.vis-item.vis-range {
border-radius: var(--frigate-card-css-border-radius, unset);
}
.vis-time-axis .vis-grid.vis-minor {
border-color: var(--secondary-color);
border-color: var(--frigate-card-timeline-divider-color);
}
// Give an indication that the user can interact with the axes.
@@ -121,11 +127,15 @@ div.timeline {
transition: background-color 0.5s ease-out;
}
:host([recordings]) .vis-text.vis-minor:hover {
background-color: var(--primary-color);
background-color: color-mix(
in oklab,
var(--frigate-card-timeline-text-color),
transparent 80%
);
}
.vis-time-axis .vis-grid.vis-major {
border-color: var(--secondary-color);
border-color: var(--frigate-card-timeline-divider-color);
}
.vis-label {
@@ -146,7 +156,7 @@ div.vis-tooltip {
}
.target_bar {
background-color: var(--primary-color);
background-color: var(--frigate-card-timeline-target-bar-color);
width: 2px;
z-index: 20;
@@ -155,8 +165,8 @@ div.vis-tooltip {
pointer-events: none;
}
.target_bar .vis-custom-time-marker {
background-color: var(--primary-background-color);
color: var(--primary-text-color);
background-color: var(--frigate-card-timeline-background);
color: var(--frigate-card-timeline-text-color);
bottom: 0px;
top: unset;
}
@@ -176,7 +186,7 @@ div.vis-tooltip {
position: absolute;
right: 0px;
bottom: 0px;
color: var(--primary-color);
color: var(--frigate-card-timeline-tool-color);
z-index: 10;
}
.timeline-tools * {