Improve title & accessibility label support.
This commit is contained in:
@@ -164,9 +164,10 @@ export class FrigateCardGalleryCore extends LitElement {
|
||||
</div>`
|
||||
: child.thumbnail
|
||||
? html`<img
|
||||
title="${child.title}"
|
||||
aria-label="${child.title}"
|
||||
class="mdc-image-list__image"
|
||||
src="${child.thumbnail}"
|
||||
title="${child.title}"
|
||||
@click=${() => {
|
||||
if (this.view) {
|
||||
this.view
|
||||
|
||||
+15
-6
@@ -1,3 +1,4 @@
|
||||
// TODO clip autoplay not working as expected
|
||||
// TODO verify README links worked correctly (e.g. basic cameras configuration)
|
||||
|
||||
import {
|
||||
@@ -388,11 +389,11 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
|
||||
|
||||
return html` <div class="embla__slide">
|
||||
<frigate-card-live-provider
|
||||
.title=${getCameraTitle(this.hass, cameraConfig)}
|
||||
.hass=${this.hass}
|
||||
.cameraConfig=${cameraConfig}
|
||||
.liveConfig=${config}
|
||||
?disabled=${this._isLazyLoading()}
|
||||
.cameraConfig=${cameraConfig}
|
||||
.label=${getCameraTitle(this.hass, cameraConfig)}
|
||||
.liveConfig=${config}
|
||||
.hass=${this.hass}
|
||||
@frigate-card:media-show=${(e: CustomEvent<MediaShowInfo>) =>
|
||||
this._mediaShowEventHandler(slideIndex, e)}
|
||||
>
|
||||
@@ -470,7 +471,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
|
||||
${ref(this._previousControlRef)}
|
||||
.direction=${'previous'}
|
||||
.controlConfig=${config.controls.next_previous}
|
||||
.title=${getCameraTitle(this.hass, prev)}
|
||||
.label=${getCameraTitle(this.hass, prev)}
|
||||
.icon=${getCameraIcon(this.hass, prev)}
|
||||
?disabled=${prev == null}
|
||||
@click=${() => {
|
||||
@@ -485,7 +486,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
|
||||
${ref(this._nextControlRef)}
|
||||
.direction=${'next'}
|
||||
.controlConfig=${config.controls.next_previous}
|
||||
.title=${getCameraTitle(this.hass, next)}
|
||||
.label=${getCameraTitle(this.hass, next)}
|
||||
.icon=${getCameraIcon(this.hass, next)}
|
||||
?disabled=${next == null}
|
||||
@click=${() => {
|
||||
@@ -514,6 +515,10 @@ export class FrigateCardLiveProvider extends LitElement {
|
||||
@property({ attribute: true, type: Boolean })
|
||||
public disabled = false;
|
||||
|
||||
// Label that is used for ARIA support and as tooltip.
|
||||
@property({ attribute: false })
|
||||
public label = "";
|
||||
|
||||
protected _getResolvedProvider(): LiveProvider {
|
||||
if (this.cameraConfig?.live_provider === 'auto') {
|
||||
if (this.cameraConfig?.webrtc?.entity || this.cameraConfig?.webrtc?.url) {
|
||||
@@ -537,6 +542,10 @@ export class FrigateCardLiveProvider extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set title and ariaLabel from the provided label property.
|
||||
this.title = this.label;
|
||||
this.ariaLabel = this.label;
|
||||
|
||||
const provider = this._getResolvedProvider();
|
||||
|
||||
return html`
|
||||
|
||||
+4
-10
@@ -1,4 +1,4 @@
|
||||
import { HomeAssistant, handleAction, hasAction } from 'custom-card-helpers';
|
||||
import { HASSDomEvent, HomeAssistant, handleAction, hasAction } from 'custom-card-helpers';
|
||||
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
@@ -65,7 +65,7 @@ export class FrigateCardMenu extends LitElement {
|
||||
* @param button The button configuration.
|
||||
*/
|
||||
protected _actionHandler(
|
||||
ev: CustomEvent<{ action: string; config?: Actions }>,
|
||||
ev: HASSDomEvent<{ action: string; config?: Actions }>,
|
||||
config?: Actions,
|
||||
): void {
|
||||
if (!ev) {
|
||||
@@ -152,21 +152,15 @@ export class FrigateCardMenu extends LitElement {
|
||||
button: true,
|
||||
};
|
||||
|
||||
// TODO: Upon a safe distance from the release of HA 2021.11 these
|
||||
// attributes can be removed from the <ha-icon-button>.
|
||||
// - icon (replaced with the embedded <ha-icon>)
|
||||
// - title (replaced with .label)
|
||||
return html` <ha-icon-button
|
||||
class="${classMap(classes)}"
|
||||
style="${styleMap(stateParameters.style || {})}"
|
||||
icon=${stateParameters.icon || 'mdi:gesture-tap-button'}
|
||||
.label=${stateParameters.title || ''}
|
||||
title=${stateParameters.title || ''}
|
||||
@action=${(ev) => this._actionHandler(ev, button)}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasHold,
|
||||
hasDoubleClick: hasDoubleClick,
|
||||
})}
|
||||
.label=${stateParameters.title || ''}
|
||||
@action=${(ev) => this._actionHandler(ev, button)}
|
||||
>
|
||||
<ha-icon icon="${stateParameters.icon || 'mdi:gesture-tap-button'}"></ha-icon>
|
||||
</ha-icon-button>`;
|
||||
|
||||
@@ -30,6 +30,9 @@ export class FrigateCardNextPreviousControl extends LitElement {
|
||||
@property({ attribute: true, type: Boolean })
|
||||
public disabled = false;
|
||||
|
||||
// Label that is used for ARIA support and as tooltip.
|
||||
@property() label = "";
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this.disabled || !this._controlConfig || this._controlConfig.style == 'none') {
|
||||
return html``;
|
||||
@@ -55,15 +58,9 @@ export class FrigateCardNextPreviousControl extends LitElement {
|
||||
icon = this.icon
|
||||
}
|
||||
|
||||
// TODO: Upon a safe distance from the release of HA 2021.11 these
|
||||
// attributes can be removed from the <ha-icon-button>.
|
||||
// - icon (replaced with the embedded <ha-icon>)
|
||||
// - title (replaced with .label)
|
||||
return html` <ha-icon-button
|
||||
icon=${icon}
|
||||
class="${classMap(classes)}"
|
||||
.label=${this.title}
|
||||
title=${this.title}
|
||||
.label=${this.label}
|
||||
>
|
||||
<ha-icon icon=${icon}></ha-icon>
|
||||
</ha-icon-button>`;
|
||||
@@ -75,7 +72,8 @@ export class FrigateCardNextPreviousControl extends LitElement {
|
||||
return html`<img
|
||||
src="${this.thumbnail}"
|
||||
class="${classMap(classes)}"
|
||||
title="${this.title}"
|
||||
title="${this.label}"
|
||||
aria-label="${this.label}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export class FrigateCardThumbnailCarousel extends FrigateCardCarousel {
|
||||
@property({ attribute: false })
|
||||
set config(config: ThumbnailsControlConfig | undefined) {
|
||||
if (config) {
|
||||
if (config && (config.size !== undefined && config.size !== null)) {
|
||||
if (config && config.size !== undefined && config.size !== null) {
|
||||
this.style.setProperty('--frigate-card-carousel-thumbnail-size', config.size);
|
||||
}
|
||||
this._config = config;
|
||||
@@ -35,7 +35,10 @@ export class FrigateCardThumbnailCarousel extends FrigateCardCarousel {
|
||||
|
||||
@property({ attribute: false })
|
||||
set highlightSelected(value: boolean) {
|
||||
this.style.setProperty('--frigate-card-carousel-thumbnail-opacity', value ? '0.6' : '1.0');
|
||||
this.style.setProperty(
|
||||
'--frigate-card-carousel-thumbnail-opacity',
|
||||
value ? '0.6' : '1.0',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,10 +82,7 @@ export class FrigateCardThumbnailCarousel extends FrigateCardCarousel {
|
||||
|
||||
const slides: TemplateResult[] = [];
|
||||
for (let i = 0; i < this.target.children.length; ++i) {
|
||||
const thumbnail = this._renderThumbnail(
|
||||
this.target,
|
||||
i,
|
||||
slides.length);
|
||||
const thumbnail = this._renderThumbnail(this.target, i, slides.length);
|
||||
if (thumbnail) {
|
||||
slides.push(thumbnail);
|
||||
}
|
||||
@@ -121,7 +121,11 @@ export class FrigateCardThumbnailCarousel extends FrigateCardCarousel {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<img src="${mediaToRender.thumbnail}" title="${mediaToRender.title}" />
|
||||
<img
|
||||
aria-label="${mediaToRender.title}"
|
||||
src="${mediaToRender.thumbnail}"
|
||||
title="${mediaToRender.title}"
|
||||
/>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -601,7 +601,7 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
|
||||
.direction=${'previous'}
|
||||
.controlConfig=${this.viewerConfig?.controls.next_previous}
|
||||
.thumbnail=${prev && prev.thumbnail ? prev.thumbnail : undefined}
|
||||
.title=${prev ? prev.title : ''}
|
||||
.label=${prev ? prev.title : ''}
|
||||
?disabled=${!prev}
|
||||
@click=${() => {
|
||||
this._nextPreviousHandler('previous');
|
||||
@@ -615,7 +615,7 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
|
||||
.direction=${'next'}
|
||||
.controlConfig=${this.viewerConfig?.controls.next_previous}
|
||||
.thumbnail=${next && next.thumbnail ? next.thumbnail : undefined}
|
||||
.title=${next ? next.title : ''}
|
||||
.label=${next ? next.title : ''}
|
||||
?disabled=${!next}
|
||||
@click=${() => {
|
||||
this._nextPreviousHandler('next');
|
||||
@@ -657,19 +657,21 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
|
||||
<div class="embla__slide">
|
||||
${this.view.isClipRelatedView()
|
||||
? html`<frigate-card-ha-hls-player
|
||||
.hass=${this.hass}
|
||||
url=${ifDefined(lazyLoad ? undefined : resolvedMedia?.url)}
|
||||
title="${mediaToRender.title}"
|
||||
muted
|
||||
controls
|
||||
playsinline
|
||||
allow-exoplayer
|
||||
?autoplay="${autoplay}"
|
||||
aria-label="${mediaToRender.title}"
|
||||
controls
|
||||
muted
|
||||
playsinline
|
||||
title="${mediaToRender.title}"
|
||||
url=${ifDefined(lazyLoad ? undefined : resolvedMedia?.url)}
|
||||
.hass=${this.hass}
|
||||
@frigate-card:media-show=${(e: CustomEvent<MediaShowInfo>) =>
|
||||
this._mediaShowEventHandler(slideIndex, e)}
|
||||
>
|
||||
</frigate-card-ha-hls-player>`
|
||||
: html`<img
|
||||
aria-label="${mediaToRender.title}"
|
||||
src=${ifDefined(lazyLoad ? IMG_EMPTY : resolvedMedia?.url)}
|
||||
title="${mediaToRender.title}"
|
||||
@click=${() => {
|
||||
|
||||
@@ -48,10 +48,6 @@ customElements.whenDefined('ha-camera-stream').then(() => {
|
||||
? html`
|
||||
<img
|
||||
@load=${(e) => {
|
||||
// TODO: This block can be removed a safe distance from HA 2021.11.
|
||||
if (typeof this._elementResized != 'undefined') {
|
||||
this._elementResized();
|
||||
}
|
||||
dispatchMediaShowEvent(this, e);
|
||||
}}
|
||||
.src=${typeof this._connected == 'undefined' || this._connected
|
||||
|
||||
@@ -34,10 +34,6 @@ customElements.whenDefined('ha-hls-player').then(() => {
|
||||
?playsinline=${this.playsInline}
|
||||
?controls=${this.controls}
|
||||
@loadeddata=${(e) => {
|
||||
// TODO: This block can be removed a safe distance from HA 2021.11.
|
||||
if (typeof this._elementResized != 'undefined') {
|
||||
this._elementResized();
|
||||
}
|
||||
dispatchMediaShowEvent(this, e);
|
||||
}}
|
||||
@pause=${() => dispatchPauseEvent(this)}
|
||||
|
||||
Reference in New Issue
Block a user