A11y expansion panel (#11967)

This commit is contained in:
Bram Kragten 2022-03-07 15:40:19 +01:00 committed by GitHub
parent 9d28df31bd
commit 4b8b14a69d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,13 @@
import { mdiChevronDown } from "@mdi/js"; import { mdiChevronDown } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import {
import { customElement, property, query } from "lit/decorators"; css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { nextRender } from "../common/util/render-status"; import { nextRender } from "../common/util/render-status";
@ -16,11 +23,21 @@ class HaExpansionPanel extends LitElement {
@property() secondary?: string; @property() secondary?: string;
@state() _showContent = this.expanded;
@query(".container") private _container!: HTMLDivElement; @query(".container") private _container!: HTMLDivElement;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<div class="summary" @click=${this._toggleContainer}> <div
id="summary"
@click=${this._toggleContainer}
@keydown=${this._toggleContainer}
role="button"
tabindex="0"
aria-expanded=${this.expanded}
aria-controls="sect1"
>
<slot class="header" name="header"> <slot class="header" name="header">
${this.header} ${this.header}
<slot class="secondary" name="secondary">${this.secondary}</slot> <slot class="secondary" name="secondary">${this.secondary}</slot>
@ -33,21 +50,37 @@ class HaExpansionPanel extends LitElement {
<div <div
class="container ${classMap({ expanded: this.expanded })}" class="container ${classMap({ expanded: this.expanded })}"
@transitionend=${this._handleTransitionEnd} @transitionend=${this._handleTransitionEnd}
role="region"
aria-labelledby="summary"
aria-hidden=${!this.expanded}
tabindex="-1"
> >
<slot></slot> ${this._showContent ? html`<slot></slot>` : ""}
</div> </div>
`; `;
} }
private _handleTransitionEnd() { protected willUpdate(changedProps: PropertyValues) {
this._container.style.removeProperty("height"); if (changedProps.has("expanded") && this.expanded) {
this._showContent = this.expanded;
}
} }
private async _toggleContainer(): Promise<void> { private _handleTransitionEnd() {
this._container.style.removeProperty("height");
this._showContent = this.expanded;
}
private async _toggleContainer(ev): Promise<void> {
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
return;
}
ev.preventDefault();
const newExpanded = !this.expanded; const newExpanded = !this.expanded;
fireEvent(this, "expanded-will-change", { expanded: newExpanded }); fireEvent(this, "expanded-will-change", { expanded: newExpanded });
if (newExpanded) { if (newExpanded) {
this._showContent = true;
// allow for dynamic content to be rendered // allow for dynamic content to be rendered
await nextRender(); await nextRender();
} }
@ -80,17 +113,21 @@ class HaExpansionPanel extends LitElement {
var(--divider-color, #e0e0e0) var(--divider-color, #e0e0e0)
); );
border-radius: var(--ha-card-border-radius, 4px); border-radius: var(--ha-card-border-radius, 4px);
padding: 0 8px;
} }
.summary { #summary {
display: flex; display: flex;
padding: var(--expansion-panel-summary-padding, 0); padding: var(--expansion-panel-summary-padding, 0 8px);
min-height: 48px; min-height: 48px;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
overflow: hidden; overflow: hidden;
font-weight: 500; font-weight: 500;
outline: none;
}
#summary:focus {
background: var(--input-fill-color);
} }
.summary-icon { .summary-icon {
@ -103,6 +140,7 @@ class HaExpansionPanel extends LitElement {
} }
.container { .container {
padding: var(--expansion-panel-content-padding, 0 8px);
overflow: hidden; overflow: hidden;
transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1); transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1);
height: 0px; height: 0px;