Merge pull request #38 from dermotduffy/vertical-overlays

Add support for top, left, bottom, right menus
This commit is contained in:
Dermot Duffy
2021-09-02 20:33:53 -07:00
committed by GitHub
6 changed files with 76 additions and 44 deletions
+3 -3
View File
@@ -62,7 +62,7 @@ lovelace:
| `motion_entity` | | A binary sensor to show in the menu (e.g. a Frigate motion binary sensor) and to use to trigger card updates.|
| `frigate_camera_name` | The string after the "camera." in the `camera_entity` option (above). | This parameter allows the camera name heuristic to be overriden for cases where the entity name does not cleanly map to the Frigate camera name (e.g. when the Frigate camera name is capitalized, but the entity name is lower case). This camera name is used for communicating with the Frigate backend, e.g. for fetching events. |
| `view_default` | `live` | The view to show by default. See [views](#views) below.|
| `menu_mode` | `hidden` | The menu mode to show by default. See [menu modes](#menu-modes) below.|
| `menu_mode` | `hidden-top` | The menu mode to show by default. See [menu modes](#menu-modes) below.|
| `frigate_client_id` | `frigate` | The Frigate client id to use. If this Home Assistant server has multiple Frigate server backends configured, this selects which server should be used. It should be set to the MQTT client id configured for this server, see [Frigate Integration Multiple Instance Support](https://blakeblackshear.github.io/frigate/usage/home-assistant/#multiple-instance-support).|
| `view_timeout` | | A numbers of seconds of inactivity after which the card will reset to the default configured view. Inactivity is defined as lack of interaction with the Frigate menu.|
| `frigate_url` | | The URL of the frigate server. If set, this value will be (exclusively) used for a `Frigate UI` menu button. |
@@ -155,8 +155,8 @@ This card supports several menu configurations.
| Key | Description | Screenshot |
| ------------- | --------------------------------------------- | - |
|`hidden` (default)| Hide the menu by default, expandable upon clicking the 'F' button. | <img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/images/menu-mode-hidden.png" alt="Menu hidden" width="400px"> |
|`overlay`| Overlay the menu on top of the card contents. The 'F' button shows the default view. | <img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/images/menu-mode-overlay.png" alt="Menu overlaid" width="400px"> |
|`hidden-{top,bottom,right,left}` (default)| Hide the menu by default, expandable upon clicking the 'F' button. | <img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/images/menu-mode-hidden.png" alt="Menu hidden" width="400px"> |
|`overlay-{top,bottom,right,left}`| Overlay the menu on top of the card contents. The 'F' button shows the default view. | <img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/images/menu-mode-overlay.png" alt="Menu overlaid" width="400px"> |
|`above`| Render the menu above the card. The 'F' button shows the default view. | <img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/images/menu-mode-above.png" alt="Menu above" width="400px"> |
|`below`| Render the menu below the card. The 'F' button shows the default view. | <img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/images/menu-mode-below.png" alt="Menu below" width="400px"> |
+8 -2
View File
@@ -105,8 +105,14 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
const menuModes = {
'': '',
hidden: 'Hidden',
overlay: 'Overlay',
'hidden-top': 'Hidden Top',
'hidden-left': 'Hidden Left',
'hidden-bottom': 'Hidden Bottom',
'hidden-right': 'Hidden Right',
'overlay-top': 'Overlay Top',
'overlay-left': 'Overlay Left',
'overlay-bottom': 'Overlay Bottom',
'overlay-right': 'Overlay Right',
above: 'Above',
below: 'Below',
};
+22 -16
View File
@@ -1,5 +1,4 @@
/* Base: Not used directly */
.frigate-card-menu-base {
.frigate-card-menu {
z-index: 1;
height: 56px;
overflow: hidden;
@@ -8,24 +7,32 @@
*/
pointer-events: none;
}
/* Small 'F' button for hidden menu */
.frigate-card-menu-hidden {
@extend .frigate-card-menu-base;
.frigate-card-menu.overlay-hidden {
position: absolute;
width: 56px;
}
/* Expanded overlay menu */
.frigate-card-menu-overlay {
@extend .frigate-card-menu-hidden;
.frigate-card-menu.overlay-hidden.left {
left: 0px;
}
.frigate-card-menu.overlay-hidden.right {
right: 0px;
}
.frigate-card-menu.overlay-hidden.top {
top: 0px;
}
.frigate-card-menu.overlay-hidden.bottom {
bottom: 0px;
}
.frigate-card-menu.overlay-hidden.expanded-horizontal {
width: 100%;
background: linear-gradient(90deg, rgba(0,0,0,0.3), rgba(0,0,0,0))
background: linear-gradient(90deg, rgba(0,0,0,0.3), rgba(0,0,0,0));
}
.frigate-card-menu.overlay-hidden.expanded-vertical {
height: 100%;
background: linear-gradient(180deg, rgba(0,0,0,0.3), rgba(0,0,0,0));
}
/* Full above/below menu */
.frigate-card-menu-full {
@extend .frigate-card-menu-base;
.frigate-card-menu.full {
width: 100%;
background: var(--secondary-background-color);
}
@@ -44,7 +51,6 @@ ha-icon-button.button {
pointer-events: auto;
}
ha-icon-button.emphasized-button {
@extend ha-icon-button, .button;
ha-icon-button.button.emphasize {
color: var(--primary-color, white);
}
+4 -4
View File
@@ -102,15 +102,15 @@ webrtc-camera ha-card {
}
.frigate-media-controls.previous {
left: 20px;
left: 50px;
}
.frigate-media-controls.previous:hover {
left: 8px;
left: 38px;
}
.frigate-media-controls.next {
right: 20px;
right: 50px;
}
.frigate-media-controls.next:hover {
right: 8px;
right: 38px;
}
+30 -16
View File
@@ -14,6 +14,7 @@ import {
import { NodePart } from 'lit-html';
import { until } from 'lit-html/directives/until.js';
import { classMap } from 'lit-html/directives/class-map.js';
import {
HomeAssistant,
@@ -107,7 +108,7 @@ export class FrigateCardMenu extends LitElement {
static FRIGATE_CARD_MENU_ID: string = 'frigate-card-menu-id' as const;
@property({ attribute: false })
protected menuMode: FrigateMenuMode = 'hidden';
protected menuMode: FrigateMenuMode = 'hidden-top';
@property({ attribute: false })
protected expand = false;
@@ -120,7 +121,7 @@ export class FrigateCardMenu extends LitElement {
// Call the callback.
protected _callAction(name: string): void {
if (this.menuMode == 'hidden') {
if (this.menuMode.startsWith('hidden-')) {
if (name == 'frigate') {
this.expand = !this.expand;
return;
@@ -136,8 +137,13 @@ export class FrigateCardMenu extends LitElement {
// Render a menu button.
protected _renderButton(name: string, button: MenuButton): TemplateResult {
const classes = {
button: true,
emphasize: button.emphasize ?? false,
};
return html` <ha-icon-button
class=${button.emphasize ? 'emphasized-button' : 'button'}
class="${classMap(classes)}"
icon=${button.icon || 'mdi:gesture-tap-button'}
data-toggle="tooltip"
title=${button.description}
@@ -148,26 +154,34 @@ export class FrigateCardMenu extends LitElement {
// Render the Frigate menu button.
protected _renderFrigateButton(name: string, button: MenuButton): TemplateResult {
const icon =
this.menuMode != 'hidden' || this.expand
? 'mdi:alpha-f-box'
: 'mdi:alpha-f-box-outline';
this.menuMode.startsWith('hidden-') && !this.expand
? 'mdi:alpha-f-box-outline'
: 'mdi:alpha-f-box';
return this._renderButton(name, Object.assign({}, button, { icon: icon }));
}
// Render the menu.
protected render(): TemplateResult | void | ((part: NodePart) => Promise<void>) {
let menuClass = 'frigate-card-menu-full';
if (['hidden', 'overlay'].includes(this.menuMode)) {
if (this.menuMode == 'overlay' || this.expand) {
menuClass = 'frigate-card-menu-overlay';
} else {
menuClass = 'frigate-card-menu-hidden';
}
}
const classes = {
'frigate-card-menu': true,
'overlay-hidden':
this.menuMode.startsWith('hidden-') || this.menuMode.startsWith('overlay-'),
'expanded-horizontal':
(this.menuMode.startsWith('overlay-') || this.expand) &&
(this.menuMode.endsWith('-top') || this.menuMode.endsWith('-bottom')),
'expanded-vertical':
(this.menuMode.startsWith('overlay-') || this.expand) &&
(this.menuMode.endsWith('-left') || this.menuMode.endsWith('-right')),
full: ['above', 'below'].includes(this.menuMode),
left: this.menuMode.endsWith('-left'),
right: this.menuMode.endsWith('-right'),
top: this.menuMode.endsWith('-top'),
bottom: this.menuMode.endsWith('-bottom'),
};
return html`
<div class=${menuClass}>
<div class=${classMap(classes)}>
${Array.from(this.buttons.keys()).map((name) => {
const button = this.buttons.get(name);
if (button) {
@@ -523,7 +537,7 @@ export class FrigateCard extends LitElement {
outlined=""
class="frigate-card-image-list-folder"
>
<ha-icon .icon=${"mdi:arrow-left"}></ha-icon>
<ha-icon .icon=${'mdi:arrow-left'}></ha-icon>
</ha-card>
</div>
</div>
+9 -3
View File
@@ -25,8 +25,14 @@ export const FRIGATE_CARD_VIEWS = [
export type FrigateCardView = typeof FRIGATE_CARD_VIEWS[number];
export const FRIGATE_MENU_MODES = [
'hidden',
'overlay',
'hidden-top',
'hidden-left',
'hidden-bottom',
'hidden-right',
'overlay-top',
'overlay-left',
'overlay-bottom',
'overlay-right',
'above',
'below',
] as const;
@@ -55,7 +61,7 @@ export const frigateCardConfigSchema = z.object({
label: z.string().optional(),
zone: z.string().optional(),
autoplay_clip: z.boolean().default(false),
menu_mode: z.enum(FRIGATE_MENU_MODES).optional().default('hidden'),
menu_mode: z.enum(FRIGATE_MENU_MODES).optional().default('hidden-top'),
// Stock lovelace card config.
type: z.string(),