Redesign ha-button (#25564)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Wendelin 2025-07-30 16:15:18 +02:00 committed by GitHub
parent 6dbfc2f4ed
commit fa758f2bee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
318 changed files with 3333 additions and 2189 deletions

View File

@ -1,5 +1,3 @@
import "@material/mwc-button/mwc-button";
import type { ActionDetail } from "@material/mwc-list/mwc-list";
import { mdiCast, mdiCastConnected, mdiViewDashboard } from "@mdi/js";
import type { Auth, Connection } from "home-assistant-js-websocket";
@ -20,6 +18,7 @@ import { atLeastVersion } from "../../../../src/common/config/version";
import { toggleAttribute } from "../../../../src/common/dom/toggle_attribute";
import "../../../../src/components/ha-icon";
import "../../../../src/components/ha-list";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-list-item";
import "../../../../src/components/ha-svg-icon";
import {
@ -63,12 +62,20 @@ class HcCast extends LitElement {
<p class="question action-item">
Stay logged in?
<span>
<mwc-button @click=${this._handleSaveTokens}>
<ha-button
appearance="plain"
size="small"
@click=${this._handleSaveTokens}
>
YES
</mwc-button>
<mwc-button @click=${this._handleSkipSaveTokens}>
</ha-button>
<ha-button
appearance="plain"
size="small"
@click=${this._handleSkipSaveTokens}
>
NO
</mwc-button>
</ha-button>
</span>
</p>
`
@ -78,10 +85,10 @@ class HcCast extends LitElement {
: !this.castManager.status
? html`
<p class="center-item">
<mwc-button raised @click=${this._handleLaunch}>
<ha-svg-icon .path=${mdiCast}></ha-svg-icon>
<ha-button @click=${this._handleLaunch}>
<ha-svg-icon slot="start" .path=${mdiCast}></ha-svg-icon>
Start Casting
</mwc-button>
</ha-button>
</p>
`
: html`
@ -121,14 +128,22 @@ class HcCast extends LitElement {
<div class="card-actions">
${this.castManager.status
? html`
<mwc-button @click=${this._handleLaunch}>
<ha-svg-icon .path=${mdiCastConnected}></ha-svg-icon>
<ha-button appearance="plain" @click=${this._handleLaunch}>
<ha-svg-icon
slot="start"
.path=${mdiCastConnected}
></ha-svg-icon>
Manage
</mwc-button>
</ha-button>
`
: ""}
<div class="spacer"></div>
<mwc-button @click=${this._handleLogout}>Log out</mwc-button>
<ha-button
variant="danger"
appearance="plain"
@click=${this._handleLogout}
>Log out</ha-button
>
</div>
</hc-layout>
`;
@ -245,13 +260,6 @@ class HcCast extends LitElement {
color: var(--secondary-text-color);
}
mwc-button ha-svg-icon {
margin-right: 8px;
margin-inline-end: 8px;
margin-inline-start: initial;
height: 18px;
}
ha-list-item ha-icon,
ha-list-item ha-svg-icon {
padding: 12px;

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import { mdiCastConnected, mdiCast } from "@mdi/js";
import type {
Auth,
@ -28,6 +27,7 @@ import "../../../../src/layouts/hass-loading-screen";
import { registerServiceWorker } from "../../../../src/util/register-service-worker";
import "./hc-layout";
import "../../../../src/components/ha-textfield";
import "../../../../src/components/ha-button";
const seeFAQ = (qid) => html`
See <a href="./faq.html${qid ? `#${qid}` : ""}">the FAQ</a> for more
@ -83,11 +83,14 @@ export class HcConnect extends LitElement {
Unable to connect to ${tokens!.hassUrl}.
</div>
<div class="card-actions">
<a href="/">
<mwc-button> Retry </mwc-button>
</a>
<ha-button appearance="plain" href="/">Retry</ha-button>
<div class="spacer"></div>
<mwc-button @click=${this._handleLogout}>Log out</mwc-button>
<ha-button
appearance="plain"
variant="danger"
@click=${this._handleLogout}
>Log out</ha-button
>
</div>
</hc-layout>
`;
@ -128,16 +131,19 @@ export class HcConnect extends LitElement {
${this.error ? html` <p class="error">${this.error}</p> ` : ""}
</div>
<div class="card-actions">
<mwc-button @click=${this._handleDemo}>
<ha-button appearance="plain" @click=${this._handleDemo}>
Show Demo
<ha-svg-icon
slot="end"
.path=${this.castManager.castState === "CONNECTED"
? mdiCastConnected
: mdiCast}
></ha-svg-icon>
</mwc-button>
</ha-button>
<div class="spacer"></div>
<mwc-button @click=${this._handleConnect}>Authorize</mwc-button>
<ha-button appearance="plain" @click=${this._handleConnect}
>Authorize</ha-button
>
</div>
</hc-layout>
`;
@ -309,10 +315,6 @@ export class HcConnect extends LitElement {
color: darkred;
}
mwc-button ha-svg-icon {
margin-left: 8px;
}
.spacer {
flex: 1;
}

View File

@ -1,11 +1,11 @@
import "@material/mwc-button/mwc-button";
import type { Button } from "@material/mwc-button";
import type { TemplateResult } from "lit";
import { html, LitElement, css, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/ha-card";
import "../../../src/components/ha-button";
import type { HaButton } from "../../../src/components/ha-button";
@customElement("demo-black-white-row")
class DemoBlackWhiteRow extends LitElement {
@ -25,12 +25,9 @@ class DemoBlackWhiteRow extends LitElement {
<slot name="light"></slot>
</div>
<div class="card-actions">
<mwc-button
.disabled=${this.disabled}
@click=${this.handleSubmit}
>
<ha-button .disabled=${this.disabled} @click=${this.handleSubmit}>
Submit
</mwc-button>
</ha-button>
</div>
</ha-card>
</div>
@ -40,12 +37,9 @@ class DemoBlackWhiteRow extends LitElement {
<slot name="dark"></slot>
</div>
<div class="card-actions">
<mwc-button
.disabled=${this.disabled}
@click=${this.handleSubmit}
>
<ha-button .disabled=${this.disabled} @click=${this.handleSubmit}>
Submit
</mwc-button>
</ha-button>
</div>
</ha-card>
${this.value
@ -74,7 +68,7 @@ class DemoBlackWhiteRow extends LitElement {
}
handleSubmit(ev) {
const content = (ev.target as Button).closest(".content")!;
const content = (ev.target as HaButton).closest(".content")!;
fireEvent(this, "submitted" as any, {
slot: content.classList.contains("light") ? "light" : "dark",
});

View File

@ -147,13 +147,13 @@ The `title ` option should not be used without a description.
<ha-alert alert-type="success">
This is a success alert — check it out!
<mwc-button slot="action" label="Undo"></mwc-button>
<ha-button slot="action" label="Undo"></ha-button>
</ha-alert>
```html
<ha-alert alert-type="success">
This is a success alert — check it out!
<mwc-button slot="action" label="Undo"></mwc-button>
<ha-button slot="action" label="Undo"></ha-button>
</ha-alert>
```

View File

@ -1,10 +1,10 @@
import "@material/mwc-button/mwc-button";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-logo-svg";
const alerts: {
@ -78,13 +78,21 @@ const alerts: {
title: "Error with action",
description: "This is a test error alert with action",
type: "error",
actionSlot: html`<mwc-button slot="action" label="restart"></mwc-button>`,
actionSlot: html`<ha-button
size="small"
slot="action"
label="restart"
></ha-button>`,
},
{
title: "Unsaved data",
description: "You have unsaved data",
type: "warning",
actionSlot: html`<mwc-button slot="action" label="save"></mwc-button>`,
actionSlot: html`<ha-button
size="small"
slot="action"
label="save"
></ha-button>`,
},
{
title: "Slotted icon",
@ -108,7 +116,7 @@ const alerts: {
title: "Slotted action",
description: "Alert with slotted action",
type: "info",
actionSlot: html`<mwc-button slot="action" label="action"></mwc-button>`,
actionSlot: html`<ha-button slot="action" label="action"></ha-button>`,
},
{
description: "Dismissable information (RTL)",
@ -120,7 +128,7 @@ const alerts: {
title: "Error with action",
description: "This is a test error alert with action (RTL)",
type: "error",
actionSlot: html`<mwc-button slot="action" label="restart"></mwc-button>`,
actionSlot: html`<ha-button slot="action" label="restart"></ha-button>`,
rtl: true,
},
{
@ -211,7 +219,7 @@ export class DemoHaAlert extends LitElement {
max-height: 24px;
width: 24px;
}
mwc-button {
ha-button {
--mdc-theme-primary: var(--primary-text-color);
}
`;

View File

@ -0,0 +1,66 @@
---
title: Button
---
<style>
.wrapper {
display: flex;
gap: 24px;
}
</style>
# Button `<ha-button>`
## Implementation
### Example Usage
<div class="wrapper">
<ha-button>
simple button
</ha-button>
<ha-button appearance="plain">
plain button
</ha-button>
<ha-button appearance="filled">
filled button
</ha-button>
<ha-button size="small">
small
</ha-button>
</div>
```html
<ha-button> simple button </ha-button>
<ha-button size="small"> small </ha-button>
```
### API
This component is based on the webawesome button component.
Check the [webawesome documentation](https://webawesome.com/docs/components/button/) for more details.
**Slots**
- default slot: Label of the button
` - no default
- `start`: The prefix container (usually for icons).
` - no default
- `end`: The suffix container (usually for icons).
` - no default
**Properties/Attributes**
| Name | Type | Default | Description |
| ----------- | ---------------------------------------------- | -------- | -------------------------------------------------- |
| appearance | "accent"/"filled"/"plain" | "accent" | Sets the button appearance. |
| variants | "brand"/"danger"/"neutral"/"warning"/"success" | "brand" | Sets the button color variant. "brand" is default. |
| size | "small"/"medium" | "medium" | Sets the button size. |
| hideContent | Boolean | false | Hides the button content (for overlays) |
**CSS Custom Properties**
- `--ha-button-height` - Height of the button.
- `--ha-button-radius` - Border radius of the button. Defaults to `var(--wa-border-radius-pill)`.

View File

@ -0,0 +1,171 @@
import { mdiHome } from "@mdi/js";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
import { titleCase } from "../../../../src/common/string/title-case";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-svg-icon";
import { mdiHomeAssistant } from "../../../../src/resources/home-assistant-logo-svg";
const appearances = ["accent", "filled", "plain"];
const variants = ["brand", "danger", "neutral", "warning", "success"];
@customElement("demo-components-ha-button")
export class DemoHaButton extends LitElement {
protected render(): TemplateResult {
return html`
${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<ha-card header="ha-button in ${mode}">
<div class="card-content">
${variants.map(
(variant) => html`
<div>
${appearances.map(
(appearance) => html`
<ha-button
.appearance=${appearance}
.variant=${variant}
>
<ha-svg-icon
.path=${mdiHomeAssistant}
slot="start"
></ha-svg-icon>
${titleCase(`${variant} ${appearance}`)}
<ha-svg-icon
.path=${mdiHome}
slot="end"
></ha-svg-icon>
</ha-button>
`
)}
</div>
<div>
${appearances.map(
(appearance) => html`
<ha-button
.appearance=${appearance}
.variant=${variant}
size="small"
>
${titleCase(`${variant} ${appearance}`)}
</ha-button>
`
)}
</div>
<div>
${appearances.map(
(appearance) => html`
<ha-button
.appearance=${appearance}
.variant=${variant}
loading
>
<ha-svg-icon
.path=${mdiHomeAssistant}
slot="start"
></ha-svg-icon>
${titleCase(`${variant} ${appearance}`)}
<ha-svg-icon
.path=${mdiHome}
slot="end"
></ha-svg-icon>
</ha-button>
`
)}
</div>
`
)}
${variants.map(
(variant) => html`
<div>
${appearances.map(
(appearance) => html`
<ha-button
.variant=${variant}
.appearance=${appearance}
disabled
>
${titleCase(`${appearance}`)}
</ha-button>
`
)}
</div>
<div>
${appearances.map(
(appearance) => html`
<ha-button
.variant=${variant}
.appearance=${appearance}
size="small"
disabled
>
${titleCase(`${appearance}`)}
</ha-button>
`
)}
</div>
`
)}
</div>
</ha-card>
</div>
`
)}
`;
}
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static styles = css`
:host {
display: flex;
justify-content: center;
}
.dark,
.light {
display: block;
background-color: var(--primary-background-color);
padding: 0 50px;
}
.button {
padding: unset;
}
ha-card {
margin: 24px auto;
}
.card-content {
display: flex;
flex-direction: column;
gap: 24px;
}
.card-content div {
display: flex;
gap: 8px;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-button": DemoHaButton;
}
}

View File

@ -1,5 +1,4 @@
/* eslint-disable lit/no-template-arrow */
import "@material/mwc-button";
import type { TemplateResult } from "lit";
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";

View File

@ -0,0 +1,32 @@
---
title: Progress Button
---
<style>
.wrapper {
display: flex;
gap: 24px;
}
</style>
# Progress Button `<ha-progress-button>`
### API
This component is a wrapper around `<ha-button>` that adds support for showing progress
**Slots**
- default slot: Label of the button
` - no default
**Properties/Attributes**
| Name | Type | Default | Description |
| ---------- | ---------------------------------------------- | --------- | -------------------------------------------------- |
| label | string | "accent" | Sets the button label. |
| disabled | Boolean | false | Disables the button if true. |
| progress | Boolean | false | Shows a progress indicator on the button. |
| appearance | "accent"/"filled"/"plain" | "accent" | Sets the button appearance. |
| variants | "brand"/"danger"/"neutral"/"warning"/"success" | "brand" | Sets the button color variant. "brand" is default. |
| iconPath | string | undefined | Sets the icon path for the button. |

View File

@ -0,0 +1,139 @@
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-svg-icon";
import { mdiHomeAssistant } from "../../../../src/resources/home-assistant-logo-svg";
@customElement("demo-components-ha-progress-button")
export class DemoHaProgressButton extends LitElement {
protected render(): TemplateResult {
return html`
${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<ha-card header="ha-progress-button in ${mode}">
<div class="card-content">
<ha-progress-button @click=${this._clickedSuccess}>
Success
</ha-progress-button>
<ha-progress-button @click=${this._clickedFail}>
Fail
</ha-progress-button>
<ha-progress-button size="small" @click=${this._clickedSuccess}>
small
</ha-progress-button>
<ha-progress-button
appearance="filled"
@click=${this._clickedSuccess}
>
filled
</ha-progress-button>
<ha-progress-button
appearance="plain"
@click=${this._clickedSuccess}
>
plain
</ha-progress-button>
<ha-progress-button
variant="warning"
@click=${this._clickedSuccess}
>
warning
</ha-progress-button>
<ha-progress-button
variant="neutral"
@click=${this._clickedSuccess}
label="with icon"
.iconPath=${mdiHomeAssistant}
>
With Icon
</ha-progress-button>
<ha-progress-button progress @click=${this._clickedSuccess}>
progress
</ha-progress-button>
<ha-progress-button disabled @click=${this._clickedSuccess}>
disabled
</ha-progress-button>
</div>
</ha-card>
</div>
`
)}
`;
}
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
private async _clickedSuccess(ev: CustomEvent): Promise<void> {
console.log("Clicked success");
const button = ev.currentTarget as any;
button.progress = true;
setTimeout(() => {
button.actionSuccess();
button.progress = false;
}, 1000);
}
private async _clickedFail(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;
setTimeout(() => {
button.actionError();
button.progress = false;
}, 1000);
}
static styles = css`
:host {
display: flex;
justify-content: center;
}
.dark,
.light {
display: block;
background-color: var(--primary-background-color);
padding: 0 50px;
}
.button {
padding: unset;
}
ha-card {
margin: 24px auto;
}
.card-content {
display: flex;
flex-direction: column;
gap: 24px;
}
.card-content div {
display: flex;
gap: 8px;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-progress-button": DemoHaProgressButton;
}
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";

View File

@ -1,7 +1,7 @@
import "@material/mwc-button";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-card";
import type { ActionHandlerEvent } from "../../../../src/data/lovelace/action_handler";
import { actionHandler } from "../../../../src/panels/lovelace/common/directives/action-handler-directive";
@ -13,12 +13,16 @@ export class DemoUtilLongPress extends LitElement {
${[1, 2, 3].map(
() => html`
<ha-card>
<mwc-button
<ha-button
appearance="plain"
@action=${this._handleAction}
.actionHandler=${actionHandler({})}
.actionHandler=${actionHandler({
hasHold: true,
hasDoubleClick: true,
})}
>
(long) press me!
</mwc-button>
</ha-button>
<textarea></textarea>

View File

@ -99,7 +99,8 @@ class HassioAddonNetwork extends LitElement {
: nothing}
<div class="card-actions">
<ha-progress-button
class="warning"
variant="danger"
appearance="plain"
.disabled=${this.disabled}
@click=${this._resetTapped}
>

View File

@ -25,6 +25,7 @@ import type { CSSResultGroup, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event";
@ -187,12 +188,13 @@ class HassioAddonInfo extends LitElement {
"addon.dashboard.protection_mode.content"
)}
<ha-button
variant="danger"
slot="action"
.label=${this.supervisor.localize(
"addon.dashboard.protection_mode.enable"
)}
@click=${this._protectionToggled}
>
${this.supervisor.localize(
"addon.dashboard.protection_mode.enable"
)}
</ha-button>
</ha-alert>
`
@ -692,14 +694,16 @@ class HassioAddonInfo extends LitElement {
? this._computeIsRunning
? html`
<ha-progress-button
class="warning"
variant="danger"
appearance="plain"
@click=${this._stopClicked}
.disabled=${systemManaged && !this.controlEnabled}
>
${this.supervisor.localize("addon.dashboard.stop")}
</ha-progress-button>
<ha-progress-button
class="warning"
variant="danger"
appearance="plain"
@click=${this._restartClicked}
>
${this.supervisor.localize("addon.dashboard.restart")}
@ -709,48 +713,19 @@ class HassioAddonInfo extends LitElement {
<ha-progress-button
@click=${this._startClicked}
.progress=${this.addon.state === "startup"}
appearance="plain"
>
${this.supervisor.localize("addon.dashboard.start")}
</ha-progress-button>
`
: html`
<ha-progress-button
.disabled=${!this.addon.available}
@click=${this._installClicked}
>
${this.supervisor.localize("addon.dashboard.install")}
</ha-progress-button>
`}
: nothing}
</div>
<div>
${this.addon.version
? html` ${this._computeShowWebUI
? html`
<a
href=${this._pathWebui!}
tabindex="-1"
target="_blank"
rel="noopener"
>
<ha-button>
${this.supervisor.localize(
"addon.dashboard.open_web_ui"
)}
</ha-button>
</a>
`
: nothing}
${this._computeShowIngressUI
? html`
<ha-button @click=${this._openIngress}>
${this.supervisor.localize(
"addon.dashboard.open_web_ui"
)}
</ha-button>
`
: nothing}
? html`
<ha-progress-button
class="warning"
variant="danger"
appearance="plain"
@click=${this._uninstallClicked}
.disabled=${systemManaged && !this.controlEnabled}
>
@ -759,14 +734,47 @@ class HassioAddonInfo extends LitElement {
${this.addon.build
? html`
<ha-progress-button
class="warning"
variant="danger"
appearance="plain"
@click=${this._rebuildClicked}
>
${this.supervisor.localize("addon.dashboard.rebuild")}
</ha-progress-button>
`
: nothing}`
: nothing}
: nothing}
${this._computeShowWebUI || this._computeShowIngressUI
? html`
<ha-button
href=${ifDefined(
!this._computeShowIngressUI
? this._pathWebui!
: nothing
)}
target=${ifDefined(
!this._computeShowIngressUI ? "_blank" : nothing
)}
rel=${ifDefined(
!this._computeShowIngressUI ? "noopener" : nothing
)}
@click=${!this._computeShowWebUI
? this._openIngress
: undefined}
>
${this.supervisor.localize(
"addon.dashboard.open_web_ui"
)}
</ha-button>
`
: nothing}
`
: html`
<ha-progress-button
.disabled=${!this.addon.available}
@click=${this._installClicked}
>
${this.supervisor.localize("addon.dashboard.install")}
</ha-progress-button>
`}
</div>
</div>
</ha-card>
@ -1146,15 +1154,17 @@ class HassioAddonInfo extends LitElement {
),
dismissText: this.supervisor.localize("common.cancel"),
});
button.actionError();
button.progress = false;
return;
}
} catch (err: any) {
button.actionError();
button.progress = false;
showAlertDialog(this, {
title: "Failed to validate addon configuration",
text: extractApiErrorMessage(err),
});
button.progress = false;
return;
}
@ -1168,11 +1178,15 @@ class HassioAddonInfo extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
button.actionError();
button.progress = false;
showAlertDialog(this, {
title: this.supervisor.localize("addon.dashboard.action_error.start"),
text: extractApiErrorMessage(err),
});
return;
}
button.actionSuccess();
button.progress = false;
}
@ -1228,6 +1242,7 @@ class HassioAddonInfo extends LitElement {
path: "uninstall",
};
fireEvent(this, "hass-api-called", eventdata);
button.actionSuccess();
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize(
@ -1235,6 +1250,7 @@ class HassioAddonInfo extends LitElement {
),
text: extractApiErrorMessage(err),
});
button.actionError();
}
button.progress = false;
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { ActionDetail } from "@material/mwc-list";
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
@ -17,6 +16,7 @@ import type {
} from "../../../src/components/data-table/ha-data-table";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-fab";
import "../../../src/components/ha-button";
import "../../../src/components/ha-icon-button";
import "../../../src/components/ha-list-item";
import "../../../src/components/ha-svg-icon";
@ -241,12 +241,13 @@ export class HassioBackups extends LitElement {
<div class="header-btns">
${!this.narrow
? html`
<mwc-button
<ha-button
appearance="plain"
variant="danger"
@click=${this._deleteSelected}
class="warning"
>
${this.supervisor.localize("backup.delete_selected")}
</mwc-button>
</ha-button>
`
: html`
<ha-icon-button
@ -408,7 +409,7 @@ export class HassioBackups extends LitElement {
margin-inline-end: -12px;
margin-inline-start: initial;
}
.header-btns > mwc-button,
.header-btns > ha-button,
.header-btns > ha-icon-button {
margin: 8px;
}

View File

@ -1,10 +1,9 @@
import "@material/mwc-button";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-card";
import "../../../src/components/ha-button";
import "../../../src/components/ha-settings-row";
import "../../../src/components/ha-svg-icon";
import type { HassioHassOSInfo } from "../../../src/data/hassio/host";
@ -109,10 +108,9 @@ export class HassioUpdate extends LitElement {
</ha-settings-row>
</div>
<div class="card-actions">
<a href="/hassio/update-available/${key}">
<mwc-button .label=${this.supervisor.localize("common.show")}>
</mwc-button>
</a>
<ha-button appearance="plain" href="/hassio/update-available/${key}">
${this.supervisor.localize("common.show")}
</ha-button>
</div>
</ha-card>
`;

View File

@ -1,10 +1,10 @@
import "@material/mwc-button/mwc-button";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../src/components/ha-form/types";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
@ -77,20 +77,21 @@ class HassioBackupLocationDialog extends LitElement {
@value-changed=${this._valueChanged}
dialogInitialFocus
></ha-form>
<mwc-button
<ha-button
appearance="plain"
slot="secondaryAction"
@click=${this.closeDialog}
dialogInitialFocus
>
${this._dialogParams.supervisor.localize("common.cancel")}
</mwc-button>
<mwc-button
</ha-button>
<ha-button
.disabled=${this._waiting || !this._data}
slot="primaryAction"
@click=${this._changeMount}
>
${this._dialogParams.supervisor.localize("common.save")}
</mwc-button>
</ha-button>
</ha-dialog>
`;
}

View File

@ -8,7 +8,6 @@ import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
import { slugify } from "../../../../src/common/string/slugify";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-button-menu";

View File

@ -1,10 +1,9 @@
import "@material/mwc-button";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-spinner";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import {
@ -69,16 +68,20 @@ class HassioCreateBackupDialog extends LitElement {
${this._error
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
: ""}
<mwc-button slot="secondaryAction" @click=${this.closeDialog}>
<ha-button
appearance="plain"
slot="secondaryAction"
@click=${this.closeDialog}
>
${this._dialogParams.supervisor.localize("common.close")}
</mwc-button>
<mwc-button
</ha-button>
<ha-button
.disabled=${this._creatingBackup}
slot="primaryAction"
@click=${this._createBackup}
>
${this._dialogParams.supervisor.localize("backup.create")}
</mwc-button>
</ha-button>
</ha-dialog>
`;
}

View File

@ -4,6 +4,7 @@ import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-list-item";
import "../../../../src/components/ha-select";
import "../../../../src/components/ha-spinner";
@ -109,17 +110,18 @@ class HassioDatadiskDialog extends LitElement {
"dialog.datadisk_move.no_devices"
)}
<mwc-button
slot="secondaryAction"
<ha-button
appearance="plain"
slot="primaryAction"
@click=${this.closeDialog}
dialogInitialFocus
>
${this.dialogParams.supervisor.localize(
"dialog.datadisk_move.cancel"
)}
</mwc-button>
</ha-button>
<mwc-button
<ha-button
.disabled=${!this.selectedDevice}
slot="primaryAction"
@click=${this._moveDatadisk}
@ -127,7 +129,7 @@ class HassioDatadiskDialog extends LitElement {
${this.dialogParams.supervisor.localize(
"dialog.datadisk_move.move"
)}
</mwc-button>`}
</ha-button>`}
</ha-dialog>
`;
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import { mdiClose } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
@ -6,6 +5,7 @@ import { customElement, property, state } from "lit/decorators";
import { cache } from "lit/directives/cache";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-expansion-panel";
import "../../../../src/components/ha-formfield";
@ -15,7 +15,6 @@ import "../../../../src/components/ha-list";
import "../../../../src/components/ha-list-item";
import "../../../../src/components/ha-password-field";
import "../../../../src/components/ha-radio";
import "../../../../src/components/ha-spinner";
import "../../../../src/components/ha-textfield";
import type { HaTextField } from "../../../../src/components/ha-textfield";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
@ -154,16 +153,16 @@ export class DialogHassioNetwork
)}
</p>`
: ""}
<mwc-button
<ha-button
appearance="plain"
size="small"
class="scan"
@click=${this._scanForAP}
.disabled=${this._scanning}
.loading=${this._scanning}
>
${this._scanning
? html`<ha-spinner aria-label="Scanning" size="small">
</ha-spinner>`
: this.supervisor.localize("dialog.network.scan_ap")}
</mwc-button>
${this.supervisor.localize("dialog.network.scan_ap")}
</ha-button>
${this._accessPoints &&
this._accessPoints.accesspoints &&
this._accessPoints.accesspoints.length !== 0
@ -270,16 +269,16 @@ export class DialogHassioNetwork
: ""}
</div>
<div class="buttons">
<mwc-button
.label=${this.supervisor.localize("common.cancel")}
@click=${this.closeDialog}
<ha-button @click=${this.closeDialog} appearance="plain">
${this.supervisor.localize("common.cancel")}
</ha-button>
<ha-button
@click=${this._updateNetwork}
.disabled=${!this._dirty}
.loading=${this._processing}
>
</mwc-button>
<mwc-button @click=${this._updateNetwork} .disabled=${!this._dirty}>
${this._processing
? html`<ha-spinner size="small"> </ha-spinner>`
: this.supervisor.localize("common.save")}
</mwc-button>
${this.supervisor.localize("common.save")}
</ha-button>
</div>`;
}
@ -584,11 +583,7 @@ export class DialogHassioNetwork
}
}
mwc-button.warning {
--mdc-theme-primary: var(--error-color);
}
mwc-button.scan {
ha-button.scan {
margin-left: 8px;
margin-inline-start: 8px;
margin-inline-end: initial;

View File

@ -1,5 +1,4 @@
import "@material/mwc-button/mwc-button";
import { mdiDelete } from "@mdi/js";
import { mdiDelete, mdiPlus } from "@mdi/js";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -7,6 +6,8 @@ import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../src/components/ha-form/types";
import "../../../../src/components/ha-icon-button";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-svg-icon";
import "../../../../src/components/ha-settings-row";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import {
@ -84,16 +85,19 @@ class HassioRegistriesDialog extends LitElement {
dialogInitialFocus
></ha-form>
<div class="action">
<mwc-button
<ha-button
?disabled=${Boolean(
!this._input.registry ||
!this._input.username ||
!this._input.password
)}
@click=${this._addNewRegistry}
appearance="filled"
size="small"
>
<ha-svg-icon slot="start" .path=${mdiPlus}></ha-svg-icon>
${this.supervisor.localize("dialog.registries.add_registry")}
</mwc-button>
</ha-button>
</div>
`
: html`${this._registries?.length
@ -126,11 +130,17 @@ class HassioRegistriesDialog extends LitElement {
</ha-alert>
`}
<div class="action">
<mwc-button @click=${this._addRegistry} dialogInitialFocus>
<ha-button
@click=${this._addRegistry}
dialogInitialFocus
appearance="filled"
size="small"
>
<ha-svg-icon slot="start" .path=${mdiPlus}></ha-svg-icon>
${this.supervisor.localize(
"dialog.registries.add_new_registry"
)}
</mwc-button>
</ha-button>
</div> `}
</ha-dialog>
`;

View File

@ -1,5 +1,4 @@
import "@material/mwc-button/mwc-button";
import { mdiDelete, mdiDeleteOff } from "@mdi/js";
import { mdiDelete, mdiDeleteOff, mdiPlus } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
@ -7,8 +6,9 @@ import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { caseInsensitiveStringCompare } from "../../../../src/common/string/compare";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-tooltip";
import "../../../../src/components/ha-spinner";
import "../../../../src/components/ha-svg-icon";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-icon-button";
import type {
@ -159,18 +159,22 @@ class HassioRepositoriesDialog extends LitElement {
@keydown=${this._handleKeyAdd}
dialogInitialFocus
></ha-textfield>
<mwc-button @click=${this._addRepository}>
${this._processing
? html`<ha-spinner size="small"></ha-spinner>`
: this._dialogParams!.supervisor.localize(
"dialog.repositories.add"
)}
</mwc-button>
<ha-button
.loading=${this._processing}
@click=${this._addRepository}
appearance="filled"
size="small"
>
<ha-svg-icon slot="start" .path=${mdiPlus}></ha-svg-icon>
${this._dialogParams!.supervisor.localize(
"dialog.repositories.add"
)}
</ha-button>
</div>
</div>
<mwc-button slot="primaryAction" @click=${this.closeDialog}>
<ha-button slot="primaryAction" @click=${this.closeDialog}>
${this._dialogParams?.supervisor.localize("common.close")}
</mwc-button>
</ha-button>
</ha-dialog>
`;
}
@ -191,16 +195,11 @@ class HassioRepositoriesDialog extends LitElement {
border-radius: 4px;
margin-top: 4px;
}
mwc-button {
ha-button {
margin-left: 8px;
margin-inline-start: 8px;
margin-inline-end: initial;
}
ha-spinner {
display: block;
margin: 32px;
text-align: center;
}
div.delete ha-icon-button {
color: var(--error-color);
}

View File

@ -1,10 +1,9 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { atLeastVersion } from "../../../src/common/config/version";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-button";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row";
@ -70,12 +69,12 @@ class HassioCoreInfo extends LitElement {
${!atLeastVersion(this.hass.config.version, 2021, 12) &&
this.supervisor.core.update_available
? html`
<a href="/hassio/update-available/core">
<mwc-button
.label=${this.supervisor.localize("common.show")}
>
</mwc-button>
</a>
<ha-button
appearance="plain"
href="/hassio/update-available/core"
>
${this.supervisor.localize("common.show")}
</ha-button>
`
: ""}
</ha-settings-row>
@ -95,7 +94,7 @@ class HassioCoreInfo extends LitElement {
<div class="card-actions">
<ha-progress-button
slot="primaryAction"
class="warning"
variant="danger"
@click=${this._coreRestart}
.title=${this.supervisor.localize("common.restart_name", {
name: "Core",
@ -188,11 +187,6 @@ class HassioCoreInfo extends LitElement {
white-space: normal;
color: var(--secondary-text-color);
}
.warning {
--mdc-theme-primary: var(--error-color);
}
ha-button-menu {
color: var(--secondary-text-color);
--mdc-menu-min-width: 200px;

View File

@ -1,5 +1,3 @@
import "@material/mwc-button";
import { mdiDotsVertical } from "@mdi/js";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
@ -8,10 +6,11 @@ import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-button";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card";
import "../../../src/components/ha-list-item";
import "../../../src/components/ha-icon-button";
import "../../../src/components/ha-list-item";
import "../../../src/components/ha-settings-row";
import {
extractApiErrorMessage,
@ -77,24 +76,28 @@ class HassioHostInfo extends LitElement {
<span slot="description">
${this.supervisor.host.hostname}
</span>
<mwc-button
.label=${this.supervisor.localize("system.host.change")}
<ha-button
@click=${this._changeHostnameClicked}
appearance="plain"
size="small"
>
</mwc-button>
${this.supervisor.localize("system.host.change")}
</ha-button>
</ha-settings-row>`
: ""}
${this.supervisor.host.features.includes("network")
? html` <ha-settings-row>
? html`<ha-settings-row>
<span slot="heading">
${this.supervisor.localize("system.host.ip_address")}
</span>
<span slot="description"> ${primaryIpAddress} </span>
<mwc-button
.label=${this.supervisor.localize("system.host.change")}
<ha-button
@click=${this._changeNetworkClicked}
appearance="plain"
size="small"
>
</mwc-button>
${this.supervisor.localize("system.host.change")}
</ha-button>
</ha-settings-row>`
: ""}
@ -108,12 +111,13 @@ class HassioHostInfo extends LitElement {
${!atLeastVersion(this.hass.config.version, 2021, 12) &&
this.supervisor.os.update_available
? html`
<a href="/hassio/update-available/os">
<mwc-button
.label=${this.supervisor.localize("common.show")}
>
</mwc-button>
</a>
<ha-button
appearance="plain"
size="small"
href="/hassio/update-available/os"
>
${this.supervisor.localize("common.show")}
</ha-button>
`
: ""}
</ha-settings-row>
@ -167,7 +171,7 @@ class HassioHostInfo extends LitElement {
<div class="card-actions">
${this.supervisor.host.features.includes("reboot")
? html`
<ha-progress-button class="warning" @click=${this._hostReboot}>
<ha-progress-button variant="danger" @click=${this._hostReboot}>
${this.supervisor.localize("system.host.reboot_host")}
</ha-progress-button>
`
@ -175,7 +179,7 @@ class HassioHostInfo extends LitElement {
${this.supervisor.host.features.includes("shutdown")
? html`
<ha-progress-button
class="warning"
variant="danger"
@click=${this._hostShutdown}
>
${this.supervisor.localize("system.host.shutdown_host")}
@ -431,10 +435,6 @@ class HassioHostInfo extends LitElement {
color: var(--secondary-text-color);
}
.warning {
--mdc-theme-primary: var(--error-color);
}
ha-button-menu {
color: var(--secondary-text-color);
--mdc-menu-min-width: 200px;

View File

@ -5,6 +5,7 @@ import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-alert";
import "../../../src/components/ha-button";
import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row";
import "../../../src/components/ha-switch";
@ -80,12 +81,13 @@ class HassioSupervisorInfo extends LitElement {
${!atLeastVersion(this.hass.config.version, 2021, 12) &&
this.supervisor.supervisor.update_available
? html`
<a href="/hassio/update-available/supervisor">
<mwc-button
.label=${this.supervisor.localize("common.show")}
>
</mwc-button>
</a>
<ha-button
appearance="plain"
size="small"
href="/hassio/update-available/supervisor"
>
${this.supervisor.localize("common.show")}
</ha-button>
`
: ""}
</ha-settings-row>
@ -156,24 +158,28 @@ class HassioSupervisorInfo extends LitElement {
${this.supervisor.localize(
"system.supervisor.unsupported_title"
)}
<mwc-button
<ha-button
slot="action"
.label=${this.supervisor.localize("common.learn_more")}
@click=${this._unsupportedDialog}
variant="warning"
size="small"
>
</mwc-button>
${this.supervisor.localize("common.learn_more")}
</ha-button>
</ha-alert>`}
${!this.supervisor.supervisor.healthy
? html`<ha-alert alert-type="error">
${this.supervisor.localize(
"system.supervisor.unhealthy_title"
)}
<mwc-button
<ha-button
variant="danger"
size="small"
slot="action"
.label=${this.supervisor.localize("common.learn_more")}
@click=${this._unhealthyDialog}
>
</mwc-button>
${this.supervisor.localize("common.learn_more")}
</ha-button>
</ha-alert>`
: ""}
</div>
@ -448,9 +454,6 @@ class HassioSupervisorInfo extends LitElement {
white-space: normal;
color: var(--secondary-text-color);
}
ha-alert mwc-button {
--mdc-theme-primary: var(--primary-text-color);
}
a {
text-decoration: none;
}

View File

@ -1,5 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";

View File

@ -64,7 +64,7 @@ class LandingPageLogs extends LitElement {
protected render() {
return html`
<div class="actions">
<ha-button @click=${this._toggleLogDetails}>
<ha-button appearance="plain" @click=${this._toggleLogDetails}>
${this.localize(this._show ? "hide_details" : "show_details")}
</ha-button>
${this._show
@ -81,7 +81,11 @@ class LandingPageLogs extends LitElement {
alert-type="error"
.title=${this.localize("logs.fetch_error")}
>
<ha-button @click=${this._startLogStream}>
<ha-button
size="small"
variant="danger"
@click=${this._startLogStream}
>
${this.localize("logs.retry")}
</ha-button>
</ha-alert>

View File

@ -67,6 +67,7 @@ class LandingPageNetwork extends LitElement {
${ALTERNATIVE_DNS_SERVERS.map(
({ translationKey }, key) =>
html`<ha-button
size="small"
.index=${key}
.disabled=${!dnsPrimaryInterfaceNameservers}
@click=${this._setDns}

View File

@ -26,6 +26,7 @@
"license": "Apache-2.0",
"type": "module",
"dependencies": {
"@awesome.me/webawesome": "3.0.0-beta.3",
"@babel/runtime": "7.28.2",
"@braintree/sanitize-url": "7.1.1",
"@codemirror/autocomplete": "6.18.6",

View File

@ -1,5 +1,4 @@
/* eslint-disable lit/prefer-static-styles */
import "@material/mwc-button";
import { genClientId } from "home-assistant-js-websocket";
import type { PropertyValues } from "lit";
import { html, LitElement, nothing } from "lit";
@ -7,6 +6,7 @@ import { keyed } from "lit/directives/keyed";
import { customElement, property, state } from "lit/decorators";
import type { LocalizeFunc } from "../common/translations/localize";
import "../components/ha-alert";
import "../components/ha-button";
import "../components/ha-checkbox";
import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data";
import "../components/ha-formfield";
@ -173,15 +173,14 @@ export class HaAuthFlow extends LitElement {
return html`
${this._renderStep(this.step)}
<div class="action">
<mwc-button
raised
<ha-button
@click=${this._handleSubmit}
.disabled=${this._submitting}
>
${this.step.type === "form"
? this.localize("ui.panel.page-authorize.form.next")
: this.localize("ui.panel.page-authorize.form.start_over")}
</mwc-button>
</ha-button>
</div>
`;
case "error":
@ -192,9 +191,9 @@ export class HaAuthFlow extends LitElement {
})}
</ha-alert>
<div class="action">
<mwc-button raised @click=${this._startOver}>
<ha-button @click=${this._startOver}>
${this.localize("ui.panel.page-authorize.form.start_over")}
</mwc-button>
</ha-button>
</div>
`;
case "loading":

View File

@ -83,6 +83,9 @@ export const applyThemesOnElement = (
themeRules["light-primary-color"] = rgb2hex(rgbLightPrimaryColor);
themeRules["dark-primary-color"] = lab2hex(labDarken(labPrimaryColor));
themeRules["darker-primary-color"] = lab2hex(
labDarken(labPrimaryColor, 2)
);
themeRules["text-primary-color"] =
rgbContrast(rgbPrimaryColor, [33, 33, 33]) < 6 ? "#fff" : "#212121";
themeRules["text-light-primary-color"] =

View File

@ -30,6 +30,7 @@ class HaCallServiceButton extends LitElement {
<ha-progress-button
.progress=${this.progress}
.disabled=${this.disabled}
appearance="plain"
@click=${this._buttonTapped}
tabindex="0"
>

View File

@ -2,7 +2,9 @@ import { mdiAlertOctagram, mdiCheckBold } from "@mdi/js";
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";
import "../ha-button";
import type { Appearance } from "../ha-button";
import "../ha-spinner";
import "../ha-svg-icon";
@ -12,28 +14,47 @@ export class HaProgressButton extends LitElement {
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public progress = false;
@property({ type: Boolean, reflect: true }) public progress = false;
@property({ type: Boolean }) public raised = false;
@property() appearance: Appearance = "accent";
@property({ type: Boolean }) public unelevated = false;
@property({ attribute: false }) public iconPath?: string;
@property() variant: "brand" | "danger" | "neutral" | "warning" | "success" =
"brand";
@state() private _result?: "success" | "error";
public render(): TemplateResult {
const overlay = this._result || this.progress;
const appearance =
this.progress || this._result ? "accent" : this.appearance;
return html`
<ha-button
.raised=${this.raised}
.label=${this.label}
.unelevated=${this.unelevated}
.disabled=${this.disabled || this.progress}
class=${this._result || ""}
.appearance=${appearance}
.disabled=${this.disabled}
.loading=${this.progress}
.variant=${this._result === "success"
? "success"
: this._result === "error"
? "danger"
: this.variant}
class=${classMap({
result: !!this._result,
success: this._result === "success",
error: this._result === "error",
})}
>
<slot name="icon" slot="icon"></slot>
<slot></slot>
${this.iconPath
? html`<ha-svg-icon
.path=${this.iconPath}
slot="start"
></ha-svg-icon>`
: nothing}
<slot>${this.label}</slot>
</ha-button>
${!overlay
${!this._result
? nothing
: html`
<div class="progress">
@ -41,9 +62,7 @@ export class HaProgressButton extends LitElement {
? html`<ha-svg-icon .path=${mdiCheckBold}></ha-svg-icon>`
: this._result === "error"
? html`<ha-svg-icon .path=${mdiAlertOctagram}></ha-svg-icon>`
: this.progress
? html`<ha-spinner size="small"></ha-spinner>`
: nothing}
: nothing}
</div>
`}
`;
@ -69,60 +88,36 @@ export class HaProgressButton extends LitElement {
outline: none;
display: inline-block;
position: relative;
}
:host([progress]) {
pointer-events: none;
}
ha-button {
transition: all 1s;
pointer-events: initial;
}
ha-button.success {
--mdc-theme-primary: white;
background-color: var(--success-color);
transition: none;
border-radius: 4px;
pointer-events: none;
}
ha-button[unelevated].success,
ha-button[raised].success {
--mdc-theme-primary: var(--success-color);
--mdc-theme-on-primary: white;
}
ha-button.error {
--mdc-theme-primary: white;
background-color: var(--error-color);
transition: none;
border-radius: 4px;
pointer-events: none;
}
ha-button[unelevated].error,
ha-button[raised].error {
--mdc-theme-primary: var(--error-color);
--mdc-theme-on-primary: white;
}
.progress {
bottom: 4px;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
text-align: center;
top: 4px;
top: 0;
width: 100%;
}
ha-svg-icon {
color: white;
ha-button {
width: 100%;
}
ha-button.success slot,
ha-button.error slot {
ha-button.result::part(start),
ha-button.result::part(end),
ha-button.result::part(label),
ha-button.result::part(caret),
ha-button.result::part(spinner) {
visibility: hidden;
}
:host([destructive]) {
--mdc-theme-primary: var(--error-color);
ha-svg-icon {
color: var(--white);
}
`;
}

View File

@ -152,7 +152,10 @@ export class DialogDataTableSettings extends LitElement {
)}
</ha-list>
</ha-sortable>
<ha-button slot="secondaryAction" @click=${this._reset}
<ha-button
appearance="plain"
slot="secondaryAction"
@click=${this._reset}
>${localize("ui.components.data-table.settings.restore")}</ha-button
>
<ha-button slot="primaryAction" @click=${this.closeDialog}>

View File

@ -932,7 +932,7 @@ export class HaDataTable extends LitElement {
.find((el) =>
[
"ha-checkbox",
"mwc-button",
"ha-button",
"ha-button",
"ha-icon-button",
"ha-assist-chip",

View File

@ -131,7 +131,6 @@ class HaAlert extends LitElement {
margin-top: 2px;
font-weight: var(--ha-font-weight-bold);
}
.action mwc-button,
.action ha-icon-button {
--mdc-theme-primary: var(--primary-text-color);
--mdc-icon-button-size: 36px;

View File

@ -1,4 +1,3 @@
import type { Button } from "@material/mwc-button";
import type { Corner, Menu, MenuCorner } from "@material/mwc-menu";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
@ -6,6 +5,7 @@ import { customElement, property, query } from "lit/decorators";
import { mainWindow } from "../common/dom/get_main_window";
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
import type { HaIconButton } from "./ha-icon-button";
import type { HaButton } from "./ha-button";
import "./ha-menu";
@customElement("ha-button-menu")
@ -93,8 +93,8 @@ export class HaButtonMenu extends LitElement {
private get _triggerButton() {
return this.querySelector(
'ha-icon-button[slot="trigger"], ha-button[slot="trigger"], mwc-button[slot="trigger"]'
) as HaIconButton | Button | null;
'ha-icon-button[slot="trigger"], ha-button[slot="trigger"]'
) as HaIconButton | HaButton | null;
}
private _setTriggerAria() {

View File

@ -1,33 +1,177 @@
import { Button } from "@material/mwc-button";
import { css } from "lit";
import Button from "@awesome.me/webawesome/dist/components/button/button";
import { css, type CSSResultGroup } from "lit";
import { customElement } from "lit/decorators";
import { styles } from "@material/mwc-button/styles.css";
import { StateSet } from "../resources/polyfills/stateset";
export type Appearance = "accent" | "filled" | "outlined" | "plain";
/**
* Home Assistant button component
*
* @element ha-button
* @extends {Button}
*
* @summary
* A stylable button component supporting Home Assistant theming, variants, and appearances based on webawesome button.
*
* @slot - Label of the button
* @slot start - The prefix container (usually for icons).
* @slot end - The suffix container (usually for icons).
*
* @csspart base - The component's base wrapper.
* @csspart start - The container that wraps the prefix.
* @csspart label - The button's label.
* @csspart end - The container that wraps the suffix.
* @csspart caret - The button's caret icon, an `<sl-icon>` element.
* @csspart spinner - The spinner that shows when the button is in the loading state.
*
* @cssprop --ha-button-height - The height of the button.
* @cssprop --ha-button-radius - The border radius of the button. defaults to `var(--wa-border-radius-pill)`.
*
* @attr {("small"|"medium")} size - Sets the button size.
* @attr {("brand"|"neutral"|"danger"|"warning"|"success")} variant - Sets the button color variant. "primary" is default.
* @attr {("accent"|"filled"|"plain")} appearance - Sets the button appearance.
* @attr {boolean} hideContent - Hides the button content (for overlays).
*/
@customElement("ha-button")
export class HaButton extends Button {
static override styles = [
styles,
css`
::slotted([slot="icon"]) {
margin-inline-start: 0px;
margin-inline-end: 8px;
direction: var(--direction);
display: block;
}
.mdc-button {
height: var(--button-height, 36px);
}
.trailing-icon {
display: flex;
}
.slot-container {
overflow: var(--button-slot-container-overflow, visible);
}
:host([destructive]) {
--mdc-theme-primary: var(--error-color);
}
`,
];
variant: "brand" | "neutral" | "success" | "warning" | "danger" = "brand";
attachInternals() {
const internals = super.attachInternals();
Object.defineProperty(internals, "states", {
value: new StateSet(this, internals.states),
});
return internals;
}
static get styles(): CSSResultGroup {
return [
Button.styles,
css`
.button {
/* set theme vars */
--wa-form-control-padding-inline: 16px;
--wa-font-weight-action: var(--ha-font-weight-medium);
--wa-border-radius-pill: 9999px;
--wa-form-control-border-radius: var(
--ha-button-radius,
var(--wa-border-radius-pill)
);
--wa-form-control-height: var(
--ha-button-height,
var(--button-height, 40px)
);
font-size: var(--ha-font-size-m);
}
:host([size="small"]) .button {
--wa-form-control-height: var(
--ha-button-height,
var(--button-height, 32px)
);
font-size: var(--wa-font-size-s, var(--ha-font-size-m));
}
:host([variant="brand"]) {
--color-fill-normal-active: var(--color-fill-primary-normal-active);
--color-fill-normal-hover: var(--color-fill-primary-normal-hover);
--color-fill-loud-active: var(--color-fill-primary-loud-active);
--color-fill-loud-hover: var(--color-fill-primary-loud-hover);
}
:host([variant="neutral"]) {
--color-fill-normal-active: var(--color-fill-neutral-normal-active);
--color-fill-normal-hover: var(--color-fill-neutral-normal-hover);
--color-fill-loud-active: var(--color-fill-neutral-loud-active);
--color-fill-loud-hover: var(--color-fill-neutral-loud-hover);
}
:host([variant="success"]) {
--color-fill-normal-active: var(--color-fill-success-normal-active);
--color-fill-normal-hover: var(--color-fill-success-normal-hover);
--color-fill-loud-active: var(--color-fill-success-loud-active);
--color-fill-loud-hover: var(--color-fill-success-loud-hover);
}
:host([variant="warning"]) {
--color-fill-normal-active: var(--color-fill-warning-normal-active);
--color-fill-normal-hover: var(--color-fill-warning-normal-hover);
--color-fill-loud-active: var(--color-fill-warning-loud-active);
--color-fill-loud-hover: var(--color-fill-warning-loud-hover);
}
:host([variant="danger"]) {
--color-fill-normal-active: var(--color-fill-danger-normal-active);
--color-fill-normal-hover: var(--color-fill-danger-normal-hover);
--color-fill-loud-active: var(--color-fill-danger-loud-active);
--color-fill-loud-hover: var(--color-fill-danger-loud-hover);
}
:host([appearance~="plain"]) .button {
color: var(--wa-color-on-normal);
}
:host([appearance~="plain"]) .button.disabled {
background-color: var(--transparent-none);
color: var(--color-on-disabled-quiet);
}
:host([appearance~="outlined"]) .button.disabled {
background-color: var(--transparent-none);
color: var(--color-on-disabled-quiet);
}
@media (hover: hover) {
:host([appearance~="filled"])
.button:not(.disabled):not(.loading):hover {
background-color: var(--color-fill-normal-hover);
}
:host([appearance~="accent"])
.button:not(.disabled):not(.loading):hover {
background-color: var(--color-fill-loud-hover);
}
:host([appearance~="plain"])
.button:not(.disabled):not(.loading):hover {
color: var(--wa-color-on-normal);
}
}
:host([appearance~="filled"])
.button:not(.disabled):not(.loading):active {
background-color: var(--color-fill-normal-active);
}
:host([appearance~="filled"]) .button.disabled {
background-color: var(--color-fill-disabled-normal-resting);
color: var(--color-on-disabled-normal);
}
:host([appearance~="accent"]) .button {
background-color: var(
--wa-color-fill-loud,
var(--wa-color-neutral-fill-loud)
);
}
:host([appearance~="accent"])
.button:not(.disabled):not(.loading):active {
background-color: var(--color-fill-loud-active);
}
:host([appearance~="accent"]) .button.disabled {
background-color: var(--color-fill-disabled-loud-resting);
color: var(--color-on-disabled-loud);
}
:host([loading]) {
pointer-events: none;
}
.button.disabled {
opacity: 1;
}
`,
];
}
}
declare global {

View File

@ -63,7 +63,7 @@ export class HaCard extends LitElement {
:host ::slotted(.card-actions) {
border-top: 1px solid var(--divider-color, #e8e8e8);
padding: 5px 16px;
padding: 8px;
}
`;

View File

@ -1,14 +1,14 @@
import { customElement, property, state } from "lit/decorators";
import { css, html, LitElement, nothing } from "lit";
import { mdiContentCopy, mdiEye, mdiEyeOff } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { copyToClipboard } from "../common/util/copy-clipboard";
import type { HomeAssistant } from "../types";
import { showToast } from "../util/toast";
import "./ha-button";
import "./ha-icon-button";
import "./ha-svg-icon";
import "./ha-textfield";
import type { HomeAssistant } from "../types";
import { copyToClipboard } from "../common/util/copy-clipboard";
import { showToast } from "../util/toast";
import type { HaTextField } from "./ha-textfield";
@customElement("ha-copy-textfield")
@ -48,8 +48,8 @@ export class HaCopyTextfield extends LitElement {
></ha-icon-button>`
: nothing}
</div>
<ha-button @click=${this._copy} unelevated>
<ha-svg-icon slot="icon" .path=${mdiContentCopy}></ha-svg-icon>
<ha-button @click=${this._copy} appearance="plain" size="small">
<ha-svg-icon slot="start" .path=${mdiContentCopy}></ha-svg-icon>
${this.label || this.hass.localize("ui.common.copy")}
</ha-button>
</div>

View File

@ -1,5 +1,3 @@
import "@material/mwc-button/mwc-button";
import type { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import { mdiCalendar } from "@mdi/js";
@ -22,6 +20,7 @@ import { fireEvent } from "../common/dom/fire_event";
import { TimeZone } from "../data/translation";
import type { HomeAssistant } from "../types";
import "./date-range-picker";
import "./ha-button";
import "./ha-icon-button";
import "./ha-icon-button-next";
import "./ha-icon-button-prev";
@ -197,13 +196,13 @@ export class HaDateRangePicker extends LitElement {
</div>`
: nothing}
<div slot="footer" class="date-range-footer">
<mwc-button @click=${this._cancelDateRange}
>${this.hass.localize("ui.common.cancel")}</mwc-button
<ha-button appearance="plain" @click=${this._cancelDateRange}
>${this.hass.localize("ui.common.cancel")}</ha-button
>
<mwc-button @click=${this._applyDateRange}
<ha-button @click=${this._applyDateRange}
>${this.hass.localize(
"ui.components.date-range-picker.select"
)}</mwc-button
)}</ha-button
>
</div>
</date-range-picker>

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import "app-datepicker";
import { format } from "date-fns";
import { css, html, LitElement, nothing } from "lit";
@ -9,6 +8,7 @@ import { haStyleDialog } from "../resources/styles";
import type { HomeAssistant } from "../types";
import type { DatePickerDialogParams } from "./ha-date-input";
import "./ha-dialog";
import "./ha-button";
@customElement("ha-dialog-date-picker")
export class HaDialogDatePicker extends LitElement {
@ -51,23 +51,33 @@ export class HaDialogDatePicker extends LitElement {
.firstDayOfWeek=${this._params.firstWeekday}
></app-datepicker>
${this._params.canClear
? html`<mwc-button
? html`<ha-button
slot="secondaryAction"
@click=${this._clear}
class="warning"
variant="danger"
appearance="plain"
>
${this.hass.localize("ui.dialogs.date-picker.clear")}
</mwc-button>`
</ha-button>`
: nothing}
<mwc-button slot="secondaryAction" @click=${this._setToday}>
<ha-button
appearance="plain"
slot="secondaryAction"
@click=${this._setToday}
>
${this.hass.localize("ui.dialogs.date-picker.today")}
</mwc-button>
<mwc-button slot="primaryAction" dialogaction="cancel" class="cancel-btn">
</ha-button>
<ha-button
appearance="plain"
slot="primaryAction"
dialogaction="cancel"
class="cancel-btn"
>
${this.hass.localize("ui.common.cancel")}
</mwc-button>
<mwc-button slot="primaryAction" @click=${this._setValue}>
</ha-button>
<ha-button slot="primaryAction" @click=${this._setValue}>
${this.hass.localize("ui.common.ok")}
</mwc-button>
</ha-button>
</ha-dialog>`;
}

View File

@ -64,7 +64,7 @@ export class HaDialogHeader extends LitElement {
}
@media all and (min-width: 450px) and (min-height: 500px) {
.header-bar {
padding: 12px;
padding: 16px;
}
}
.header-navigation-icon {

View File

@ -90,7 +90,7 @@ export class HaDialog extends DialogBase {
}
.mdc-dialog__actions {
justify-content: var(--justify-action-buttons, flex-end);
padding: 12px 24px max(var(--safe-area-inset-bottom), 12px) 24px;
padding: 12px 16px max(var(--safe-area-inset-bottom), 16px) 16px;
}
.mdc-dialog__actions span:nth-child(1) {
flex: var(--secondary-action-button-flex, unset);
@ -102,7 +102,7 @@ export class HaDialog extends DialogBase {
align-items: var(--vertical-align-dialog, center);
}
.mdc-dialog__title {
padding: 24px 24px 0 24px;
padding: 16px 16px 0 16px;
}
.mdc-dialog__title:has(span) {
padding: 12px 12px 0;
@ -125,7 +125,7 @@ export class HaDialog extends DialogBase {
top: var(--dialog-surface-top);
margin-top: var(--dialog-surface-margin-top);
min-height: var(--mdc-dialog-min-height, auto);
border-radius: var(--ha-dialog-border-radius, 28px);
border-radius: var(--ha-dialog-border-radius, 24px);
-webkit-backdrop-filter: var(--ha-dialog-surface-backdrop-filter, none);
backdrop-filter: var(--ha-dialog-surface-backdrop-filter, none);
background: var(

View File

@ -14,6 +14,12 @@ export class HaFab extends FabBase {
static override styles = [
styles,
css`
:host {
--mdc-typography-button-text-transform: none;
--mdc-typography-button-font-size: var(--ha-font-size-l);
--mdc-typography-button-font-family: var(--ha-font-family-body);
--mdc-typography-button-font-weight: var(--ha-font-weight-medium);
}
:host .mdc-fab--extended .mdc-fab__icon {
margin-inline-start: -8px;
margin-inline-end: 12px;

View File

@ -118,11 +118,15 @@ export class HaFileUpload extends LitElement {
@dragleave=${this._handleDragEnd}
@dragend=${this._handleDragEnd}
>${!this.value
? html`<ha-svg-icon
class="big-icon"
.path=${this.icon || mdiFileUpload}
></ha-svg-icon>
<ha-button unelevated @click=${this._openFilePicker}>
? html`<ha-button
size="small"
appearance="filled"
@click=${this._openFilePicker}
>
<ha-svg-icon
slot="start"
.path=${this.icon || mdiFileUpload}
></ha-svg-icon>
${this.label || localize("ui.components.file-upload.label")}
</ha-button>
<span class="secondary"
@ -291,7 +295,7 @@ export class HaFileUpload extends LitElement {
color: var(--primary-color);
}
ha-button {
margin-bottom: 4px;
margin-bottom: 8px;
}
.supports {
color: var(--secondary-text-color);
@ -311,10 +315,6 @@ export class HaFileUpload extends LitElement {
margin-inline-end: 8px;
margin-inline-start: initial;
}
.big-icon {
--mdc-icon-size: 48px;
margin-bottom: 8px;
}
ha-button {
--mdc-button-outline-color: var(--primary-color);
--mdc-icon-button-size: 24px;

View File

@ -1,3 +1,4 @@
import { mdiPlus } from "@mdi/js";
import type { PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -5,12 +6,14 @@ import memoizeOne from "memoize-one";
import { stopPropagation } from "../../common/dom/stop_propagation";
import type { LocalizeFunc } from "../../common/translations/localize";
import type { HomeAssistant } from "../../types";
import "./ha-form";
import "../ha-button";
import "../ha-list-item";
import "../ha-svg-icon";
import "./ha-form";
import type {
HaFormOptionalActionsSchema,
HaFormDataContainer,
HaFormElement,
HaFormOptionalActionsSchema,
HaFormSchema,
} from "./types";
@ -118,7 +121,8 @@ export class HaFormOptionalActions extends LitElement implements HaFormElement {
fixed
@closed=${stopPropagation}
>
<ha-button slot="trigger">
<ha-button slot="trigger" appearance="filled" size="small">
<ha-svg-icon .path=${mdiPlus} slot="start"></ha-svg-icon>
${this.localize?.("ui.components.form-optional-actions.add") ||
"Add interaction"}
</ha-button>

View File

@ -1,7 +1,7 @@
import "@material/mwc-button";
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators";
import { supportsFeature } from "../common/entity/supports-feature";
import "./ha-button";
import type { LawnMowerEntity, LawnMowerEntityState } from "../data/lawn_mower";
import { LawnMowerEntityFeature } from "../data/lawn_mower";
import type { HomeAssistant } from "../types";
@ -49,16 +49,21 @@ class HaLawnMowerActionButton extends LitElement {
if (action && supportsFeature(this.stateObj, action.feature)) {
return html`
<mwc-button @click=${this.callService} .service=${action.service}>
<ha-button
appearance="plain"
@click=${this.callService}
.service=${action.service}
size="small"
>
${this.hass.localize(`ui.card.lawn_mower.actions.${action.action}`)}
</mwc-button>
</ha-button>
`;
}
return html`
<mwc-button disabled>
<ha-button appearance="plain" disabled>
${this.hass.formatEntityState(this.stateObj)}
</mwc-button>
</ha-button>
`;
}
@ -72,17 +77,13 @@ class HaLawnMowerActionButton extends LitElement {
}
static styles = css`
mwc-button {
ha-button {
top: 3px;
height: 37px;
margin-right: -0.57em;
margin-inline-end: -0.57em;
margin-inline-start: initial;
}
mwc-button[disabled] {
background-color: transparent;
color: var(--secondary-text-color);
}
`;
}

View File

@ -1,9 +1,9 @@
import type { Button } from "@material/mwc-button";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, query } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
import type { HaButton } from "./ha-button";
import type { HaIconButton } from "./ha-icon-button";
import "./ha-md-menu";
import type { HaMdMenu } from "./ha-md-menu";
@ -71,8 +71,8 @@ export class HaMdButtonMenu extends LitElement {
private get _triggerButton() {
return this.querySelector(
'ha-icon-button[slot="trigger"], mwc-button[slot="trigger"], ha-assist-chip[slot="trigger"]'
) as HaIconButton | Button | null;
'ha-icon-button[slot="trigger"], ha-button[slot="trigger"], ha-assist-chip[slot="trigger"]'
) as HaIconButton | HaButton | null;
}
private _setTriggerAria() {

View File

@ -183,6 +183,10 @@ export class HaMdDialog extends Dialog {
display: contents;
}
slot[name="actions"]::slotted(*) {
padding: 16px;
}
.scroller {
overflow: var(--dialog-content-overflow, auto);
}

View File

@ -73,7 +73,12 @@ class HaMultiTextField extends LitElement {
`;
})}
<div class="layout horizontal">
<ha-button @click=${this._addItem} .disabled=${this.disabled}>
<ha-button
size="small"
appearance="filled"
@click=${this._addItem}
.disabled=${this.disabled}
>
${this.addLabel ??
(this.label
? this.hass?.localize("ui.components.multi-textfield.add_item", {
@ -81,7 +86,7 @@ class HaMultiTextField extends LitElement {
})
: this.hass?.localize("ui.common.add")) ??
"Add"}
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
<ha-svg-icon slot="end" .path=${mdiPlus}></ha-svg-icon>
</ha-button>
</div>
${this.helper
@ -145,11 +150,6 @@ class HaMultiTextField extends LitElement {
ha-icon-button {
display: block;
}
ha-button {
margin-left: 8px;
margin-inline-start: 8px;
margin-inline-end: initial;
}
`,
];
}

View File

@ -244,9 +244,6 @@ export class HaMediaSelector extends LitElement {
display: block;
margin-bottom: 16px;
}
mwc-button {
margin-top: 8px;
}
ha-alert {
display: block;
margin-bottom: 16px;

View File

@ -138,7 +138,7 @@ export class HaObjectSelector extends LitElement {
${items.map((item, index) => this._renderItem(item, index))}
</ha-md-list>
</ha-sortable>
<ha-button outlined @click=${this._addItem}>
<ha-button appearance="filled" @click=${this._addItem}>
${this.hass.localize("ui.common.add")}
</ha-button>
</div>
@ -153,7 +153,7 @@ export class HaObjectSelector extends LitElement {
${this._renderItem(this.value, 0)}
</ha-md-list>`
: html`
<ha-button outlined @click=${this._addItem}>
<ha-button appearance="filled" @click=${this._addItem}>
${this.hass.localize("ui.common.add")}
</ha-button>
`}

View File

@ -1,6 +1,5 @@
// @ts-ignore
import chipStyles from "@material/chips/dist/mdc.chips.min.css";
import "@material/mwc-button/mwc-button";
import "@material/mwc-menu/mwc-menu-surface";
import {
mdiClose,

View File

@ -1,10 +1,10 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit";
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators";
import type { HassEntity } from "home-assistant-js-websocket";
import { haStyle } from "../resources/styles";
import type { HomeAssistant } from "../types";
import "./ha-button";
const STATES_INTERCEPTABLE: Record<
string,
@ -56,9 +56,14 @@ export class HaVacuumState extends LitElement {
this.stateObj.attributes.supported_features
);
return html`
<mwc-button @click=${this._callService} .disabled=${!interceptable}>
<ha-button
appearance="plain"
size="small"
@click=${this._callService}
.disabled=${!interceptable}
>
${this._computeLabel(this.stateObj.state, interceptable)}
</mwc-button>
</ha-button>
`;
}
@ -92,17 +97,13 @@ export class HaVacuumState extends LitElement {
return [
haStyle,
css`
mwc-button {
ha-button {
top: 3px;
height: 37px;
margin-right: -0.57em;
margin-inline-end: -0.57em;
margin-inline-start: initial;
}
mwc-button[disabled] {
background-color: transparent;
color: var(--secondary-text-color);
}
`,
];
}

View File

@ -1,28 +1,28 @@
import type { CSSResultGroup } from "lit";
import { mdiClose } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket";
import type { CSSResultGroup } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import type { HassEntity } from "home-assistant-js-websocket";
import { fireEvent } from "../../common/dom/fire_event";
import { haStyleDialog } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import "../ha-alert";
import "../ha-dialog";
import "../ha-button";
import "../ha-dialog-header";
import "./ha-media-player-toggle";
import type { JoinMediaPlayersDialogParams } from "./show-join-media-players-dialog";
import { computeDomain } from "../../common/entity/compute_domain";
import { computeStateName } from "../../common/entity/compute_state_name";
import { supportsFeature } from "../../common/entity/supports-feature";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import { extractApiErrorMessage } from "../../data/hassio/common";
import {
type MediaPlayerEntity,
MediaPlayerEntityFeature,
mediaPlayerJoin,
mediaPlayerUnjoin,
} from "../../data/media-player";
import { extractApiErrorMessage } from "../../data/hassio/common";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import { computeDomain } from "../../common/entity/compute_domain";
import { haStyleDialog } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import "../ha-alert";
import "../ha-button";
import "../ha-dialog";
import "../ha-dialog-header";
import "./ha-media-player-toggle";
import type { JoinMediaPlayersDialogParams } from "./show-join-media-players-dialog";
@customElement("dialog-join-media-players")
class DialogJoinMediaPlayers extends LitElement {
@ -90,7 +90,11 @@ class DialogJoinMediaPlayers extends LitElement {
<span slot="title"
>${this.hass.localize("ui.card.media_player.media_players")}</span
>
<ha-button slot="actionItems" @click=${this._selectAll}>
<ha-button
appearance="plain"
slot="actionItems"
@click=${this._selectAll}
>
${this.hass.localize("ui.card.media_player.select_all")}
</ha-button>
</ha-dialog-header>
@ -114,11 +118,15 @@ class DialogJoinMediaPlayers extends LitElement {
></ha-media-player-toggle>`
)}
</div>
<ha-button slot="secondaryAction" @click=${this.closeDialog}>
<ha-button
appearance="plain"
slot="secondaryAction"
@click=${this.closeDialog}
>
${this.hass.localize("ui.common.cancel")}
</ha-button>
<ha-button
.disabled=${this._submitting}
.disabled=${!!this._submitting}
slot="primaryAction"
@click=${this._submit}
>

View File

@ -127,7 +127,7 @@ class DialogMediaManage extends LitElement {
)}
@click=${this._handleDelete}
>
<ha-svg-icon .path=${mdiDelete} slot="icon"></ha-svg-icon>
<ha-svg-icon .path=${mdiDelete} slot="start"></ha-svg-icon>
</ha-button>
${this._deleting

View File

@ -1,10 +1,11 @@
import "@material/mwc-button/mwc-button";
import { mdiContentCopy } from "@mdi/js";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { mdiContentCopy } from "@mdi/js";
import { storage } from "../../common/decorators/storage";
import { fireEvent } from "../../common/dom/fire_event";
import { copyToClipboard } from "../../common/util/copy-clipboard";
import { fetchCloudStatus } from "../../data/cloud";
import type {
MediaPlayerBrowseAction,
MediaPlayerItem,
@ -13,13 +14,12 @@ import type { TTSEngine } from "../../data/tts";
import { getProviderFromTTSMediaSource, getTTSEngine } from "../../data/tts";
import { buttonLinkStyle } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import "../ha-textarea";
import "../ha-language-picker";
import "../ha-tts-voice-picker";
import "../ha-card";
import { fetchCloudStatus } from "../../data/cloud";
import { copyToClipboard } from "../../common/util/copy-clipboard";
import { showToast } from "../../util/toast";
import "../ha-button";
import "../ha-card";
import "../ha-language-picker";
import "../ha-textarea";
import "../ha-tts-voice-picker";
export interface TtsMediaPickedEvent {
item: MediaPlayerItem;
@ -92,11 +92,11 @@ class BrowseMediaTTS extends LitElement {
: nothing}
</div>
<div class="card-actions">
<mwc-button @click=${this._ttsClicked}>
<ha-button appearance="plain" @click=${this._ttsClicked}>
${this.hass.localize(
`ui.components.media-browser.tts.action_${this.action}`
)}
</mwc-button>
</ha-button>
</div>
</ha-card>
${this._voice

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import { mdiFolderEdit } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -10,6 +9,7 @@ import {
} from "../../data/media_source";
import type { HomeAssistant } from "../../types";
import "../ha-svg-icon";
import "../ha-button";
import { showMediaManageDialog } from "./show-media-manage-dialog";
declare global {
@ -38,14 +38,12 @@ class MediaManageButton extends LitElement {
return nothing;
}
return html`
<mwc-button
.label=${this.hass.localize(
<ha-button appearance="plain" size="small" @click=${this._manage}>
<ha-svg-icon .path=${mdiFolderEdit} slot="start"></ha-svg-icon>
${this.hass.localize(
"ui.components.media-browser.file_management.manage"
)}
@click=${this._manage}
>
<ha-svg-icon .path=${mdiFolderEdit} slot="icon"></ha-svg-icon>
</mwc-button>
</ha-button>
`;
}
@ -57,11 +55,6 @@ class MediaManageButton extends LitElement {
}
static styles = css`
mwc-button {
/* We use icon + text to show disabled state */
--mdc-button-disabled-ink-color: --mdc-theme-primary;
}
ha-svg-icon[slot="icon"] {
vertical-align: middle;
}

View File

@ -1,6 +1,5 @@
import type { LitVirtualizer } from "@lit-labs/virtualizer";
import { grid } from "@lit-labs/virtualizer/layouts/grid";
import "@material/mwc-button/mwc-button";
import { mdiArrowUpRight, mdiPlay, mdiPlus } from "@mdi/js";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
@ -42,6 +41,7 @@ import {
import { documentationUrl } from "../../util/documentation-url";
import "../entity/ha-entity-picker";
import "../ha-alert";
import "../ha-button";
import "../ha-button-menu";
import "../ha-card";
import "../ha-spinner";
@ -440,8 +440,7 @@ export class HaMediaPlayerBrowse extends LitElement {
${currentItem.can_play &&
(!currentItem.thumbnail || !this.narrow)
? html`
<mwc-button
raised
<ha-button
.item=${currentItem}
@click=${this._actionClicked}
>
@ -452,11 +451,12 @@ export class HaMediaPlayerBrowse extends LitElement {
.path=${this.action === "play"
? mdiPlay
: mdiPlus}
slot="start"
></ha-svg-icon>
${this.hass.localize(
`ui.components.media-browser.${this.action}`
)}
</mwc-button>
</ha-button>
`
: ""}
</div>
@ -990,9 +990,8 @@ export class HaMediaPlayerBrowse extends LitElement {
min-width: 0;
flex: 1;
}
.header-info mwc-button {
.header-info ha-button {
display: block;
--mdc-theme-primary: var(--primary-color);
padding-bottom: 16px;
}
.breadcrumb {
@ -1284,7 +1283,7 @@ export class HaMediaPlayerBrowse extends LitElement {
bottom: -20px;
right: 20px;
}
:host([narrow]) .header-info mwc-button {
:host([narrow]) .header-info ha-button {
margin-top: 16px;
margin-bottom: 8px;
}
@ -1303,17 +1302,17 @@ export class HaMediaPlayerBrowse extends LitElement {
:host(:not([narrow])[scrolled]) .header:not(.no-img) ha-icon-button {
align-self: center;
}
:host([scrolled]) .header-info mwc-button,
.no-img .header-info mwc-button {
:host([scrolled]) .header-info ha-button,
.no-img .header-info ha-button {
padding-right: 4px;
}
:host([scrolled][narrow]) .no-img .header-info mwc-button {
:host([scrolled][narrow]) .no-img .header-info ha-button {
padding-right: 16px;
}
:host([scrolled]) .header-info {
flex-direction: row;
}
:host([scrolled]) .header-info mwc-button {
:host([scrolled]) .header-info ha-button {
align-self: center;
margin-top: 0;
margin-bottom: 0;

View File

@ -1,6 +1,5 @@
import "@material/mwc-button";
import { mdiUpload } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import type { MediaPlayerItem } from "../../data/media-player";
@ -10,7 +9,7 @@ import {
} from "../../data/media_source";
import { showAlertDialog } from "../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../types";
import "../ha-spinner";
import "../ha-button";
import "../ha-svg-icon";
declare global {
@ -36,8 +35,13 @@ class MediaUploadButton extends LitElement {
return nothing;
}
return html`
<mwc-button
.label=${this._uploading > 0
<ha-button
.disabled=${this._uploading > 0}
@click=${this._startUpload}
.loading=${this._uploading > 0}
>
<ha-svg-icon .path=${mdiUpload} slot="start"></ha-svg-icon>
${this._uploading > 0
? this.hass.localize(
"ui.components.media-browser.file_management.uploading",
{
@ -47,19 +51,7 @@ class MediaUploadButton extends LitElement {
: this.hass.localize(
"ui.components.media-browser.file_management.add_media"
)}
.disabled=${this._uploading > 0}
@click=${this._startUpload}
>
${this._uploading > 0
? html`
<ha-spinner
size="small"
area-label="Uploading"
slot="icon"
></ha-spinner>
`
: html` <ha-svg-icon .path=${mdiUpload} slot="icon"></ha-svg-icon> `}
</mwc-button>
</ha-button>
`;
}
@ -107,24 +99,6 @@ class MediaUploadButton extends LitElement {
document.body.append(input);
input.click();
}
static styles = css`
mwc-button {
/* We use icon + text to show disabled state */
--mdc-button-disabled-ink-color: --mdc-theme-primary;
}
ha-svg-icon[slot="icon"],
ha-spinner[slot="icon"] {
vertical-align: middle;
}
ha-svg-icon[slot="icon"] {
margin-inline-start: 0px;
margin-inline-end: 8px;
direction: var(--direction);
}
`;
}
declare global {

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -6,6 +5,7 @@ import { fireEvent } from "../../common/dom/fire_event";
import { createCloseHeading } from "../../components/ha-dialog";
import "../../components/ha-formfield";
import "../../components/ha-switch";
import "../../components/ha-button";
import type { HaSwitch } from "../../components/ha-switch";
import type { ConfigEntryMutableParams } from "../../data/config_entries";
import { updateConfigEntry } from "../../data/config_entries";
@ -113,20 +113,21 @@ class DialogConfigEntrySystemOptions extends LitElement {
.disabled=${this._submitting}
></ha-switch>
</ha-formfield>
<mwc-button
slot="secondaryAction"
<ha-button
appearance="plain"
slot="primaryAction"
@click=${this.closeDialog}
.disabled=${this._submitting}
>
${this.hass.localize("ui.common.cancel")}
</mwc-button>
<mwc-button
</ha-button>
<ha-button
slot="primaryAction"
@click=${this._updateEntry}
.disabled=${this._submitting}
>
${this.hass.localize("ui.dialogs.config_entry_system_options.update")}
</mwc-button>
</ha-button>
</ha-dialog>
`;
}

View File

@ -7,6 +7,7 @@ import { ifDefined } from "lit/directives/if-defined";
import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/entity/ha-entity-toggle";
import "../../../components/entity/state-badge";
import "../../../components/ha-button";
import "../../../components/ha-climate-state";
import "../../../components/ha-cover-controls";
import "../../../components/ha-cover-tilt-controls";
@ -91,7 +92,7 @@ class EntityPreviewRow extends LitElement {
justify-content: flex-end;
width: 100%;
}
mwc-button {
ha-button {
margin-right: -0.57em;
margin-inline-end: -0.57em;
margin-inline-start: initial;
@ -107,9 +108,13 @@ class EntityPreviewRow extends LitElement {
if (domain === "button") {
return html`
<mwc-button .disabled=${isUnavailableState(stateObj.state)}>
<ha-button
appearance="plain"
size="small"
.disabled=${isUnavailableState(stateObj.state)}
>
${this.hass.localize("ui.card.button.press")}
</mwc-button>
</ha-button>
`;
}
@ -232,14 +237,16 @@ class EntityPreviewRow extends LitElement {
if (domain === "lock") {
return html`
<mwc-button
<ha-button
.disabled=${isUnavailableState(stateObj.state)}
class="text-content"
appearance="plain"
size="small"
>
${stateObj.state === "locked"
? this.hass!.localize("ui.card.lock.unlock")
: this.hass!.localize("ui.card.lock.lock")}
</mwc-button>
</ha-button>
`;
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, PropertyValues } from "lit";
import { html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
@ -9,6 +8,7 @@ import type { HomeAssistant } from "../../types";
import { showConfigFlowDialog } from "./show-dialog-config-flow";
import type { DataEntryFlowDialogParams } from "./show-dialog-data-entry-flow";
import { configFlowContentStyles } from "./styles";
import "../../components/ha-button";
@customElement("step-flow-abort")
class StepFlowAbort extends LitElement {
@ -38,10 +38,10 @@ class StepFlowAbort extends LitElement {
${this.params.flowConfig.renderAbortDescription(this.hass, this.step)}
</div>
<div class="buttons">
<mwc-button @click=${this._flowDone}
<ha-button appearance="plain" @click=${this._flowDone}
>${this.hass.localize(
"ui.panel.config.integrations.config_flow.close"
)}</mwc-button
)}</ha-button
>
</div>
`;

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -11,6 +10,7 @@ import {
import { computeDomain } from "../../common/entity/compute_domain";
import { navigate } from "../../common/navigate";
import "../../components/ha-area-picker";
import "../../components/ha-button";
import { assistSatelliteSupportsSetupFlow } from "../../data/assist_satellite";
import type { DataEntryFlowStepCreateEntry } from "../../data/data_entry_flow";
import type { DeviceRegistryEntry } from "../../data/device_registry";
@ -171,10 +171,10 @@ class StepFlowCreateEntry extends LitElement {
`}
</div>
<div class="buttons">
<mwc-button @click=${this._flowDone}
<ha-button @click=${this._flowDone}
>${localize(
`ui.panel.config.integrations.config_flow.${!this.devices.length || Object.keys(this._deviceUpdate).length ? "finish" : "finish_skip"}`
)}</mwc-button
)}</ha-button
>
</div>
`;

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
@ -6,6 +5,7 @@ import type { DataEntryFlowStepExternal } from "../../data/data_entry_flow";
import type { HomeAssistant } from "../../types";
import type { FlowConfig } from "./show-dialog-data-entry-flow";
import { configFlowContentStyles } from "./styles";
import "../../components/ha-button";
@customElement("step-flow-external")
class StepFlowExternal extends LitElement {
@ -22,13 +22,11 @@ class StepFlowExternal extends LitElement {
<div class="content">
${this.flowConfig.renderExternalStepDescription(this.hass, this.step)}
<div class="open-button">
<a href=${this.step.url} target="_blank" rel="noreferrer">
<mwc-button raised>
${localize(
"ui.panel.config.integrations.config_flow.external_step.open_site"
)}
</mwc-button>
</a>
<ha-button href=${this.step.url} target="_blank" rel="noreferrer">
${localize(
"ui.panel.config.integrations.config_flow.external_step.open_site"
)}
</ha-button>
</div>
</div>
`;

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -6,6 +5,7 @@ import memoizeOne from "memoize-one";
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../common/dom/fire_event";
import { isNavigationClick } from "../../common/dom/is-navigation-click";
import "../../components/ha-button";
import "../../components/ha-alert";
import { computeInitialHaFormData } from "../../components/ha-form/compute-initial-ha-form-data";
import "../../components/ha-form/ha-form";
@ -112,12 +112,12 @@ class StepFlowForm extends LitElement {
`
: html`
<div>
<mwc-button @click=${this._submitStep}>
<ha-button @click=${this._submitStep}>
${this.flowConfig.renderShowFormStepSubmitButton(
this.hass,
this.step
)}
</mwc-button>
</ha-button>
</div>
`}
</div>
@ -318,6 +318,10 @@ class StepFlowForm extends LitElement {
margin-top: 24px;
display: block;
}
.buttons {
padding: 8px;
}
`,
];
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";

View File

@ -110,7 +110,11 @@ export class DialogEnterCode
pattern=${ifDefined(this._dialogParams.codePattern)}
inputmode="text"
></ha-textfield>
<ha-button slot="secondaryAction" dialogAction="cancel">
<ha-button
appearance="plain"
slot="secondaryAction"
dialogAction="cancel"
>
${this._dialogParams.cancelText ??
this.hass.localize("ui.common.cancel")}
</ha-button>

View File

@ -4,10 +4,10 @@ import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-button";
import { createCloseHeading } from "../../components/ha-dialog";
import "../../components/ha-form/ha-form";
import { haStyleDialog } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import type { HassDialog } from "../make-dialog-manager";
import type { FormDialogData, FormDialogParams } from "./show-form-dialog";
import { haStyleDialog } from "../../resources/styles";
@customElement("dialog-form")
export class DialogForm
@ -69,7 +69,11 @@ export class DialogForm
@value-changed=${this._valueChanged}
>
</ha-form>
<ha-button @click=${this._cancel} slot="secondaryAction">
<ha-button
appearance="plain"
@click=${this._cancel}
slot="secondaryAction"
>
${this._params.cancelText || this.hass.localize("ui.common.cancel")}
</ha-button>
<ha-button @click=${this._submit} slot="primaryAction">

View File

@ -106,6 +106,7 @@ class DialogBox extends LitElement {
@click=${this._dismiss}
?dialogInitialFocus=${!this._params.prompt &&
this._params.destructive}
appearance="plain"
>
${this._params.dismissText
? this._params.dismissText
@ -116,7 +117,7 @@ class DialogBox extends LitElement {
@click=${this._confirm}
?dialogInitialFocus=${!this._params.prompt &&
!this._params.destructive}
?destructive=${this._params.destructive}
variant=${this._params.destructive ? "danger" : "brand"}
>
${this._params.confirmText
? this._params.confirmText

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import Cropper from "cropperjs";
// @ts-ignore
import cropperCss from "cropperjs/dist/cropper.css";
@ -7,6 +6,7 @@ import { css, html, nothing, LitElement, unsafeCSS } from "lit";
import { customElement, property, state, query } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import "../../components/ha-dialog";
import "../../components/ha-button";
import { haStyleDialog } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import type { HaImageCropperDialogParams } from "./show-image-cropper-dialog";
@ -92,18 +92,26 @@ export class HaImagecropperDialog extends LitElement {
>
<img alt=${this.hass.localize("ui.dialogs.image_cropper.crop_image")} />
</div>
<mwc-button slot="secondaryAction" @click=${this.closeDialog}>
<ha-button
appearance="plain"
slot="primaryAction"
@click=${this.closeDialog}
>
${this.hass.localize("ui.common.cancel")}
</mwc-button>
</ha-button>
${this._isTargetAspectRatio
? html`<mwc-button slot="primaryAction" @click=${this._useOriginal}>
? html`<ha-button
appearance="plain"
slot="primaryAction"
@click=${this._useOriginal}
>
${this.hass.localize("ui.dialogs.image_cropper.use_original")}
</mwc-button>`
</ha-button>`
: nothing}
<mwc-button slot="primaryAction" @click=${this._cropImage}>
<ha-button slot="primaryAction" @click=${this._cropImage}>
${this.hass.localize("ui.dialogs.image_cropper.crop")}
</mwc-button>
</ha-button>
</ha-dialog>`;
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import { mdiEyedropper } from "@mdi/js";
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
@ -6,6 +5,7 @@ import "../../../components/ha-relative-time";
import { triggerAutomationActions } from "../../../data/automation";
import { isUnavailableState } from "../../../data/entity";
import type { HomeAssistant } from "../../../types";
import "../../../components/ha-button";
@customElement("more-info-automation")
class MoreInfoAutomation extends LitElement {
@ -30,12 +30,14 @@ class MoreInfoAutomation extends LitElement {
</div>
<div class="actions">
<mwc-button
<ha-button
appearance="plain"
size="small"
@click=${this._runActions}
.disabled=${isUnavailableState(this.stateObj!.state)}
>
${this.hass.localize("ui.card.automation.trigger")}
</mwc-button>
</ha-button>
</div>
`;
}

View File

@ -1,9 +1,8 @@
import "@material/mwc-button";
import type { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../components/ha-alert";
import "../../../components/ha-spinner";
import "../../../components/ha-button";
import "../../../components/ha-markdown";
import "../../../components/ha-textfield";
import type { HomeAssistant } from "../../../types";
@ -46,19 +45,13 @@ export class MoreInfoConfigurator extends LitElement {
)}
${this.stateObj.attributes.submit_caption
? html`<p class="submit">
<mwc-button
raised
<ha-button
.disabled=${this._isConfiguring}
@click=${this._submitClicked}
.loading=${this._isConfiguring}
>
${this._isConfiguring
? html`<ha-spinner
size="tiny"
aria-label="Configuring"
></ha-spinner>`
: ""}
${this.stateObj.attributes.submit_caption}
</mwc-button>
</ha-button>
</p>`
: ""}
</div>
@ -113,12 +106,6 @@ export class MoreInfoConfigurator extends LitElement {
text-align: center;
height: 41px;
}
ha-spinner {
--ha-spinner-indicator-color: var(--primary-text-color);
margin-right: auto;
margin-left: auto;
}
`;
}

View File

@ -1,9 +1,9 @@
import "@material/mwc-button";
import type { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { isUnavailableState } from "../../../data/entity";
import type { HomeAssistant } from "../../../types";
import "../../../components/ha-button";
@customElement("more-info-counter")
class MoreInfoCounter extends LitElement {
@ -20,29 +20,35 @@ class MoreInfoCounter extends LitElement {
return html`
<div class="actions">
<mwc-button
<ha-button
appearance="plain"
size="small"
.action=${"increment"}
@click=${this._handleActionClick}
.disabled=${disabled ||
Number(this.stateObj.state) === this.stateObj.attributes.maximum}
>
${this.hass!.localize("ui.card.counter.actions.increment")}
</mwc-button>
<mwc-button
</ha-button>
<ha-button
appearance="plain"
size="small"
.action=${"decrement"}
@click=${this._handleActionClick}
.disabled=${disabled ||
Number(this.stateObj.state) === this.stateObj.attributes.minimum}
>
${this.hass!.localize("ui.card.counter.actions.decrement")}
</mwc-button>
<mwc-button
</ha-button>
<ha-button
appearance="plain"
size="small"
.action=${"reset"}
@click=${this._handleActionClick}
.disabled=${disabled}
>
${this.hass!.localize("ui.card.counter.actions.reset")}
</mwc-button>
</ha-button>
</div>
`;
}

View File

@ -1,5 +1,3 @@
import "@material/mwc-button/mwc-button";
import {
mdiLoginVariant,
mdiMusicNote,
@ -19,6 +17,7 @@ import "../../../components/ha-icon-button";
import "../../../components/ha-list-item";
import "../../../components/ha-select";
import "../../../components/ha-slider";
import "../../../components/ha-button";
import "../../../components/ha-svg-icon";
import { showMediaBrowserDialog } from "../../../components/media-player/show-media-browser-dialog";
import { showJoinMediaPlayersDialog } from "../../../components/media-player/show-join-media-players-dialog";
@ -73,15 +72,15 @@ class MoreInfoMediaPlayer extends LitElement {
supportsFeature(stateObj, MediaPlayerEntityFeature.BROWSE_MEDIA)
? html`
<ha-button
.label=${this.hass.localize(
"ui.card.media_player.browse_media"
)}
@click=${this._showBrowseMedia}
appearance="plain"
size="small"
>
<ha-svg-icon
.path=${mdiPlayBoxMultiple}
slot="icon"
slot="start"
></ha-svg-icon>
${this.hass.localize("ui.card.media_player.browse_media")}
</ha-button>
`
: ""}
@ -89,18 +88,20 @@ class MoreInfoMediaPlayer extends LitElement {
supportsFeature(stateObj, MediaPlayerEntityFeature.GROUPING)
? html`
<ha-button
.label=${this.hass.localize("ui.card.media_player.join")}
@click=${this._showGroupMediaPlayers}
appearance="plain"
size="small"
>
<ha-svg-icon
.path=${mdiSpeakerMultiple}
slot="icon"
slot="start"
></ha-svg-icon>
${groupMembers && groupMembers > 1
? html`<span class="badge">
${stateObj.attributes.group_members?.length}
${stateObj.attributes.group_members?.length || 4}
</span>`
: nothing}
${this.hass.localize("ui.card.media_player.join")}
</ha-button>
`
: ""}
@ -284,14 +285,14 @@ class MoreInfoMediaPlayer extends LitElement {
font-style: italic;
}
mwc-button > ha-svg-icon {
ha-button > ha-svg-icon {
vertical-align: text-bottom;
}
.badge {
position: absolute;
top: 0;
left: 16px;
top: -6px;
left: 24px;
display: flex;
justify-content: center;
align-items: center;

View File

@ -1,10 +1,10 @@
import "@material/mwc-button";
import type { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-attributes";
import "../../../components/ha-button";
import "../../../components/map/ha-map";
import { showZoneEditor } from "../../../data/zone";
import type { HomeAssistant } from "../../../types";
@ -38,11 +38,15 @@ class MoreInfoPerson extends LitElement {
this.stateObj.attributes.longitude
? html`
<div class="actions">
<mwc-button @click=${this._handleAction}>
<ha-button
appearance="plain"
size="small"
@click=${this._handleAction}
>
${this.hass.localize(
"ui.dialogs.more_info_control.person.create_zone"
)}
</mwc-button>
</ha-button>
</div>
`
: ""}

View File

@ -1,5 +1,4 @@
import { mdiPlay, mdiStop } from "@mdi/js";
import "@material/mwc-button";
import type { HassEntity } from "home-assistant-js-websocket";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";

View File

@ -1,7 +1,7 @@
import "@material/mwc-button";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../components/ha-attributes";
import "../../../components/ha-button";
import type { TimerEntity } from "../../../data/timer";
import type { HomeAssistant } from "../../../types";
@ -20,26 +20,46 @@ class MoreInfoTimer extends LitElement {
<div class="actions">
${this.stateObj.state === "idle" || this.stateObj.state === "paused"
? html`
<mwc-button .action=${"start"} @click=${this._handleActionClick}>
<ha-button
appearance="plain"
size="small"
.action=${"start"}
@click=${this._handleActionClick}
>
${this.hass!.localize("ui.card.timer.actions.start")}
</mwc-button>
</ha-button>
`
: ""}
${this.stateObj.state === "active"
? html`
<mwc-button .action=${"pause"} @click=${this._handleActionClick}>
<ha-button
appearance="plain"
size="small"
.action=${"pause"}
@click=${this._handleActionClick}
>
${this.hass!.localize("ui.card.timer.actions.pause")}
</mwc-button>
</ha-button>
`
: ""}
${this.stateObj.state === "active" || this.stateObj.state === "paused"
? html`
<mwc-button .action=${"cancel"} @click=${this._handleActionClick}>
<ha-button
appearance="plain"
size="small"
.action=${"cancel"}
@click=${this._handleActionClick}
>
${this.hass!.localize("ui.card.timer.actions.cancel")}
</mwc-button>
<mwc-button .action=${"finish"} @click=${this._handleActionClick}>
</ha-button>
<ha-button
appearance="plain"
size="small"
.action=${"finish"}
@click=${this._handleActionClick}
>
${this.hass!.localize("ui.card.timer.actions.finish")}
</mwc-button>
</ha-button>
`
: ""}
</div>

View File

@ -299,7 +299,10 @@ class MoreInfoUpdate extends LitElement {
${this.stateObj.state === BINARY_STATE_OFF &&
this.stateObj.attributes.skipped_version
? html`
<ha-button @click=${this._handleClearSkipped}>
<ha-button
appearance="plain"
@click=${this._handleClearSkipped}
>
${this.hass.localize(
"ui.dialogs.more_info_control.update.clear_skipped"
)}
@ -307,6 +310,7 @@ class MoreInfoUpdate extends LitElement {
`
: html`
<ha-button
appearance="plain"
@click=${this._handleSkip}
.disabled=${skippedVersion ||
this.stateObj.state === BINARY_STATE_OFF ||

View File

@ -1,10 +1,10 @@
import "@material/mwc-button";
import { html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import { domainToName } from "../../data/integration";
import type { PersitentNotificationEntity } from "../../data/persistent_notification";
import type { HomeAssistant } from "../../types";
import "../../components/ha-button";
import "./notification-item-template";
@customElement("configurator-notification-item")
@ -31,9 +31,13 @@ export class HuiConfiguratorNotificationItem extends LitElement {
})}
</div>
<mwc-button slot="actions" @click=${this._handleClick}>
<ha-button
appearance="plain"
slot="actions"
@click=${this._handleClick}
>
${this.hass.formatEntityState(this.notification)}
</mwc-button>
</ha-button>
</notification-item-template>
`;
}

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import { LitElement, html, css, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
@ -10,6 +9,7 @@ import { subscribeNotifications } from "../../data/persistent_notification";
import type { HomeAssistant } from "../../types";
import "./notification-item";
import "../../components/ha-header-bar";
import "../../components/ha-button";
import "../../components/ha-drawer";
import type { HaDrawer } from "../../components/ha-drawer";
import { computeRTLDirection } from "../../common/util/compute_rtl";
@ -122,11 +122,11 @@ export class HuiNotificationDrawer extends LitElement {
)}
${this._notifications.length > 1
? html`<div class="notification-actions">
<mwc-button raised @click=${this._dismissAll}>
<ha-button appearance="filled" @click=${this._dismissAll}>
${this.hass.localize(
"ui.notification_drawer.dismiss_all"
)}
</mwc-button>
</ha-button>
</div>`
: ""}`
: html` <div class="empty">

View File

@ -39,6 +39,8 @@ export class HuiNotificationItemTemplate extends LitElement {
.actions {
border-top: 1px solid var(--divider-color, #e8e8e8);
padding: 5px 16px;
display: flex;
justify-content: flex-end;
}
::slotted(.primary) {

View File

@ -41,7 +41,10 @@ export class HuiPersistentNotificationItem extends LitElement {
</span>
</div>
<ha-button slot="actions" @click=${this._handleDismiss}
<ha-button
appearance="plain"
slot="actions"
@click=${this._handleDismiss}
>${this.hass.localize(
"ui.card.persistent_notification.dismiss"
)}</ha-button

View File

@ -37,6 +37,7 @@ import { computeRTL } from "../../common/util/compute_rtl";
import { debounce } from "../../common/util/debounce";
import "../../components/ha-icon-button";
import "../../components/ha-label";
import "../../components/ha-button";
import "../../components/ha-list";
import "../../components/ha-md-list-item";
import "../../components/ha-spinner";
@ -246,10 +247,13 @@ export class QuickBar extends LitElement {
></ha-icon-button>`}
${this._narrow
? html`
<mwc-button
.label=${this.hass!.localize("ui.common.close")}
<ha-button
appearance="plain"
size="small"
@click=${this.closeDialog}
></mwc-button>
>
${this.hass!.localize("ui.common.close")}
</ha-button>
`
: ""}
</div>

View File

@ -160,7 +160,7 @@ class DialogEditSidebar extends LitElement {
</ha-dialog-header>
<div slot="content" class="content">${this._renderContent()}</div>
<div slot="actions">
<ha-button @click=${this.closeDialog}>
<ha-button appearance="plain" @click=${this.closeDialog}>
${this.hass.localize("ui.common.cancel")}
</ha-button>
<ha-button

View File

@ -3,6 +3,7 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { storage } from "../../common/decorators/storage";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/buttons/ha-progress-button";
import { createCloseHeading } from "../../components/ha-dialog";
import "../../components/ha-textarea";
import type { HaTextArea } from "../../components/ha-textarea";
@ -10,7 +11,6 @@ import { convertTextToSpeech } from "../../data/tts";
import type { HomeAssistant } from "../../types";
import { showAlertDialog } from "../generic/show-dialog-box";
import type { TTSTryDialogParams } from "./show-dialog-tts-try";
import "../../components/buttons/ha-progress-button";
@customElement("dialog-tts-try")
export class TTSTryDialog extends LitElement {
@ -85,11 +85,11 @@ export class TTSTryDialog extends LitElement {
.progress=${this._loadingExample}
?dialogInitialFocus=${Boolean(this._defaultMessage)}
slot="primaryAction"
.label=${this.hass.localize("ui.dialogs.tts-try.play")}
@click=${this._playExample}
.disabled=${!this._valid}
.iconPath=${mdiPlayCircleOutline}
>
<ha-svg-icon slot="icon" .path=${mdiPlayCircleOutline}></ha-svg-icon>
${this.hass.localize("ui.dialogs.tts-try.play")}
</ha-progress-button>
</ha-dialog>
`;

View File

@ -97,17 +97,16 @@ export class CloudStepIntro extends LitElement {
</div>
</div>
<div class="footer side-by-side">
<a
<ha-button
href="https://www.nabucasa.com"
target="_blank"
rel="noreferrer noopener"
appearance="plain"
>
<ha-button>
<ha-svg-icon .path=${mdiOpenInNew} slot="icon"></ha-svg-icon>
nabucasa.com
</ha-button>
</a>
<ha-button unelevated @click=${this._signUp}
<ha-svg-icon .path=${mdiOpenInNew} slot="start"></ha-svg-icon>
nabucasa.com
</ha-button>
<ha-button @click=${this._signUp}
>${this.hass.localize(
"ui.panel.config.cloud.register.headline"
)}</ha-button

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import { mdiChevronLeft, mdiClose, mdiMenuDown } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";

View File

@ -1,11 +1,11 @@
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-area-picker";
import { updateDeviceRegistryEntry } from "../../data/device_registry";
import type { HomeAssistant } from "../../types";
import { showAlertDialog } from "../generic/show-dialog-box";
import { AssistantSetupStyles } from "./styles";
import "../../components/ha-area-picker";
@customElement("ha-voice-assistant-setup-step-area")
export class HaVoiceAssistantSetupStepArea extends LitElement {
@ -37,7 +37,7 @@ export class HaVoiceAssistantSetupStepArea extends LitElement {
></ha-area-picker>
</div>
<div class="footer">
<ha-button @click=${this._setArea} unelevated
<ha-button @click=${this._setArea}
>${this.hass.localize("ui.common.next")}</ha-button
>
</div>`;

View File

@ -180,7 +180,7 @@ export class HaVoiceAssistantSetupStepSuccess extends LitElement {
</div>
</div>
<div class="footer">
<ha-button @click=${this._done} unelevated
<ha-button @click=${this._done}
>${this.hass.localize(
"ui.panel.config.voice_assistants.satellite_wizard.success.done"
)}</ha-button

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import {
mdiChevronDown,
mdiClose,
@ -11,14 +10,14 @@ import { customElement, property, state } from "lit/decorators";
import { storage } from "../../common/decorators/storage";
import { fireEvent } from "../../common/dom/fire_event";
import { stopPropagation } from "../../common/dom/stop_propagation";
import "../../components/ha-alert";
import "../../components/ha-assist-chat";
import "../../components/ha-button";
import "../../components/ha-button-menu";
import "../../components/ha-dialog";
import "../../components/ha-dialog-header";
import "../../components/ha-icon-button";
import "../../components/ha-list-item";
import "../../components/ha-alert";
import "../../components/ha-assist-chat";
import "../../components/ha-spinner";
import type { AssistPipeline } from "../../data/assist_pipeline";
import {
@ -111,12 +110,14 @@ export class HaVoiceCommandDialog extends LitElement {
activatable
fixed
>
<ha-button slot="trigger">
<ha-button
slot="trigger"
appearance="plain"
variant="neutral"
size="small"
>
${this._pipeline?.name}
<ha-svg-icon
slot="trailingIcon"
.path=${mdiChevronDown}
></ha-svg-icon>
<ha-svg-icon slot="end" .path=${mdiChevronDown}></ha-svg-icon>
</ha-button>
${!this._pipelines
? html`<div class="pipelines-loading">
@ -270,19 +271,17 @@ export class HaVoiceCommandDialog extends LitElement {
margin-inline-start: -8px;
}
ha-button-menu ha-button {
--mdc-theme-primary: var(--secondary-text-color);
--mdc-typography-button-text-transform: none;
--mdc-typography-button-font-size: unset;
--mdc-typography-button-font-weight: var(--ha-font-weight-normal);
--mdc-typography-button-letter-spacing: var(
--mdc-typography-headline6-letter-spacing,
0.0125em
);
--mdc-typography-button-line-height: var(
--mdc-typography-headline6-line-height,
var(--ha-line-height-expanded)
);
--button-height: auto;
--ha-font-size-l: var(--ha-font-size-m);
--ha-button-height: 20px;
}
ha-button-menu ha-button::part(base) {
margin-left: 5px;
padding: 0;
}
@media (prefers-color-scheme: dark) {
ha-button-menu ha-button {
--ha-button-theme-lighter-color: rgba(255, 255, 255, 0.1);
}
}
ha-button-menu ha-button ha-svg-icon {
height: 28px;

View File

@ -1,8 +1,8 @@
import type { PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { property, state } from "lit/decorators";
import "@material/mwc-button";
import "../components/ha-spinner";
import "../components/ha-button";
class HaInitPage extends LitElement {
@property({ type: Boolean }) public error = false;
@ -22,7 +22,7 @@ class HaInitPage extends LitElement {
<p class="retry-text">
Retrying in ${this._retryInSeconds} seconds...
</p>
<mwc-button @click=${this._retry}>Retry now</mwc-button>
<ha-button @click=${this._retry}>Retry now</ha-button>
${location.host.includes("ui.nabu.casa")
? html`
<p>
@ -66,7 +66,7 @@ class HaInitPage extends LitElement {
protected willUpdate(changedProperties: PropertyValues<this>) {
if (changedProperties.has("error") && this.error) {
import("@material/mwc-button");
import("../components/ha-button");
}
}

View File

@ -1,8 +1,8 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import "../components/ha-icon-button-arrow-prev";
import "../components/ha-button";
import "../components/ha-menu-button";
import type { HomeAssistant } from "../types";
import "../components/ha-alert";
@ -41,9 +41,9 @@ class HassErrorScreen extends LitElement {
<div class="content">
<ha-alert alert-type="error">${this.error}</ha-alert>
<slot>
<mwc-button @click=${this._handleBack}>
<ha-button appearance="plain" size="small" @click=${this._handleBack}>
${this.hass?.localize("ui.common.back")}
</mwc-button>
</ha-button>
</slot>
</div>
`;

View File

@ -1,5 +1,4 @@
import { ResizeController } from "@lit-labs/observers/resize-controller";
import "@material/mwc-button/mwc-button";
import {
mdiArrowDown,
mdiArrowUp,
@ -768,12 +767,6 @@ export class HaTabsSubpageDataTable extends KeyboardShortcutMixin(LitElement) {
.active-filters ha-svg-icon {
color: var(--primary-color);
}
.active-filters mwc-button {
margin-left: 8px;
margin-inline-start: 8px;
margin-inline-end: initial;
direction: var(--direction);
}
.active-filters::before {
background-color: var(--primary-color);
opacity: 0.12;

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";

View File

@ -1,4 +1,3 @@
import "@material/mwc-button/mwc-button";
import { mdiOpenInNew } from "@mdi/js";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
@ -6,6 +5,7 @@ import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import type { LocalizeFunc } from "../common/translations/localize";
import "../components/ha-analytics";
import "../components/ha-button";
import "../components/ha-svg-icon";
import type { Analytics } from "../data/analytics";
import { setAnalyticsPreferences } from "../data/analytics";
@ -49,13 +49,9 @@ class OnboardingAnalytics extends LitElement {
</ha-analytics>
${this._error ? html`<div class="error">${this._error}</div>` : ""}
<div class="footer">
<mwc-button
unelevated
@click=${this._save}
.disabled=${!this._analyticsDetails}
>
<ha-button @click=${this._save} .disabled=${!this._analyticsDetails}>
${this.localize("ui.panel.page-onboarding.analytics.finish")}
</mwc-button>
</ha-button>
</div>
`;
}

Some files were not shown because too many files have changed in this diff Show More