Improve search and filters on mobile + fix close button in search field (#11662)

Co-authored-by: Zack <zackbarett@hey.com>
This commit is contained in:
Bram Kragten 2022-02-11 19:34:50 +01:00 committed by GitHub
parent 35cc291118
commit a9bfea233c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 163 additions and 93 deletions

View File

@ -14,6 +14,9 @@ class SearchInput extends LitElement {
@property() public filter?: string;
@property({ type: Boolean })
public suffix = false;
@property({ type: Boolean })
public autofocus = false;
@ -33,7 +36,7 @@ class SearchInput extends LitElement {
.label=${this.label || "Search"}
.value=${this.filter || ""}
.icon=${true}
.iconTrailing=${this.filter}
.iconTrailing=${this.filter || this.suffix}
@input=${this._filterInputChanged}
>
<slot name="prefix" slot="leadingIcon">
@ -43,16 +46,18 @@ class SearchInput extends LitElement {
.path=${mdiMagnify}
></ha-svg-icon>
</slot>
${this.filter &&
html`
<ha-icon-button
slot="trailingIcon"
@click=${this._clearSearch}
.label=${this.hass.localize("ui.common.clear")}
.path=${mdiClose}
class="clear-button"
></ha-icon-button>
`}
<div class="trailing" slot="trailingIcon">
${this.filter &&
html`
<ha-icon-button
@click=${this._clearSearch}
.label=${this.hass.localize("ui.common.clear")}
.path=${mdiClose}
class="clear-button"
></ha-icon-button>
`}
<slot name="suffix"></slot>
</div>
</ha-textfield>
`;
}
@ -81,15 +86,16 @@ class SearchInput extends LitElement {
ha-svg-icon {
outline: none;
}
ha-icon-button {
--mdc-icon-button-size: 24px;
}
.clear-button {
--mdc-icon-size: 20px;
}
ha-textfield {
display: inherit;
}
.trailing {
display: flex;
align-items: center;
}
`;
}
}

View File

@ -73,6 +73,7 @@ export class HaRelatedFilterButtonMenu extends LitElement {
.hass=${this.hass}
.value=${this.value?.area}
no-add
.excludeDomains=${this.excludeDomains}
@value-changed=${this._areaPicked}
></ha-area-picker>
<ha-device-picker
@ -81,6 +82,7 @@ export class HaRelatedFilterButtonMenu extends LitElement {
)}
.hass=${this.hass}
.value=${this.value?.device}
.excludeDomains=${this.excludeDomains}
@value-changed=${this._devicePicked}
></ha-device-picker>
<ha-entity-picker
@ -103,7 +105,8 @@ export class HaRelatedFilterButtonMenu extends LitElement {
this._open = true;
}
private _onClosed(): void {
private _onClosed(ev): void {
ev.stopPropagation();
this._open = false;
}
@ -173,9 +176,7 @@ export class HaRelatedFilterButtonMenu extends LitElement {
:host {
display: inline-block;
position: relative;
}
:host([narrow]) {
position: static;
--mdc-menu-min-width: 200px;
}
ha-area-picker,
ha-device-picker,
@ -186,7 +187,8 @@ export class HaRelatedFilterButtonMenu extends LitElement {
box-sizing: border-box;
}
:host([narrow]) ha-area-picker,
:host([narrow]) ha-device-picker {
:host([narrow]) ha-device-picker,
:host([narrow]) ha-entity-picker {
width: 100%;
}
`;

View File

@ -68,6 +68,14 @@ export class HaTextField extends TextFieldBase {
:host([no-spinner]) input[type="number"] {
-moz-appearance: textfield;
}
.mdc-text-field__ripple {
overflow: hidden;
}
.mdc-text-field {
overflow: var(--text-field-overflow);
}
`,
];
}

View File

@ -1,5 +1,4 @@
import "@material/mwc-button/mwc-button";
import { mdiFilterVariant } from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
@ -157,30 +156,27 @@ export class HaTabsSubpageDataTable extends LitElement {
: hiddenLabel;
const headerToolbar = html`<search-input
.hass=${this.hass}
.filter=${this.filter}
@value-changed=${this._handleSearchChange}
.label=${this.searchLabel ||
this.hass.localize("ui.components.data-table.search")}
>
</search-input>
<div class="filters">
${filterInfo
? html`<div class="active-filters">
${this.narrow
? html`<div>
<ha-svg-icon .path=${mdiFilterVariant}></ha-svg-icon>
<paper-tooltip animation-delay="0" position="left">
${filterInfo}
</paper-tooltip>
</div>`
: filterInfo}
<mwc-button @click=${this._clearFilter}>
${this.hass.localize("ui.components.data-table.clear")}
</mwc-button>
</div>`
: ""}<slot name="filter-menu"></slot>
</div>`;
.hass=${this.hass}
.filter=${this.filter}
.suffix=${!this.narrow}
@value-changed=${this._handleSearchChange}
.label=${this.searchLabel ||
this.hass.localize("ui.components.data-table.search")}
>
${!this.narrow
? html`<div class="filters" slot="suffix">
${filterInfo
? html`<div class="active-filters">
${filterInfo}
<mwc-button @click=${this._clearFilter}>
${this.hass.localize("ui.components.data-table.clear")}
</mwc-button>
</div>`
: ""}
<slot name="filter-menu"></slot>
</div>`
: ""}
</search-input>`;
return html`
<hass-tabs-subpage
@ -195,7 +191,16 @@ export class HaTabsSubpageDataTable extends LitElement {
.mainPage=${this.mainPage}
.supervisor=${this.supervisor}
>
<div slot="toolbar-icon"><slot name="toolbar-icon"></slot></div>
<div slot="toolbar-icon">
${this.narrow
? html`<div class="filter-menu">
<slot name="filter-menu"></slot>${this.numHidden ||
this.activeFilters
? html`<span class="badge">${this.numHidden || "!"}</span>`
: ""}
</div>`
: ""}<slot name="toolbar-icon"></slot>
</div>
${this.narrow
? html`
<div slot="header">
@ -267,6 +272,12 @@ export class HaTabsSubpageDataTable extends LitElement {
align-items: center;
color: var(--secondary-text-color);
}
search-input {
--mdc-text-field-fill-color: var(--sidebar-background-color);
--mdc-text-field-idle-line-color: var(--divider-color);
--text-field-overflow: visible;
z-index: 5;
}
.table-header search-input {
display: block;
position: absolute;
@ -276,15 +287,16 @@ export class HaTabsSubpageDataTable extends LitElement {
}
.search-toolbar search-input {
display: block;
width: 100%;
color: var(--secondary-text-color);
--mdc-text-field-fill-color: transparant;
--mdc-text-field-idle-line-color: var(--divider-color);
--mdc-ripple-color: transparant;
}
.filters {
--mdc-text-field-fill-color: initial;
--mdc-text-field-idle-line-color: initial;
--text-field-overflow: initial;
display: flex;
justify-content: flex-end;
width: 100%;
margin-right: 8px;
}
.active-filters {
@ -295,6 +307,7 @@ export class HaTabsSubpageDataTable extends LitElement {
padding: 2px 2px 2px 8px;
margin-left: 4px;
font-size: 14px;
width: max-content;
}
.active-filters ha-svg-icon {
color: var(--primary-color);
@ -313,6 +326,24 @@ export class HaTabsSubpageDataTable extends LitElement {
left: 0;
content: "";
}
.badge {
min-width: 20px;
box-sizing: border-box;
border-radius: 50%;
font-weight: 400;
background-color: var(--primary-color);
line-height: 20px;
text-align: center;
padding: 0px 4px;
color: var(--text-primary-color);
position: absolute;
right: 0;
top: 4px;
font-size: 0.65em;
}
.filter-menu {
position: relative;
}
`;
}
}

View File

@ -272,6 +272,7 @@ class HassTabsSubpage extends LitElement {
ha-menu-button,
ha-icon-button-arrow-prev,
::slotted([slot="toolbar-icon"]) {
display: flex;
flex-shrink: 0;
pointer-events: auto;
color: var(--sidebar-icon-color);

View File

@ -297,29 +297,35 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
this._filter
);
const filterMenu = html`<ha-button-menu
corner="BOTTOM_START"
multi
slot=${ifDefined(this.narrow ? "toolbar-icon" : undefined)}
@action=${this._handleMenuAction}
const filterMenu = html`<div
slot=${ifDefined(this.narrow ? "toolbar-icon" : "suffix")}
>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiFilterVariant}
<ha-button-menu
corner="BOTTOM_START"
multi
@action=${this._handleMenuAction}
>
</ha-icon-button>
<ha-check-list-item left .selected=${this._showIgnored}>
${this.hass.localize(
"ui.panel.config.integrations.ignore.show_ignored"
)}
</ha-check-list-item>
<ha-check-list-item left .selected=${this._showDisabled}>
${this.hass.localize(
"ui.panel.config.integrations.disable.show_disabled"
)}
</ha-check-list-item>
</ha-button-menu>`;
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiFilterVariant}
>
</ha-icon-button>
<ha-check-list-item left .selected=${this._showIgnored}>
${this.hass.localize(
"ui.panel.config.integrations.ignore.show_ignored"
)}
</ha-check-list-item>
<ha-check-list-item left .selected=${this._showDisabled}>
${this.hass.localize(
"ui.panel.config.integrations.disable.show_disabled"
)}
</ha-check-list-item>
</ha-button-menu>
${!this._showDisabled && this.narrow && disabledCount
? html`<span class="badge">${disabledCount}</span>`
: ""}
</div>`;
return html`
<hass-tabs-subpage
@ -336,8 +342,6 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
.hass=${this.hass}
.filter=${this._filter}
class="header"
no-label-float
no-underline
@value-changed=${this._handleSearchChange}
.label=${this.hass.localize(
"ui.panel.config.integrations.search"
@ -350,29 +354,29 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
<div class="search">
<search-input
.hass=${this.hass}
no-label-float
no-underline
suffix
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
.label=${this.hass.localize(
"ui.panel.config.integrations.search"
)}
></search-input>
${!this._showDisabled && disabledCount
? html`<div class="active-filters">
${this.hass.localize(
"ui.panel.config.integrations.disable.disabled_integrations",
{ number: disabledCount }
)}
<mwc-button
@click=${this._toggleShowDisabled}
.label=${this.hass.localize(
"ui.panel.config.integrations.disable.show"
>
${!this._showDisabled && disabledCount
? html`<div class="active-filters" slot="suffix">
${this.hass.localize(
"ui.panel.config.integrations.disable.disabled_integrations",
{ number: disabledCount }
)}
></mwc-button>
</div>`
: ""}
${filterMenu}
<mwc-button
@click=${this._toggleShowDisabled}
.label=${this.hass.localize(
"ui.panel.config.integrations.disable.show"
)}
></mwc-button>
</div>`
: ""}
${filterMenu}
</search-input>
</div>
`}
@ -683,13 +687,15 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
.empty-message h1 {
margin-bottom: 0;
}
search-input {
--mdc-text-field-fill-color: var(--sidebar-background-color);
--mdc-text-field-idle-line-color: var(--divider-color);
--text-field-overflow: visible;
}
search-input.header {
display: block;
color: var(--secondary-text-color);
margin-left: 8px;
--mdc-text-field-fill-color: transparant;
--mdc-text-field-idle-line-color: var(--divider-color);
--mdc-ripple-color: transparant;
}
.search {
@ -717,6 +723,7 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
align-items: center;
padding: 2px 2px 2px 8px;
font-size: 14px;
width: max-content;
}
.active-filters mwc-button {
margin-left: 8px;
@ -732,6 +739,21 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
left: 0;
content: "";
}
.badge {
min-width: 20px;
box-sizing: border-box;
border-radius: 50%;
font-weight: 400;
background-color: var(--primary-color);
line-height: 20px;
text-align: center;
padding: 0px 4px;
color: var(--text-primary-color);
position: absolute;
right: 14px;
top: 8px;
font-size: 0.65em;
}
`,
];
}

View File

@ -105,10 +105,10 @@ export class HaConfigLogs extends LitElement {
}
search-input {
display: block;
--mdc-text-field-fill-color: var(--sidebar-background-color);
--mdc-text-field-idle-line-color: var(--divider-color);
}
search-input.header {
--mdc-text-field-fill-color: transparant;
--mdc-text-field-idle-line-color: var(--divider-color);
--mdc-ripple-color: transparant;
}
.content {