mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-14 12:56:37 +00:00
Improve aria support in control elements
This commit is contained in:
parent
b60f2e3201
commit
0b45924d10
@ -135,7 +135,7 @@ export class DemoHaControlSelect extends LitElement {
|
||||
.options=${options}
|
||||
class=${ifDefined(config.class)}
|
||||
@value-changed=${this.handleValueChanged}
|
||||
aria-labelledby=${id}
|
||||
.label=${label}
|
||||
?disabled=${config.disabled}
|
||||
>
|
||||
</ha-control-select>
|
||||
@ -156,7 +156,7 @@ export class DemoHaControlSelect extends LitElement {
|
||||
vertical
|
||||
class=${ifDefined(config.class)}
|
||||
@value-changed=${this.handleValueChanged}
|
||||
aria-labelledby=${id}
|
||||
.label=${label}
|
||||
?disabled=${config.disabled}
|
||||
>
|
||||
</ha-control-select>
|
||||
|
@ -97,7 +97,7 @@ export class DemoHaBarSlider extends LitElement {
|
||||
class=${ifDefined(config.class)}
|
||||
@value-changed=${this.handleValueChanged}
|
||||
@slider-moved=${this.handleSliderMoved}
|
||||
aria-labelledby=${id}
|
||||
.label=${label}
|
||||
.unit=${config.unit}
|
||||
>
|
||||
</ha-control-slider>
|
||||
@ -119,7 +119,7 @@ export class DemoHaBarSlider extends LitElement {
|
||||
class=${ifDefined(config.class)}
|
||||
@value-changed=${this.handleValueChanged}
|
||||
@slider-moved=${this.handleSliderMoved}
|
||||
aria-label=${label}
|
||||
.label=${label}
|
||||
.unit=${config.unit}
|
||||
>
|
||||
</ha-control-slider>
|
||||
|
@ -63,7 +63,7 @@ export class DemoHaControlSwitch extends LitElement {
|
||||
@change=${this.handleValueChanged}
|
||||
.pathOn=${mdiLightbulb}
|
||||
.pathOff=${mdiLightbulbOff}
|
||||
aria-labelledby=${id}
|
||||
.label=${label}
|
||||
?disabled=${config.disabled}
|
||||
?reversed=${config.reversed}
|
||||
>
|
||||
@ -84,7 +84,7 @@ export class DemoHaControlSwitch extends LitElement {
|
||||
vertical
|
||||
class=${ifDefined(config.class)}
|
||||
@change=${this.handleValueChanged}
|
||||
aria-label=${label}
|
||||
.label=${label}
|
||||
.pathOn=${mdiGarageOpen}
|
||||
.pathOff=${mdiGarage}
|
||||
?disabled=${config.disabled}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import type { TemplateResult } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
@ -17,7 +17,7 @@ export interface ControlSelectOption {
|
||||
|
||||
@customElement("ha-control-select")
|
||||
export class HaControlSelect extends LitElement {
|
||||
@property({ type: Boolean, reflect: true }) disabled = false;
|
||||
@property({ type: Boolean }) disabled = false;
|
||||
|
||||
@property({ attribute: false }) public options?: ControlSelectOption[];
|
||||
|
||||
@ -26,58 +26,14 @@ export class HaControlSelect extends LitElement {
|
||||
@property({ type: Boolean, reflect: true })
|
||||
public vertical = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "hide-label" })
|
||||
public hideLabel = false;
|
||||
@property({ type: Boolean, attribute: "hide-option-label" })
|
||||
public hideOptionLabel = false;
|
||||
|
||||
@property({ type: String })
|
||||
public label?: string;
|
||||
|
||||
@state() private _activeIndex?: number;
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
this.setAttribute("role", "listbox");
|
||||
if (!this.hasAttribute("tabindex")) {
|
||||
this.setAttribute("tabindex", "0");
|
||||
}
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
if (changedProps.has("_activeIndex")) {
|
||||
const activeValue =
|
||||
this._activeIndex != null
|
||||
? this.options?.[this._activeIndex]?.value
|
||||
: undefined;
|
||||
const activedescendant =
|
||||
activeValue != null ? `option-${activeValue}` : undefined;
|
||||
this.setAttribute("aria-activedescendant", activedescendant ?? "");
|
||||
}
|
||||
if (changedProps.has("vertical")) {
|
||||
const orientation = this.vertical ? "vertical" : "horizontal";
|
||||
this.setAttribute("aria-orientation", orientation);
|
||||
}
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._setupListeners();
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this._destroyListeners();
|
||||
}
|
||||
|
||||
private _setupListeners() {
|
||||
this.addEventListener("focus", this._handleFocus);
|
||||
this.addEventListener("blur", this._handleBlur);
|
||||
this.addEventListener("keydown", this._handleKeydown);
|
||||
}
|
||||
|
||||
private _destroyListeners() {
|
||||
this.removeEventListener("focus", this._handleFocus);
|
||||
this.removeEventListener("blur", this._handleBlur);
|
||||
this.removeEventListener("keydown", this._handleKeydown);
|
||||
}
|
||||
|
||||
private _handleFocus() {
|
||||
if (this.disabled) return;
|
||||
this._activeIndex =
|
||||
@ -95,6 +51,7 @@ export class HaControlSelect extends LitElement {
|
||||
const value = this.options[this._activeIndex].value;
|
||||
switch (ev.key) {
|
||||
case " ":
|
||||
case "Enter":
|
||||
this.value = value;
|
||||
fireEvent(this, "value-changed", { value });
|
||||
break;
|
||||
@ -143,8 +100,26 @@ export class HaControlSelect extends LitElement {
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const activeValue =
|
||||
this._activeIndex != null
|
||||
? this.options?.[this._activeIndex]?.value
|
||||
: undefined;
|
||||
const activedescendant =
|
||||
activeValue != null ? `option-${activeValue}` : undefined;
|
||||
|
||||
return html`
|
||||
<div class="container">
|
||||
<div
|
||||
class="container"
|
||||
role="listbox"
|
||||
tabindex="0"
|
||||
aria-label=${ifDefined(this.label)}
|
||||
aria-orientation=${this.vertical ? "vertical" : "horizontal"}
|
||||
aria-activedescendant=${ifDefined(activedescendant)}
|
||||
@focus=${this._handleFocus}
|
||||
@blur=${this._handleBlur}
|
||||
@keydown=${this._handleKeydown}
|
||||
?disabled=${this.disabled}
|
||||
>
|
||||
${this.options
|
||||
? repeat(
|
||||
this.options,
|
||||
@ -167,7 +142,7 @@ export class HaControlSelect extends LitElement {
|
||||
})}
|
||||
role="option"
|
||||
.value=${option.value}
|
||||
aria-selected=${this.value === option.value}
|
||||
aria-selected=${this.value === option.value ? "true" : "false"}
|
||||
aria-label=${ifDefined(option.label)}
|
||||
title=${ifDefined(option.label)}
|
||||
@click=${this._handleOptionClick}
|
||||
@ -178,7 +153,7 @@ export class HaControlSelect extends LitElement {
|
||||
${option.path
|
||||
? html`<ha-svg-icon .path=${option.path}></ha-svg-icon>`
|
||||
: option.icon || nothing}
|
||||
${option.label && !this.hideLabel
|
||||
${option.label && !this.hideOptionLabel
|
||||
? html`<span>${option.label}</span>`
|
||||
: nothing}
|
||||
</div>
|
||||
@ -203,18 +178,12 @@ export class HaControlSelect extends LitElement {
|
||||
--mdc-icon-size: 20px;
|
||||
height: var(--control-select-thickness);
|
||||
width: 100%;
|
||||
border-radius: var(--control-select-border-radius);
|
||||
outline: none;
|
||||
transition: box-shadow 180ms ease-in-out;
|
||||
font-style: normal;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
color: var(--primary-text-color);
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
:host(:focus-visible) {
|
||||
box-shadow: 0 0 0 2px var(--control-select-color);
|
||||
}
|
||||
:host([vertical]) {
|
||||
width: var(--control-select-thickness);
|
||||
height: 100%;
|
||||
@ -230,6 +199,8 @@ export class HaControlSelect extends LitElement {
|
||||
flex-direction: row;
|
||||
padding: var(--control-select-padding);
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
transition: box-shadow 180ms ease-in-out;
|
||||
}
|
||||
.container::before {
|
||||
position: absolute;
|
||||
@ -248,6 +219,20 @@ export class HaControlSelect extends LitElement {
|
||||
margin-inline-start: initial;
|
||||
direction: var(--direction);
|
||||
}
|
||||
.container[disabled] {
|
||||
--control-select-color: var(--disabled-color);
|
||||
--control-select-focused-opacity: 0;
|
||||
color: var(--disabled-color);
|
||||
}
|
||||
|
||||
.container[disabled] .option {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.container:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--control-select-color);
|
||||
}
|
||||
|
||||
.option {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
@ -319,14 +304,6 @@ export class HaControlSelect extends LitElement {
|
||||
margin-inline-end: initial;
|
||||
margin-bottom: var(--control-select-padding);
|
||||
}
|
||||
:host([disabled]) {
|
||||
--control-select-color: var(--disabled-color);
|
||||
--control-select-focused-opacity: 0;
|
||||
color: var(--disabled-color);
|
||||
}
|
||||
:host([disabled]) .option {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,12 @@ import type { PropertyValues, TemplateResult } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { FrontendLocaleData } from "../data/translation";
|
||||
import { formatNumber } from "../common/number/format_number";
|
||||
import { blankBeforeUnit } from "../common/translations/blank_before_unit";
|
||||
import type { FrontendLocaleData } from "../data/translation";
|
||||
|
||||
declare global {
|
||||
interface HASSDomEvents {
|
||||
@ -75,6 +76,9 @@ export class HaControlSlider extends LitElement {
|
||||
@property({ type: Number })
|
||||
public max = 100;
|
||||
|
||||
@property({ type: String })
|
||||
public label?: string;
|
||||
|
||||
@state()
|
||||
public pressed = false;
|
||||
|
||||
@ -107,10 +111,6 @@ export class HaControlSlider extends LitElement {
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
this.setupListeners();
|
||||
this.setAttribute("role", "slider");
|
||||
if (!this.hasAttribute("tabindex")) {
|
||||
this.setAttribute("tabindex", "0");
|
||||
}
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
@ -197,9 +197,6 @@ export class HaControlSlider extends LitElement {
|
||||
this.value = this.steppedValue(this.percentageToValue(percentage));
|
||||
fireEvent(this, "value-changed", { value: this.value });
|
||||
});
|
||||
|
||||
this.addEventListener("keydown", this._handleKeyDown);
|
||||
this.addEventListener("keyup", this._handleKeyUp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,8 +205,6 @@ export class HaControlSlider extends LitElement {
|
||||
this._mc.destroy();
|
||||
this._mc = undefined;
|
||||
}
|
||||
this.removeEventListener("keydown", this._handleKeyDown);
|
||||
this.removeEventListener("keyup", this._handleKeyUp);
|
||||
}
|
||||
|
||||
private get _tenPercentStep() {
|
||||
@ -323,6 +318,7 @@ export class HaControlSlider extends LitElement {
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const valuenow = this.steppedValue(this.value ?? 0);
|
||||
return html`
|
||||
<div
|
||||
class="container${classMap({
|
||||
@ -332,7 +328,24 @@ export class HaControlSlider extends LitElement {
|
||||
"--value": `${this.valueToPercentage(this.value ?? 0)}`,
|
||||
})}
|
||||
>
|
||||
<div id="slider" class="slider">
|
||||
<div
|
||||
id="slider"
|
||||
class="slider"
|
||||
role="slider"
|
||||
tabindex="0"
|
||||
aria-label=${ifDefined(this.label)}
|
||||
aria-valuenow=${valuenow.toString()}
|
||||
aria-valuetext=${this._formatValue(valuenow)}
|
||||
aria-valuemin=${ifDefined(
|
||||
this.min != null ? this.min.toString() : undefined
|
||||
)}
|
||||
aria-valuemax=${ifDefined(
|
||||
this.max != null ? this.max.toString() : undefined
|
||||
)}
|
||||
aria-orientation=${this.vertical ? "vertical" : "horizontal"}
|
||||
@keydown=${this._handleKeyDown}
|
||||
@keyup=${this._handleKeyUp}
|
||||
>
|
||||
<div class="slider-track-background"></div>
|
||||
<slot name="background"></slot>
|
||||
${this.mode === "cursor"
|
||||
@ -371,12 +384,6 @@ export class HaControlSlider extends LitElement {
|
||||
--control-slider-tooltip-font-size: var(--ha-font-size-m);
|
||||
height: var(--control-slider-thickness);
|
||||
width: 100%;
|
||||
border-radius: var(--control-slider-border-radius);
|
||||
outline: none;
|
||||
transition: box-shadow 180ms ease-in-out;
|
||||
}
|
||||
:host(:focus-visible) {
|
||||
box-shadow: 0 0 0 2px var(--control-slider-color);
|
||||
}
|
||||
:host([vertical]) {
|
||||
width: var(--control-slider-thickness);
|
||||
@ -471,9 +478,14 @@ export class HaControlSlider extends LitElement {
|
||||
width: 100%;
|
||||
border-radius: var(--control-slider-border-radius);
|
||||
transform: translateZ(0);
|
||||
transition: box-shadow 180ms ease-in-out;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
.slider:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--control-slider-color);
|
||||
}
|
||||
.slider * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -9,18 +9,19 @@ import {
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import "./ha-svg-icon";
|
||||
|
||||
@customElement("ha-control-switch")
|
||||
export class HaControlSwitch extends LitElement {
|
||||
@property({ type: Boolean, reflect: true }) public disabled = false;
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@property({ type: Boolean }) public vertical = false;
|
||||
|
||||
@property({ type: Boolean }) public reversed = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public checked = false;
|
||||
@property({ type: Boolean }) public checked = false;
|
||||
|
||||
// SVG icon path (if you need a non SVG icon instead, use the provided on icon slot to pass an <ha-icon slot="icon-on"> in)
|
||||
@property({ attribute: false, type: String }) pathOn?: string;
|
||||
@ -28,6 +29,9 @@ export class HaControlSwitch extends LitElement {
|
||||
// SVG icon path (if you need a non SVG icon instead, use the provided off icon slot to pass an <ha-icon slot="icon-off"> in)
|
||||
@property({ attribute: false, type: String }) pathOff?: string;
|
||||
|
||||
@property({ type: String })
|
||||
public label?: string;
|
||||
|
||||
@property({ attribute: "touch-action" })
|
||||
public touchAction?: string;
|
||||
|
||||
@ -36,17 +40,6 @@ export class HaControlSwitch extends LitElement {
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
this.setupListeners();
|
||||
this.setAttribute("role", "switch");
|
||||
if (!this.hasAttribute("tabindex")) {
|
||||
this.setAttribute("tabindex", "0");
|
||||
}
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
if (changedProps.has("checked")) {
|
||||
this.setAttribute("aria-checked", this.checked ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
private _toggle() {
|
||||
@ -112,8 +105,6 @@ export class HaControlSwitch extends LitElement {
|
||||
if (this.disabled) return;
|
||||
this._toggle();
|
||||
});
|
||||
|
||||
this.addEventListener("keydown", this._keydown);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +113,6 @@ export class HaControlSwitch extends LitElement {
|
||||
this._mc.destroy();
|
||||
this._mc = undefined;
|
||||
}
|
||||
this.removeEventListener("keydown", this._keydown);
|
||||
}
|
||||
|
||||
private _keydown(ev: any) {
|
||||
@ -135,7 +125,18 @@ export class HaControlSwitch extends LitElement {
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div id="switch" class="switch">
|
||||
<div
|
||||
id="switch"
|
||||
class="switch"
|
||||
@keydown=${this._keydown}
|
||||
aria-checked=${this.checked ? "true" : "false"}
|
||||
aria-label=${ifDefined(this.label)}
|
||||
@click=${this._toggle}
|
||||
role="switch"
|
||||
tabindex="0"
|
||||
?checked=${this.checked}
|
||||
?disabled=${this.disabled}
|
||||
>
|
||||
<div class="background"></div>
|
||||
<div class="button" aria-hidden="true">
|
||||
${this.checked
|
||||
@ -164,16 +165,13 @@ export class HaControlSwitch extends LitElement {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
border-radius: var(--control-switch-border-radius);
|
||||
outline: none;
|
||||
transition: box-shadow 180ms ease-in-out;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
:host(:focus-visible) {
|
||||
.switch:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--control-switch-off-color);
|
||||
}
|
||||
:host([checked]:focus-visible) {
|
||||
.switch[checked]:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--control-switch-on-color);
|
||||
}
|
||||
.switch {
|
||||
@ -182,9 +180,15 @@ export class HaControlSwitch extends LitElement {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: var(--control-switch-border-radius);
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
padding: var(--control-switch-padding);
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
.switch[disabled] {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.switch .background {
|
||||
position: absolute;
|
||||
@ -212,24 +216,24 @@ export class HaControlSwitch extends LitElement {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
:host([checked]) .switch .background {
|
||||
.switch[checked] .background {
|
||||
background-color: var(--control-switch-on-color);
|
||||
}
|
||||
:host([checked]) .switch .button {
|
||||
.switch[checked] .button {
|
||||
transform: translateX(100%);
|
||||
background-color: var(--control-switch-on-color);
|
||||
}
|
||||
:host([reversed]) .switch {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
:host([reversed][checked]) .switch .button {
|
||||
:host([reversed]) .switch[checked] .button {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
:host([vertical]) {
|
||||
width: var(--control-switch-thickness);
|
||||
height: 100%;
|
||||
}
|
||||
:host([vertical][checked]) .switch .button {
|
||||
:host([vertical]) .switch[checked] .button {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
:host([vertical]) .switch .button {
|
||||
@ -239,13 +243,9 @@ export class HaControlSwitch extends LitElement {
|
||||
:host([vertical][reversed]) .switch {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
:host([vertical][reversed][checked]) .switch .button {
|
||||
:host([vertical][reversed]) .switch[checked] .button {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
:host([disabled]) {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ class LightColorTempPicker extends LitElement {
|
||||
mode="cursor"
|
||||
@value-changed=${this._ctColorChanged}
|
||||
@slider-moved=${this._ctColorCursorMoved}
|
||||
.ariaLabel=${this.hass.localize(
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.light.color_temp"
|
||||
)}
|
||||
style=${styleMap({
|
||||
|
@ -174,10 +174,8 @@ class HuiAlarmModeCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass.localize(
|
||||
"ui.card.alarm_control_panel.modes_label"
|
||||
)}
|
||||
hide-option-label
|
||||
.label=${this.hass.localize("ui.card.alarm_control_panel.modes_label")}
|
||||
style=${styleMap({
|
||||
"--control-select-color": color,
|
||||
"--modes-count": options.length.toString(),
|
||||
|
@ -174,11 +174,8 @@ class HuiClimateFanModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentFanMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass!.formatEntityAttributeName(
|
||||
stateObj,
|
||||
"fan_mode"
|
||||
)}
|
||||
hide-option-label
|
||||
.label=${this.hass!.formatEntityAttributeName(stateObj, "fan_mode")}
|
||||
.disabled=${this._stateObj!.state === UNAVAILABLE}
|
||||
>
|
||||
</ha-control-select>
|
||||
|
@ -205,8 +205,8 @@ class HuiClimateHvacModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentHvacMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass.localize("ui.card.climate.mode")}
|
||||
hide-option-label
|
||||
.label=${this.hass.localize("ui.card.climate.mode")}
|
||||
style=${styleMap({
|
||||
"--control-select-color": color,
|
||||
})}
|
||||
|
@ -176,8 +176,8 @@ class HuiClimatePresetModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentPresetMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass!.formatEntityAttributeName(
|
||||
hide-option-label
|
||||
.label=${this.hass!.formatEntityAttributeName(
|
||||
stateObj,
|
||||
"preset_mode"
|
||||
)}
|
||||
|
@ -178,8 +178,8 @@ class HuiClimateSwingHorizontalModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentSwingHorizontalMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass!.formatEntityAttributeName(
|
||||
hide-option-label
|
||||
.label=${this.hass!.formatEntityAttributeName(
|
||||
stateObj,
|
||||
"swing_horizontal_mode"
|
||||
)}
|
||||
|
@ -176,7 +176,7 @@ class HuiClimateSwingModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentSwingMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
hide-option-label
|
||||
.ariaLabel=${this.hass!.formatEntityAttributeName(
|
||||
stateObj,
|
||||
"swing_mode"
|
||||
|
@ -106,7 +106,7 @@ class HuiCoverPositionCardFeature
|
||||
inverted
|
||||
show-handle
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this._stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -105,7 +105,7 @@ class HuiCoverTiltPositionCardFeature
|
||||
mode="cursor"
|
||||
inverted
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this._stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -170,8 +170,8 @@ class HuiFanPresetModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentPresetMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass!.formatEntityAttributeName(
|
||||
hide-option-label
|
||||
.label=${this.hass!.formatEntityAttributeName(
|
||||
stateObj,
|
||||
"preset_mode"
|
||||
)}
|
||||
|
@ -109,8 +109,8 @@ class HuiFanSpeedCardFeature extends LitElement implements LovelaceCardFeature {
|
||||
.options=${options}
|
||||
.value=${speed}
|
||||
@value-changed=${this._speedValueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
hide-option-label
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this._stateObj,
|
||||
this.hass.entities,
|
||||
@ -131,7 +131,7 @@ class HuiFanSpeedCardFeature extends LitElement implements LovelaceCardFeature {
|
||||
max="100"
|
||||
.step=${this._stateObj.attributes.percentage_step ?? 1}
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this._stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -174,8 +174,8 @@ class HuiHumidifierModesCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass!.formatEntityAttributeName(stateObj, "mode")}
|
||||
hide-option-label
|
||||
.label=${this.hass!.formatEntityAttributeName(stateObj, "mode")}
|
||||
.disabled=${this._stateObj!.state === UNAVAILABLE}
|
||||
>
|
||||
</ha-control-select>
|
||||
|
@ -130,8 +130,8 @@ class HuiHumidifierToggleCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentState}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass.localize("ui.card.humidifier.state")}
|
||||
hide-option-label
|
||||
.label=${this.hass.localize("ui.card.humidifier.state")}
|
||||
style=${styleMap({
|
||||
"--control-select-color": color,
|
||||
})}
|
||||
|
@ -185,7 +185,7 @@ class HuiToggleCardFeature extends LitElement implements LovelaceCardFeature {
|
||||
.pathOff=${offIcon}
|
||||
.checked=${isOn}
|
||||
@change=${this._valueChanged}
|
||||
.ariaLabel=${this.hass.localize("ui.card.common.toggle")}
|
||||
.label=${this.hass.localize("ui.card.common.toggle")}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
>
|
||||
</ha-control-switch>
|
||||
|
@ -151,8 +151,8 @@ class HuiWaterHeaterOperationModeCardFeature
|
||||
.options=${options}
|
||||
.value=${this._currentOperationMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass.localize("ui.card.water_heater.mode")}
|
||||
hide-option-label
|
||||
.label=${this.hass.localize("ui.card.water_heater.mode")}
|
||||
style=${styleMap({
|
||||
"--control-select-color": color,
|
||||
})}
|
||||
|
@ -87,9 +87,7 @@ export class HaStateControlAlarmControlPanelModes extends LitElement {
|
||||
.options=${options}
|
||||
.value=${this._currentMode}
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${this.hass.localize(
|
||||
"ui.card.alarm_control_panel.modes_label"
|
||||
)}
|
||||
.label=${this.hass.localize("ui.card.alarm_control_panel.modes_label")}
|
||||
style=${styleMap({
|
||||
"--control-select-color": color,
|
||||
"--modes-count": modes.length.toString(),
|
||||
|
@ -50,7 +50,7 @@ export class HaStateControlCoverPosition extends LitElement {
|
||||
show-handle
|
||||
mode="end"
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -79,7 +79,7 @@ export class HaStateControlInfoCoverTiltPosition extends LitElement {
|
||||
max="100"
|
||||
mode="cursor"
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -112,7 +112,7 @@ export class HaStateControlCoverToggle extends LitElement {
|
||||
reversed
|
||||
.checked=${isOn}
|
||||
@change=${this._valueChanged}
|
||||
.ariaLabel=${isOn
|
||||
.label=${isOn
|
||||
? this.hass.localize("ui.card.cover.close_cover")
|
||||
: this.hass.localize("ui.card.cover.open_cover")}
|
||||
style=${styleMap({
|
||||
|
@ -92,7 +92,7 @@ export class HaStateControlFanSpeed extends LitElement {
|
||||
.options=${options}
|
||||
.value=${this.speedValue}
|
||||
@value-changed=${this._speedValueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
@ -117,7 +117,7 @@ export class HaStateControlFanSpeed extends LitElement {
|
||||
.value=${this.sliderValue}
|
||||
.step=${this.stateObj.attributes.percentage_step ?? 1}
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -117,7 +117,7 @@ export class HaStateControlToggle extends LitElement {
|
||||
.checked=${isOn}
|
||||
.showHandle=${stateActive(this.stateObj)}
|
||||
@change=${this._valueChanged}
|
||||
.ariaLabel=${this.hass.localize("ui.card.common.toggle")}
|
||||
.label=${this.hass.localize("ui.card.common.toggle")}
|
||||
style=${styleMap({
|
||||
"--control-switch-on-color": onColor,
|
||||
"--control-switch-off-color": offColor,
|
||||
|
@ -67,7 +67,7 @@ export class HaStateControlLightBrightness extends LitElement {
|
||||
max="100"
|
||||
.showHandle=${stateActive(this.stateObj)}
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${this.hass.formatEntityAttributeName(
|
||||
.label=${this.hass.formatEntityAttributeName(
|
||||
this.stateObj,
|
||||
"brightness"
|
||||
)}
|
||||
|
@ -118,7 +118,7 @@ export class HaStateControlLockToggle extends LitElement {
|
||||
reversed
|
||||
.checked=${this._isOn}
|
||||
@change=${this._valueChanged}
|
||||
.ariaLabel=${this._isOn
|
||||
.label=${this._isOn
|
||||
? this.hass.localize("ui.card.lock.unlock")
|
||||
: this.hass.localize("ui.card.lock.lock")}
|
||||
style=${styleMap({
|
||||
|
@ -48,7 +48,7 @@ export class HaStateControlValvePosition extends LitElement {
|
||||
max="100"
|
||||
show-handle
|
||||
@value-changed=${this._valueChanged}
|
||||
.ariaLabel=${computeAttributeNameDisplay(
|
||||
.label=${computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this.stateObj,
|
||||
this.hass.entities,
|
||||
|
@ -112,7 +112,7 @@ export class HaStateControlValveToggle extends LitElement {
|
||||
reversed
|
||||
.checked=${isOn}
|
||||
@change=${this._valueChanged}
|
||||
.ariaLabel=${isOn
|
||||
.label=${isOn
|
||||
? this.hass.localize("ui.card.valve.close_valve")
|
||||
: this.hass.localize("ui.card.valve.open_valve")}
|
||||
style=${styleMap({
|
||||
|
Loading…
x
Reference in New Issue
Block a user