mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-17 14:26:35 +00:00
ha-form-multi_select accessibility improvements (#21023)
This commit is contained in:
parent
d4cbfd9583
commit
147098f0fd
@ -5,12 +5,14 @@ import { customElement, property, query, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import "../ha-button-menu";
|
||||
import "../ha-check-list-item";
|
||||
import type { HaCheckListItem } from "../ha-check-list-item";
|
||||
import "../ha-checkbox";
|
||||
import type { HaCheckbox } from "../ha-checkbox";
|
||||
import "../ha-formfield";
|
||||
import "../ha-svg-icon";
|
||||
import "../ha-icon-button";
|
||||
import "../ha-textfield";
|
||||
import "../ha-md-button-menu";
|
||||
import "../ha-md-menu-item";
|
||||
|
||||
import type {
|
||||
HaFormElement,
|
||||
HaFormMultiSelectData,
|
||||
@ -73,13 +75,10 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-button-menu
|
||||
<ha-md-button-menu
|
||||
.disabled=${this.disabled}
|
||||
fixed
|
||||
@opened=${this._handleOpen}
|
||||
@closed=${this._handleClose}
|
||||
multi
|
||||
activatable
|
||||
@opening=${this._handleOpen}
|
||||
@closing=${this._handleClose}
|
||||
>
|
||||
<ha-textfield
|
||||
slot="trigger"
|
||||
@ -94,28 +93,56 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
|
||||
.disabled=${this.disabled}
|
||||
tabindex="-1"
|
||||
></ha-textfield>
|
||||
<ha-svg-icon
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.label}
|
||||
.path=${this._opened ? mdiMenuUp : mdiMenuDown}
|
||||
></ha-svg-icon>
|
||||
></ha-icon-button>
|
||||
${options.map((item: string | [string, string]) => {
|
||||
const value = optionValue(item);
|
||||
const selected = data.includes(value);
|
||||
return html`<ha-check-list-item
|
||||
left
|
||||
.selected=${selected}
|
||||
.activated=${selected}
|
||||
@request-selected=${this._selectedChanged}
|
||||
return html`<ha-md-menu-item
|
||||
type="option"
|
||||
aria-checked=${selected}
|
||||
.value=${value}
|
||||
.disabled=${this.disabled}
|
||||
.action=${selected ? "remove" : "add"}
|
||||
.activated=${selected}
|
||||
@click=${this._toggleItem}
|
||||
@keydown=${this._keydown}
|
||||
keep-open
|
||||
>
|
||||
<ha-checkbox
|
||||
slot="start"
|
||||
tabindex="-1"
|
||||
.checked=${selected}
|
||||
></ha-checkbox>
|
||||
${optionLabel(item)}
|
||||
</ha-check-list-item>`;
|
||||
</ha-md-menu-item>`;
|
||||
})}
|
||||
</ha-button-menu>
|
||||
</ha-md-button-menu>
|
||||
`;
|
||||
}
|
||||
|
||||
protected _keydown(ev) {
|
||||
if (ev.code === "Space" || ev.code === "Enter") {
|
||||
ev.preventDefault();
|
||||
this._toggleItem(ev);
|
||||
}
|
||||
}
|
||||
|
||||
protected _toggleItem(ev) {
|
||||
const oldData = this.data || [];
|
||||
let newData: string[];
|
||||
if (ev.currentTarget.action === "add") {
|
||||
newData = [...oldData, ev.currentTarget.value];
|
||||
} else {
|
||||
newData = oldData.filter((d) => d !== ev.currentTarget.value);
|
||||
}
|
||||
fireEvent(this, "value-changed", {
|
||||
value: newData,
|
||||
});
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
this.updateComplete.then(() => {
|
||||
const { formElement, mdcRoot } =
|
||||
@ -139,17 +166,6 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _selectedChanged(ev: CustomEvent): void {
|
||||
ev.stopPropagation();
|
||||
if (ev.detail.source === "property") {
|
||||
return;
|
||||
}
|
||||
this._handleValueChanged(
|
||||
(ev.target as HaCheckListItem).value,
|
||||
ev.detail.selected
|
||||
);
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent): void {
|
||||
const { value, checked } = ev.target as HaCheckbox;
|
||||
this._handleValueChanged(value, checked);
|
||||
@ -195,7 +211,7 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
|
||||
:host([own-margin]) {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
ha-button-menu {
|
||||
ha-md-button-menu {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -208,22 +224,23 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
|
||||
}
|
||||
ha-textfield {
|
||||
display: block;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
ha-svg-icon {
|
||||
ha-icon-button {
|
||||
color: var(--input-dropdown-icon-color);
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
top: 4px;
|
||||
cursor: pointer;
|
||||
inset-inline-end: 1em;
|
||||
inset-inline-start: initial;
|
||||
direction: var(--direction);
|
||||
}
|
||||
:host([opened]) ha-svg-icon {
|
||||
:host([opened]) ha-icon-button {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
:host([opened]) ha-button-menu {
|
||||
:host([opened]) ha-md-button-menu {
|
||||
--mdc-text-field-idle-line-color: var(--input-hover-line-color);
|
||||
--mdc-text-field-label-ink-color: var(--primary-color);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { HaIconButton } from "./ha-icon-button";
|
||||
import "./ha-menu";
|
||||
import type { HaMenu } from "./ha-menu";
|
||||
@ -40,12 +41,22 @@ export class HaMdButtonMenu extends LitElement {
|
||||
<ha-menu
|
||||
.positioning=${this.positioning}
|
||||
.hasOverflow=${this.hasOverflow}
|
||||
@opening=${this._handleOpening}
|
||||
@closing=${this._handleClosing}
|
||||
>
|
||||
<slot></slot>
|
||||
</ha-menu>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleOpening(): void {
|
||||
fireEvent(this, "opening", undefined, { composed: false });
|
||||
}
|
||||
|
||||
private _handleClosing(): void {
|
||||
fireEvent(this, "closing", undefined, { composed: false });
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
@ -88,3 +99,10 @@ declare global {
|
||||
"ha-md-button-menu": HaMdButtonMenu;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HASSDomEvents {
|
||||
opening: undefined;
|
||||
closing: undefined;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user