Adjust check focus behaviour for todo list (#19472)

* Adjust check focus behaviour for todo list

* improve aria
This commit is contained in:
Bram Kragten 2024-01-22 13:58:35 +01:00 committed by GitHub
parent 10ad0010cf
commit bf4b76864d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -224,95 +224,98 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
` `
: nothing} : nothing}
</div> </div>
${uncheckedItems.length <ha-sortable
? html`<div class="header"> handle-selector="ha-svg-icon"
<span> draggable-selector=".draggable"
${this.hass!.localize( .disabled=${!this._reordering}
"ui.panel.lovelace.cards.todo-list.unchecked_items" @item-moved=${this._itemMoved}
)} >
</span> <mwc-list wrapFocus multi>
${this.todoListSupportsFeature( ${uncheckedItems.length
TodoListEntityFeature.MOVE_TODO_ITEM ? html`
) <div class="header" role="seperator">
? html`<ha-button-menu> <h2>
<ha-icon-button ${this.hass!.localize(
slot="trigger" "ui.panel.lovelace.cards.todo-list.unchecked_items"
.path=${mdiDotsVertical} )}
></ha-icon-button> </h2>
<ha-list-item ${this.todoListSupportsFeature(
@click=${this._toggleReorder} TodoListEntityFeature.MOVE_TODO_ITEM
graphic="icon" )
> ? html`<ha-button-menu>
${this.hass!.localize( <ha-icon-button
this._reordering slot="trigger"
? "ui.panel.lovelace.cards.todo-list.exit_reorder_items" .path=${mdiDotsVertical}
: "ui.panel.lovelace.cards.todo-list.reorder_items" ></ha-icon-button>
)} <ha-list-item
<ha-svg-icon @click=${this._toggleReorder}
slot="graphic" graphic="icon"
.path=${mdiSort} >
.disabled=${unavailable} ${this.hass!.localize(
> this._reordering
</ha-svg-icon> ? "ui.panel.lovelace.cards.todo-list.exit_reorder_items"
</ha-list-item> : "ui.panel.lovelace.cards.todo-list.reorder_items"
</ha-button-menu>` )}
: nothing} <ha-svg-icon
</div> slot="graphic"
<ha-sortable .path=${mdiSort}
handle-selector="ha-svg-icon" .disabled=${unavailable}
.disabled=${!this._reordering} >
@item-moved=${this._itemMoved} </ha-svg-icon>
> </ha-list-item>
<mwc-list id="unchecked"> </ha-button-menu>`
: nothing}
</div>
${this._renderItems(uncheckedItems, unavailable)} ${this._renderItems(uncheckedItems, unavailable)}
</mwc-list> `
</ha-sortable>` : html`<p class="empty">
: html`<p class="empty"> ${this.hass.localize(
${this.hass.localize( "ui.panel.lovelace.cards.todo-list.no_unchecked_items"
"ui.panel.lovelace.cards.todo-list.no_unchecked_items"
)}
</p>`}
${checkedItems.length
? html`
<div class="divider"></div>
<div class="header">
<span>
${this.hass!.localize(
"ui.panel.lovelace.cards.todo-list.checked_items"
)} )}
</span> </p>`}
${this.todoListSupportsFeature( ${checkedItems.length
TodoListEntityFeature.DELETE_TODO_ITEM ? html`
) <div role="separator">
? html`<ha-button-menu> <div class="divider"></div>
<ha-icon-button <div class="header">
slot="trigger" <h2>
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item
@click=${this._clearCompletedItems}
graphic="icon"
class="warning"
>
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.cards.todo-list.clear_items" "ui.panel.lovelace.cards.todo-list.checked_items"
)} )}
<ha-svg-icon </h2>
class="warning" ${this.todoListSupportsFeature(
slot="graphic" TodoListEntityFeature.DELETE_TODO_ITEM
.path=${mdiDeleteSweep} )
.disabled=${unavailable} ? html`<ha-button-menu>
> <ha-icon-button
</ha-svg-icon> slot="trigger"
</ha-list-item> .path=${mdiDotsVertical}
</ha-button-menu>` ></ha-icon-button>
: nothing} <ha-list-item
</div> @click=${this._clearCompletedItems}
<mwc-list multi id="checked"> graphic="icon"
${this._renderItems(checkedItems, unavailable)} class="warning"
</mwc-list> >
` ${this.hass!.localize(
: ""} "ui.panel.lovelace.cards.todo-list.clear_items"
)}
<ha-svg-icon
class="warning"
slot="graphic"
.path=${mdiDeleteSweep}
.disabled=${unavailable}
>
</ha-svg-icon>
</ha-list-item>
</ha-button-menu>`
: nothing}
</div>
</div>
${this._renderItems(checkedItems, unavailable)}
`
: ""}
</mwc-list>
</ha-sortable>
</ha-card> </ha-card>
`; `;
} }
@ -344,6 +347,7 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
left left
.hasMeta=${showReorder || showDelete} .hasMeta=${showReorder || showDelete}
class="editRow ${classMap({ class="editRow ${classMap({
draggable: item.status === TodoItemStatus.NeedsAction,
completed: item.status === TodoItemStatus.Completed, completed: item.status === TodoItemStatus.Completed,
multiline: Boolean(item.description || item.due), multiline: Boolean(item.description || item.due),
})}" })}"
@ -471,6 +475,12 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
} }
private async _completeItem(ev): Promise<void> { private async _completeItem(ev): Promise<void> {
let focusedIndex: number | undefined;
let list: List | undefined;
if (ev.type === "keydown") {
list = this.renderRoot.querySelector("mwc-list")!;
focusedIndex = list.getFocusedItemIndex();
}
const item = this._getItem(ev.currentTarget.itemId); const item = this._getItem(ev.currentTarget.itemId);
if (!item) { if (!item) {
return; return;
@ -483,17 +493,11 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
? TodoItemStatus.Completed ? TodoItemStatus.Completed
: TodoItemStatus.NeedsAction, : TodoItemStatus.NeedsAction,
}); });
await this.updateComplete; if (focusedIndex !== undefined && list) {
const newList: List = this.shadowRoot!.querySelector( await this.updateComplete;
item.status === TodoItemStatus.NeedsAction ? "#checked" : "#unchecked" await list.updateComplete;
)!; list.focusItemAtIndex(focusedIndex);
await newList.updateComplete; }
const items =
item.status === TodoItemStatus.NeedsAction
? this._getCheckedItems(this._items)
: this._getUncheckedItems(this._items);
const index = items.findIndex((itm) => itm.uid === item.uid);
newList.focusItemAtIndex(index);
} }
private async _clearCompletedItems(): Promise<void> { private async _clearCompletedItems(): Promise<void> {
@ -562,6 +566,9 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
} }
private async _moveItem(oldIndex: number, newIndex: number) { private async _moveItem(oldIndex: number, newIndex: number) {
// correct index for header
oldIndex -= 1;
newIndex -= 1;
const uncheckedItems = this._getUncheckedItems(this._items); const uncheckedItems = this._getUncheckedItems(this._items);
const item = uncheckedItems[oldIndex]; const item = uncheckedItems[oldIndex];
let prevItem: TodoItem | undefined; let prevItem: TodoItem | undefined;
@ -630,8 +637,9 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
direction: var(--direction); direction: var(--direction);
} }
.header span { .header h2 {
color: var(--primary-text-color); color: var(--primary-text-color);
font-size: inherit;
font-weight: 500; font-weight: 500;
} }