feat: Add UI support for PTZ presets (#1920)
- Closes #1889 Whilst a simple change theoretically, the card has such a collection of surfaces that can overlap other surfaces, it's challenging to get this to work right! There's a real chance this will have broken something z-index related (e.g. X overlaps Y when it should not), or (for related reasons) broken curver corners on the card.
This commit is contained in:
+13
-43
@@ -1,4 +1,5 @@
|
||||
@use './themes/base.scss';
|
||||
@import './z-index.scss';
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
@@ -10,9 +11,8 @@
|
||||
// this ensures the same experience across all browsers.
|
||||
background-color: var(--card-background-color);
|
||||
|
||||
// The primary border-radius used is the div.main. This is only useful for
|
||||
// keeping the background-color within the radius.
|
||||
border-radius: var(--ha-card-border-radius, 4px);
|
||||
overflow: auto;
|
||||
|
||||
height: var(--advanced-camera-card-height);
|
||||
min-height: 100px;
|
||||
@@ -32,10 +32,18 @@
|
||||
--advanced-camera-card-height: auto;
|
||||
}
|
||||
|
||||
// Without hovering over the card, it is "flattened" to avoid z-index weaving
|
||||
// from other cards. Tip: Best way to test this is with multiple Advanced Camera
|
||||
// Cards, opening a submenu on the 1st (e.g. media players) and verifying the
|
||||
// menu of the 2nd card is not visible through the opened submenu on the 1st.
|
||||
:host(:not(:hover)) {
|
||||
z-index: #{$z-index-card-flatten};
|
||||
}
|
||||
|
||||
advanced-camera-card-loading {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
z-index: #{$z-index-loading};
|
||||
}
|
||||
|
||||
:host([dimmable]:not([interaction])) {
|
||||
@@ -60,17 +68,11 @@ advanced-camera-card-loading {
|
||||
div.main {
|
||||
position: relative;
|
||||
|
||||
// Required to keep curved corners on the card.
|
||||
overflow: auto;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
display: block;
|
||||
|
||||
// Necessary to get Safari to show border-radius correctly.
|
||||
transform: translateZ(0);
|
||||
|
||||
// Hide scrollbar: Firefox
|
||||
scrollbar-width: none;
|
||||
// Hide scrollbar: IE and Edge
|
||||
@@ -82,20 +84,6 @@ div.main::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Need to apply the border radius on the container level, as the ha-card has
|
||||
// overflow visible in order to allow a submenu to extend beyond the card
|
||||
// boundary. Need to be able to selectively curve top or bottom depending on
|
||||
// whether the outside menu is being shown. There's no way to select 'preceding
|
||||
// element' in CSS, so this must be implemented in JS.
|
||||
div.main.curve-top {
|
||||
border-top-left-radius: var(--ha-card-border-radius, 4px);
|
||||
border-top-right-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
div.main.curve-bottom {
|
||||
border-bottom-left-radius: var(--ha-card-border-radius, 4px);
|
||||
border-bottom-right-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
ha-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -181,30 +169,12 @@ web-dialog::part(dialog) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* "Outside" style for menu/status bar
|
||||
*************************************/
|
||||
|
||||
// Style is set on the children themselves, to avoid the need for the parent
|
||||
// outlay to prevent overflow (which needs to be enabled to menu items to be
|
||||
// visible). See similar approach in overlay.scss for overlay.
|
||||
|
||||
.outerlay[data-position='top'] > *:first-child {
|
||||
border-top-left-radius: var(--ha-card-border-radius, 4px);
|
||||
border-top-right-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
.outerlay[data-position='bottom'] > *:last-child {
|
||||
border-bottom-left-radius: var(--ha-card-border-radius, 4px);
|
||||
border-bottom-right-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Menu hover styles
|
||||
*******************/
|
||||
|
||||
advanced-camera-card-menu {
|
||||
z-index: 2;
|
||||
z-index: #{$z-index-menu};
|
||||
}
|
||||
|
||||
advanced-camera-card-menu[data-style*='hover'] {
|
||||
@@ -223,7 +193,7 @@ ha-card:hover
|
||||
*************************/
|
||||
|
||||
advanced-camera-card-status-bar {
|
||||
z-index: 1;
|
||||
z-index: #{$z-index-status-bar};
|
||||
}
|
||||
|
||||
advanced-camera-card-status-bar[data-style*='hover'] {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@import './z-index.scss';
|
||||
|
||||
:host {
|
||||
// Drawer width sizes to contents.
|
||||
width: unset;
|
||||
@@ -28,7 +30,7 @@
|
||||
|
||||
// Drawer renders behind the menu/status-bar overlay (otherwise the drawer
|
||||
// controls render on top of menu items)
|
||||
z-index: 10;
|
||||
z-index: #{$z-index-drawer};
|
||||
}
|
||||
|
||||
:host([location='right']) #d {
|
||||
|
||||
@@ -9,7 +9,6 @@ div.control-surround {
|
||||
position: absolute;
|
||||
bottom: 50%;
|
||||
transform: translateY(50%);
|
||||
z-index: 0;
|
||||
padding-top: $drawer-padding-extend;
|
||||
padding-bottom: $drawer-padding-extend;
|
||||
}
|
||||
@@ -48,13 +47,6 @@ advanced-camera-card-icon.control {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
:host([open]) advanced-camera-card-icon.control,
|
||||
advanced-camera-card-icon.control:hover {
|
||||
// When the drawer is open or hovered make the button to close it more
|
||||
// prominent.
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
:host([location='left']) advanced-camera-card-icon.control {
|
||||
border-top-right-radius: $drawer-icon-size;
|
||||
border-bottom-right-radius: $drawer-icon-size;
|
||||
|
||||
@@ -43,10 +43,6 @@
|
||||
var(--advanced-camera-card-grid-column-size)
|
||||
)
|
||||
);
|
||||
|
||||
// When at item is selected, it may be enlarged -- it should render "in-front"
|
||||
// of the other cameras that will then "move out of the way".
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
slot {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@use './button.scss';
|
||||
|
||||
ha-icon-button {
|
||||
// Icons in the menu are expected to follow Advanced Camera 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).
|
||||
--state-unavailable-color: var(--advanced-camera-card-button-color);
|
||||
--state-inactive-color: var(--advanced-camera-card-button-color);
|
||||
|
||||
color: var(--advanced-camera-card-menu-button-inactive-color);
|
||||
background-color: var(--advanced-camera-card-menu-button-background);
|
||||
}
|
||||
+1
-12
@@ -1,4 +1,4 @@
|
||||
@use './button.scss';
|
||||
@use './menu-button.scss';
|
||||
|
||||
:host {
|
||||
--advanced-camera-card-menu-button-size: 40px;
|
||||
@@ -10,9 +10,6 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
// Allow submenus to overflow the menu "bar".
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
:host([data-style='outside']) {
|
||||
@@ -142,13 +139,5 @@ div.opposing {
|
||||
background: var(--advanced-camera-card-menu-background);
|
||||
}
|
||||
|
||||
// Icons in the menu are expected to follow Advanced Camera 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(--advanced-camera-card-button-color);
|
||||
--state-inactive-color: var(--advanced-camera-card-button-color);
|
||||
}
|
||||
|
||||
// Further theme related styling is dynamically applied by `menu.ts`, see
|
||||
// `_renderPerInstanceStyle`.
|
||||
|
||||
@@ -55,31 +55,3 @@ slot[name='bottom'],
|
||||
slot[name='right'] {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Match rounded corners to card
|
||||
*******************************/
|
||||
|
||||
// Style is set on the children themselves, to avoid the need for the parent
|
||||
// outlay to prevent overflow (which needs to be enabled to menu items to be
|
||||
// visible). See similar approach in card.scss for outerlay.
|
||||
|
||||
::slotted([slot='top']:first-child),
|
||||
::slotted([slot='left']:first-child) {
|
||||
border-top-left-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
::slotted([slot='top']:first-child),
|
||||
::slotted([slot='right']:first-child) {
|
||||
border-top-right-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
::slotted([slot='bottom']:last-child),
|
||||
::slotted([slot='left']:last-child) {
|
||||
border-bottom-left-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
::slotted([slot='bottom']:last-child),
|
||||
::slotted([slot='right']:last-child) {
|
||||
border-bottom-right-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
+18
-34
@@ -55,7 +55,7 @@
|
||||
|
||||
.ptz-move,
|
||||
.ptz-zoom,
|
||||
.ptz-home {
|
||||
.ptz-presets {
|
||||
position: relative;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
@@ -68,27 +68,28 @@
|
||||
}
|
||||
|
||||
:host([data-orientation='horizontal']) .ptz .ptz-zoom,
|
||||
:host([data-orientation='horizontal']) .ptz .ptz-home {
|
||||
:host([data-orientation='horizontal']) .ptz .ptz-presets {
|
||||
width: calc(var(--advanced-camera-card-ptz-icon-size) * 1.5);
|
||||
}
|
||||
:host([data-orientation='vertical']) .ptz .ptz-zoom,
|
||||
:host([data-orientation='vertical']) .ptz .ptz-home {
|
||||
:host([data-orientation='vertical']) .ptz .ptz-presets {
|
||||
height: calc(var(--advanced-camera-card-ptz-icon-size) * 1.5);
|
||||
}
|
||||
|
||||
.ptz-zoom,
|
||||
.ptz-home {
|
||||
.ptz-presets {
|
||||
border-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
/***********
|
||||
* PTZ Icons
|
||||
***********/
|
||||
advanced-camera-card-icon {
|
||||
.ptz-move advanced-camera-card-icon {
|
||||
position: absolute;
|
||||
--mdc-icon-size: var(--advanced-camera-card-ptz-icon-size);
|
||||
}
|
||||
advanced-camera-card-icon:not(.disabled) {
|
||||
advanced-camera-card-icon:not(.disabled),
|
||||
advanced-camera-card-submenu:not(.disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
.disabled {
|
||||
@@ -115,34 +116,17 @@ advanced-camera-card-icon:not(.disabled) {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
:host([data-orientation='vertical']) .zoom_in {
|
||||
right: 5px;
|
||||
top: 50%;
|
||||
.ptz-presets,
|
||||
.ptz-zoom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
:host([data-orientation='vertical']) .zoom_out {
|
||||
left: 5px;
|
||||
top: 50%;
|
||||
:host([data-orientation='vertical']) .ptz-presets,
|
||||
:host([data-orientation='vertical']) .ptz-zoom {
|
||||
flex-direction: row;
|
||||
}
|
||||
:host([data-orientation='horizontal']) .zoom_in {
|
||||
left: 50%;
|
||||
top: 5px;
|
||||
}
|
||||
:host([data-orientation='horizontal']) .zoom_out {
|
||||
left: 50%;
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
:host([data-orientation='vertical']) .zoom_in,
|
||||
:host([data-orientation='vertical']) .zoom_out {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
:host([data-orientation='horizontal']) .zoom_in,
|
||||
:host([data-orientation='horizontal']) .zoom_out {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.home {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
:host([data-orientation='horizontal']) .ptz-presets,
|
||||
:host([data-orientation='horizontal']) .ptz-zoom {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
@use './button.scss';
|
||||
@import './z-index.scss';
|
||||
|
||||
:host {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
mwc-list-item {
|
||||
z-index: 20;
|
||||
--mdc-menu-z-index: #{$z-index-submenu};
|
||||
}
|
||||
|
||||
ha-icon-button {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/************
|
||||
* Managing z-indicies and stacking contexts is very challenging on the card,
|
||||
* due to the volume of different potentially overlapping surfaces. In
|
||||
* particular, care must be taken to not generate new stacking contexts
|
||||
* inadvertently which would make "z-index" weaving challenging (e.g. submenu
|
||||
* shown for PTZ presets, needs to render "over" the media drawer open/close
|
||||
* control).
|
||||
*************/
|
||||
|
||||
// More-info dialog box has a z-index of 8, so everything meaningful needs to be
|
||||
// below that.
|
||||
|
||||
$z-index-loading: 6;
|
||||
$z-index-submenu: 5;
|
||||
|
||||
// Need menu to render above drawer (so the drawer button is below menu-submenus)
|
||||
$z-index-menu: 4;
|
||||
$z-index-drawer: 3;
|
||||
$z-index-status-bar: 2;
|
||||
|
||||
// The base z-index when the card is not hovered over. See note in card.scss .
|
||||
$z-index-card-flatten: 0;
|
||||
Reference in New Issue
Block a user