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

View File

@ -1,4 +1,3 @@
import "@material/mwc-button";
import { mdiCastConnected, mdiCast } from "@mdi/js"; import { mdiCastConnected, mdiCast } from "@mdi/js";
import type { import type {
Auth, Auth,
@ -28,6 +27,7 @@ import "../../../../src/layouts/hass-loading-screen";
import { registerServiceWorker } from "../../../../src/util/register-service-worker"; import { registerServiceWorker } from "../../../../src/util/register-service-worker";
import "./hc-layout"; import "./hc-layout";
import "../../../../src/components/ha-textfield"; import "../../../../src/components/ha-textfield";
import "../../../../src/components/ha-button";
const seeFAQ = (qid) => html` const seeFAQ = (qid) => html`
See <a href="./faq.html${qid ? `#${qid}` : ""}">the FAQ</a> for more 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}. Unable to connect to ${tokens!.hassUrl}.
</div> </div>
<div class="card-actions"> <div class="card-actions">
<a href="/"> <ha-button appearance="plain" href="/">Retry</ha-button>
<mwc-button> Retry </mwc-button>
</a>
<div class="spacer"></div> <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> </div>
</hc-layout> </hc-layout>
`; `;
@ -128,16 +131,19 @@ export class HcConnect extends LitElement {
${this.error ? html` <p class="error">${this.error}</p> ` : ""} ${this.error ? html` <p class="error">${this.error}</p> ` : ""}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button @click=${this._handleDemo}> <ha-button appearance="plain" @click=${this._handleDemo}>
Show Demo Show Demo
<ha-svg-icon <ha-svg-icon
slot="end"
.path=${this.castManager.castState === "CONNECTED" .path=${this.castManager.castState === "CONNECTED"
? mdiCastConnected ? mdiCastConnected
: mdiCast} : mdiCast}
></ha-svg-icon> ></ha-svg-icon>
</mwc-button> </ha-button>
<div class="spacer"></div> <div class="spacer"></div>
<mwc-button @click=${this._handleConnect}>Authorize</mwc-button> <ha-button appearance="plain" @click=${this._handleConnect}
>Authorize</ha-button
>
</div> </div>
</hc-layout> </hc-layout>
`; `;
@ -309,10 +315,6 @@ export class HcConnect extends LitElement {
color: darkred; color: darkred;
} }
mwc-button ha-svg-icon {
margin-left: 8px;
}
.spacer { .spacer {
flex: 1; 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 type { TemplateResult } from "lit";
import { html, LitElement, css, nothing } from "lit"; import { html, LitElement, css, nothing } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../../src/common/dom/fire_event"; import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/ha-card"; import "../../../src/components/ha-card";
import "../../../src/components/ha-button";
import type { HaButton } from "../../../src/components/ha-button";
@customElement("demo-black-white-row") @customElement("demo-black-white-row")
class DemoBlackWhiteRow extends LitElement { class DemoBlackWhiteRow extends LitElement {
@ -25,12 +25,9 @@ class DemoBlackWhiteRow extends LitElement {
<slot name="light"></slot> <slot name="light"></slot>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button <ha-button .disabled=${this.disabled} @click=${this.handleSubmit}>
.disabled=${this.disabled}
@click=${this.handleSubmit}
>
Submit Submit
</mwc-button> </ha-button>
</div> </div>
</ha-card> </ha-card>
</div> </div>
@ -40,12 +37,9 @@ class DemoBlackWhiteRow extends LitElement {
<slot name="dark"></slot> <slot name="dark"></slot>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button <ha-button .disabled=${this.disabled} @click=${this.handleSubmit}>
.disabled=${this.disabled}
@click=${this.handleSubmit}
>
Submit Submit
</mwc-button> </ha-button>
</div> </div>
</ha-card> </ha-card>
${this.value ${this.value
@ -74,7 +68,7 @@ class DemoBlackWhiteRow extends LitElement {
} }
handleSubmit(ev) { handleSubmit(ev) {
const content = (ev.target as Button).closest(".content")!; const content = (ev.target as HaButton).closest(".content")!;
fireEvent(this, "submitted" as any, { fireEvent(this, "submitted" as any, {
slot: content.classList.contains("light") ? "light" : "dark", 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"> <ha-alert alert-type="success">
This is a success alert — check it out! 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> </ha-alert>
```html ```html
<ha-alert alert-type="success"> <ha-alert alert-type="success">
This is a success alert — check it out! 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> </ha-alert>
``` ```

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,9 @@ import { mdiAlertOctagram, mdiCheckBold } from "@mdi/js";
import type { TemplateResult } from "lit"; import type { TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import "../ha-button"; import "../ha-button";
import type { Appearance } from "../ha-button";
import "../ha-spinner"; import "../ha-spinner";
import "../ha-svg-icon"; import "../ha-svg-icon";
@ -12,28 +14,47 @@ export class HaProgressButton extends LitElement {
@property({ type: Boolean }) public disabled = false; @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"; @state() private _result?: "success" | "error";
public render(): TemplateResult { public render(): TemplateResult {
const overlay = this._result || this.progress; const appearance =
this.progress || this._result ? "accent" : this.appearance;
return html` return html`
<ha-button <ha-button
.raised=${this.raised} .appearance=${appearance}
.label=${this.label} .disabled=${this.disabled}
.unelevated=${this.unelevated} .loading=${this.progress}
.disabled=${this.disabled || this.progress} .variant=${this._result === "success"
class=${this._result || ""} ? "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> ${this.iconPath
<slot></slot> ? html`<ha-svg-icon
.path=${this.iconPath}
slot="start"
></ha-svg-icon>`
: nothing}
<slot>${this.label}</slot>
</ha-button> </ha-button>
${!overlay ${!this._result
? nothing ? nothing
: html` : html`
<div class="progress"> <div class="progress">
@ -41,9 +62,7 @@ export class HaProgressButton extends LitElement {
? html`<ha-svg-icon .path=${mdiCheckBold}></ha-svg-icon>` ? html`<ha-svg-icon .path=${mdiCheckBold}></ha-svg-icon>`
: this._result === "error" : this._result === "error"
? html`<ha-svg-icon .path=${mdiAlertOctagram}></ha-svg-icon>` ? html`<ha-svg-icon .path=${mdiAlertOctagram}></ha-svg-icon>`
: this.progress : nothing}
? html`<ha-spinner size="small"></ha-spinner>`
: nothing}
</div> </div>
`} `}
`; `;
@ -69,60 +88,36 @@ export class HaProgressButton extends LitElement {
outline: none; outline: none;
display: inline-block; display: inline-block;
position: relative; position: relative;
}
:host([progress]) {
pointer-events: none; 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 { .progress {
bottom: 4px; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
position: absolute; position: absolute;
text-align: center; top: 0;
top: 4px;
width: 100%; width: 100%;
} }
ha-svg-icon { ha-button {
color: white; width: 100%;
} }
ha-button.success slot, ha-button.result::part(start),
ha-button.error slot { ha-button.result::part(end),
ha-button.result::part(label),
ha-button.result::part(caret),
ha-button.result::part(spinner) {
visibility: hidden; 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-list>
</ha-sortable> </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 >${localize("ui.components.data-table.settings.restore")}</ha-button
> >
<ha-button slot="primaryAction" @click=${this.closeDialog}> <ha-button slot="primaryAction" @click=${this.closeDialog}>

View File

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

View File

@ -131,7 +131,6 @@ class HaAlert extends LitElement {
margin-top: 2px; margin-top: 2px;
font-weight: var(--ha-font-weight-bold); font-weight: var(--ha-font-weight-bold);
} }
.action mwc-button,
.action ha-icon-button { .action ha-icon-button {
--mdc-theme-primary: var(--primary-text-color); --mdc-theme-primary: var(--primary-text-color);
--mdc-icon-button-size: 36px; --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 { Corner, Menu, MenuCorner } from "@material/mwc-menu";
import type { TemplateResult } from "lit"; import type { TemplateResult } from "lit";
import { css, html, LitElement } 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 { mainWindow } from "../common/dom/get_main_window";
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager"; import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
import type { HaIconButton } from "./ha-icon-button"; import type { HaIconButton } from "./ha-icon-button";
import type { HaButton } from "./ha-button";
import "./ha-menu"; import "./ha-menu";
@customElement("ha-button-menu") @customElement("ha-button-menu")
@ -93,8 +93,8 @@ export class HaButtonMenu extends LitElement {
private get _triggerButton() { private get _triggerButton() {
return this.querySelector( return this.querySelector(
'ha-icon-button[slot="trigger"], ha-button[slot="trigger"], mwc-button[slot="trigger"]' 'ha-icon-button[slot="trigger"], ha-button[slot="trigger"]'
) as HaIconButton | Button | null; ) as HaIconButton | HaButton | null;
} }
private _setTriggerAria() { private _setTriggerAria() {

View File

@ -1,33 +1,177 @@
import { Button } from "@material/mwc-button"; import Button from "@awesome.me/webawesome/dist/components/button/button";
import { css } from "lit"; import { css, type CSSResultGroup } from "lit";
import { customElement } from "lit/decorators"; 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") @customElement("ha-button")
export class HaButton extends Button { export class HaButton extends Button {
static override styles = [ variant: "brand" | "neutral" | "success" | "warning" | "danger" = "brand";
styles,
css` attachInternals() {
::slotted([slot="icon"]) { const internals = super.attachInternals();
margin-inline-start: 0px; Object.defineProperty(internals, "states", {
margin-inline-end: 8px; value: new StateSet(this, internals.states),
direction: var(--direction); });
display: block; return internals;
} }
.mdc-button {
height: var(--button-height, 36px); static get styles(): CSSResultGroup {
} return [
.trailing-icon { Button.styles,
display: flex; css`
} .button {
.slot-container { /* set theme vars */
overflow: var(--button-slot-container-overflow, visible); --wa-form-control-padding-inline: 16px;
} --wa-font-weight-action: var(--ha-font-weight-medium);
:host([destructive]) { --wa-border-radius-pill: 9999px;
--mdc-theme-primary: var(--error-color); --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 { declare global {

View File

@ -63,7 +63,7 @@ export class HaCard extends LitElement {
:host ::slotted(.card-actions) { :host ::slotted(.card-actions) {
border-top: 1px solid var(--divider-color, #e8e8e8); 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 { 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-button";
import "./ha-icon-button"; import "./ha-icon-button";
import "./ha-svg-icon"; import "./ha-svg-icon";
import "./ha-textfield"; 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"; import type { HaTextField } from "./ha-textfield";
@customElement("ha-copy-textfield") @customElement("ha-copy-textfield")
@ -48,8 +48,8 @@ export class HaCopyTextfield extends LitElement {
></ha-icon-button>` ></ha-icon-button>`
: nothing} : nothing}
</div> </div>
<ha-button @click=${this._copy} unelevated> <ha-button @click=${this._copy} appearance="plain" size="small">
<ha-svg-icon slot="icon" .path=${mdiContentCopy}></ha-svg-icon> <ha-svg-icon slot="start" .path=${mdiContentCopy}></ha-svg-icon>
${this.label || this.hass.localize("ui.common.copy")} ${this.label || this.hass.localize("ui.common.copy")}
</ha-button> </ha-button>
</div> </div>

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,12 @@ export class HaFab extends FabBase {
static override styles = [ static override styles = [
styles, styles,
css` 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 { :host .mdc-fab--extended .mdc-fab__icon {
margin-inline-start: -8px; margin-inline-start: -8px;
margin-inline-end: 12px; margin-inline-end: 12px;

View File

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

View File

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

View File

@ -1,7 +1,7 @@
import "@material/mwc-button";
import { LitElement, css, html } from "lit"; import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { supportsFeature } from "../common/entity/supports-feature"; import { supportsFeature } from "../common/entity/supports-feature";
import "./ha-button";
import type { LawnMowerEntity, LawnMowerEntityState } from "../data/lawn_mower"; import type { LawnMowerEntity, LawnMowerEntityState } from "../data/lawn_mower";
import { LawnMowerEntityFeature } from "../data/lawn_mower"; import { LawnMowerEntityFeature } from "../data/lawn_mower";
import type { HomeAssistant } from "../types"; import type { HomeAssistant } from "../types";
@ -49,16 +49,21 @@ class HaLawnMowerActionButton extends LitElement {
if (action && supportsFeature(this.stateObj, action.feature)) { if (action && supportsFeature(this.stateObj, action.feature)) {
return html` 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}`)} ${this.hass.localize(`ui.card.lawn_mower.actions.${action.action}`)}
</mwc-button> </ha-button>
`; `;
} }
return html` return html`
<mwc-button disabled> <ha-button appearance="plain" disabled>
${this.hass.formatEntityState(this.stateObj)} ${this.hass.formatEntityState(this.stateObj)}
</mwc-button> </ha-button>
`; `;
} }
@ -72,17 +77,13 @@ class HaLawnMowerActionButton extends LitElement {
} }
static styles = css` static styles = css`
mwc-button { ha-button {
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;
margin-inline-end: -0.57em; margin-inline-end: -0.57em;
margin-inline-start: initial; 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 type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit"; import { css, html, LitElement } from "lit";
import { customElement, property, query } from "lit/decorators"; import { customElement, property, query } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { FOCUS_TARGET } from "../dialogs/make-dialog-manager"; import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
import type { HaButton } from "./ha-button";
import type { HaIconButton } from "./ha-icon-button"; import type { HaIconButton } from "./ha-icon-button";
import "./ha-md-menu"; import "./ha-md-menu";
import type { HaMdMenu } from "./ha-md-menu"; import type { HaMdMenu } from "./ha-md-menu";
@ -71,8 +71,8 @@ export class HaMdButtonMenu extends LitElement {
private get _triggerButton() { private get _triggerButton() {
return this.querySelector( return this.querySelector(
'ha-icon-button[slot="trigger"], mwc-button[slot="trigger"], ha-assist-chip[slot="trigger"]' 'ha-icon-button[slot="trigger"], ha-button[slot="trigger"], ha-assist-chip[slot="trigger"]'
) as HaIconButton | Button | null; ) as HaIconButton | HaButton | null;
} }
private _setTriggerAria() { private _setTriggerAria() {

View File

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

View File

@ -73,7 +73,12 @@ class HaMultiTextField extends LitElement {
`; `;
})} })}
<div class="layout horizontal"> <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.addLabel ??
(this.label (this.label
? this.hass?.localize("ui.components.multi-textfield.add_item", { ? this.hass?.localize("ui.components.multi-textfield.add_item", {
@ -81,7 +86,7 @@ class HaMultiTextField extends LitElement {
}) })
: this.hass?.localize("ui.common.add")) ?? : this.hass?.localize("ui.common.add")) ??
"Add"} "Add"}
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon> <ha-svg-icon slot="end" .path=${mdiPlus}></ha-svg-icon>
</ha-button> </ha-button>
</div> </div>
${this.helper ${this.helper
@ -145,11 +150,6 @@ class HaMultiTextField extends LitElement {
ha-icon-button { ha-icon-button {
display: block; 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; display: block;
margin-bottom: 16px; margin-bottom: 16px;
} }
mwc-button {
margin-top: 8px;
}
ha-alert { ha-alert {
display: block; display: block;
margin-bottom: 16px; margin-bottom: 16px;

View File

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

View File

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

View File

@ -1,10 +1,10 @@
import "@material/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit"; import type { CSSResultGroup, TemplateResult } from "lit";
import { LitElement, css, html } from "lit"; import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import { haStyle } from "../resources/styles"; import { haStyle } from "../resources/styles";
import type { HomeAssistant } from "../types"; import type { HomeAssistant } from "../types";
import "./ha-button";
const STATES_INTERCEPTABLE: Record< const STATES_INTERCEPTABLE: Record<
string, string,
@ -56,9 +56,14 @@ export class HaVacuumState extends LitElement {
this.stateObj.attributes.supported_features this.stateObj.attributes.supported_features
); );
return html` 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)} ${this._computeLabel(this.stateObj.state, interceptable)}
</mwc-button> </ha-button>
`; `;
} }
@ -92,17 +97,13 @@ export class HaVacuumState extends LitElement {
return [ return [
haStyle, haStyle,
css` css`
mwc-button { ha-button {
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;
margin-inline-end: -0.57em; margin-inline-end: -0.57em;
margin-inline-start: initial; 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 { 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 { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import type { HassEntity } from "home-assistant-js-websocket";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { haStyleDialog } from "../../resources/styles"; import { computeDomain } from "../../common/entity/compute_domain";
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 { computeStateName } from "../../common/entity/compute_state_name"; import { computeStateName } from "../../common/entity/compute_state_name";
import { supportsFeature } from "../../common/entity/supports-feature"; import { supportsFeature } from "../../common/entity/supports-feature";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import { extractApiErrorMessage } from "../../data/hassio/common";
import { import {
type MediaPlayerEntity, type MediaPlayerEntity,
MediaPlayerEntityFeature, MediaPlayerEntityFeature,
mediaPlayerJoin, mediaPlayerJoin,
mediaPlayerUnjoin, mediaPlayerUnjoin,
} from "../../data/media-player"; } from "../../data/media-player";
import { extractApiErrorMessage } from "../../data/hassio/common"; import { haStyleDialog } from "../../resources/styles";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry"; import type { HomeAssistant } from "../../types";
import { computeDomain } from "../../common/entity/compute_domain"; 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") @customElement("dialog-join-media-players")
class DialogJoinMediaPlayers extends LitElement { class DialogJoinMediaPlayers extends LitElement {
@ -90,7 +90,11 @@ class DialogJoinMediaPlayers extends LitElement {
<span slot="title" <span slot="title"
>${this.hass.localize("ui.card.media_player.media_players")}</span >${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")} ${this.hass.localize("ui.card.media_player.select_all")}
</ha-button> </ha-button>
</ha-dialog-header> </ha-dialog-header>
@ -114,11 +118,15 @@ class DialogJoinMediaPlayers extends LitElement {
></ha-media-player-toggle>` ></ha-media-player-toggle>`
)} )}
</div> </div>
<ha-button slot="secondaryAction" @click=${this.closeDialog}> <ha-button
appearance="plain"
slot="secondaryAction"
@click=${this.closeDialog}
>
${this.hass.localize("ui.common.cancel")} ${this.hass.localize("ui.common.cancel")}
</ha-button> </ha-button>
<ha-button <ha-button
.disabled=${this._submitting} .disabled=${!!this._submitting}
slot="primaryAction" slot="primaryAction"
@click=${this._submit} @click=${this._submit}
> >

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
import "@material/mwc-button";
import { mdiUpload } from "@mdi/js"; 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 { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import type { MediaPlayerItem } from "../../data/media-player"; import type { MediaPlayerItem } from "../../data/media-player";
@ -10,7 +9,7 @@ import {
} from "../../data/media_source"; } from "../../data/media_source";
import { showAlertDialog } from "../../dialogs/generic/show-dialog-box"; import { showAlertDialog } from "../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import "../ha-spinner"; import "../ha-button";
import "../ha-svg-icon"; import "../ha-svg-icon";
declare global { declare global {
@ -36,8 +35,13 @@ class MediaUploadButton extends LitElement {
return nothing; return nothing;
} }
return html` return html`
<mwc-button <ha-button
.label=${this._uploading > 0 .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( ? this.hass.localize(
"ui.components.media-browser.file_management.uploading", "ui.components.media-browser.file_management.uploading",
{ {
@ -47,19 +51,7 @@ class MediaUploadButton extends LitElement {
: this.hass.localize( : this.hass.localize(
"ui.components.media-browser.file_management.add_media" "ui.components.media-browser.file_management.add_media"
)} )}
.disabled=${this._uploading > 0} </ha-button>
@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>
`; `;
} }
@ -107,24 +99,6 @@ class MediaUploadButton extends LitElement {
document.body.append(input); document.body.append(input);
input.click(); 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 { declare global {

View File

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

View File

@ -7,6 +7,7 @@ import { ifDefined } from "lit/directives/if-defined";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/entity/ha-entity-toggle"; import "../../../components/entity/ha-entity-toggle";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "../../../components/ha-button";
import "../../../components/ha-climate-state"; import "../../../components/ha-climate-state";
import "../../../components/ha-cover-controls"; import "../../../components/ha-cover-controls";
import "../../../components/ha-cover-tilt-controls"; import "../../../components/ha-cover-tilt-controls";
@ -91,7 +92,7 @@ class EntityPreviewRow extends LitElement {
justify-content: flex-end; justify-content: flex-end;
width: 100%; width: 100%;
} }
mwc-button { ha-button {
margin-right: -0.57em; margin-right: -0.57em;
margin-inline-end: -0.57em; margin-inline-end: -0.57em;
margin-inline-start: initial; margin-inline-start: initial;
@ -107,9 +108,13 @@ class EntityPreviewRow extends LitElement {
if (domain === "button") { if (domain === "button") {
return html` 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")} ${this.hass.localize("ui.card.button.press")}
</mwc-button> </ha-button>
`; `;
} }
@ -232,14 +237,16 @@ class EntityPreviewRow extends LitElement {
if (domain === "lock") { if (domain === "lock") {
return html` return html`
<mwc-button <ha-button
.disabled=${isUnavailableState(stateObj.state)} .disabled=${isUnavailableState(stateObj.state)}
class="text-content" class="text-content"
appearance="plain"
size="small"
> >
${stateObj.state === "locked" ${stateObj.state === "locked"
? this.hass!.localize("ui.card.lock.unlock") ? this.hass!.localize("ui.card.lock.unlock")
: this.hass!.localize("ui.card.lock.lock")} : 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 type { CSSResultGroup, PropertyValues } from "lit";
import { html, LitElement, nothing } from "lit"; import { html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
@ -9,6 +8,7 @@ import type { HomeAssistant } from "../../types";
import { showConfigFlowDialog } from "./show-dialog-config-flow"; import { showConfigFlowDialog } from "./show-dialog-config-flow";
import type { DataEntryFlowDialogParams } from "./show-dialog-data-entry-flow"; import type { DataEntryFlowDialogParams } from "./show-dialog-data-entry-flow";
import { configFlowContentStyles } from "./styles"; import { configFlowContentStyles } from "./styles";
import "../../components/ha-button";
@customElement("step-flow-abort") @customElement("step-flow-abort")
class StepFlowAbort extends LitElement { class StepFlowAbort extends LitElement {
@ -38,10 +38,10 @@ class StepFlowAbort extends LitElement {
${this.params.flowConfig.renderAbortDescription(this.hass, this.step)} ${this.params.flowConfig.renderAbortDescription(this.hass, this.step)}
</div> </div>
<div class="buttons"> <div class="buttons">
<mwc-button @click=${this._flowDone} <ha-button appearance="plain" @click=${this._flowDone}
>${this.hass.localize( >${this.hass.localize(
"ui.panel.config.integrations.config_flow.close" "ui.panel.config.integrations.config_flow.close"
)}</mwc-button )}</ha-button
> >
</div> </div>
`; `;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,8 @@
import "@material/mwc-button";
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-spinner"; import "../../../components/ha-button";
import "../../../components/ha-markdown"; import "../../../components/ha-markdown";
import "../../../components/ha-textfield"; import "../../../components/ha-textfield";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
@ -46,19 +45,13 @@ export class MoreInfoConfigurator extends LitElement {
)} )}
${this.stateObj.attributes.submit_caption ${this.stateObj.attributes.submit_caption
? html`<p class="submit"> ? html`<p class="submit">
<mwc-button <ha-button
raised
.disabled=${this._isConfiguring} .disabled=${this._isConfiguring}
@click=${this._submitClicked} @click=${this._submitClicked}
.loading=${this._isConfiguring}
> >
${this._isConfiguring
? html`<ha-spinner
size="tiny"
aria-label="Configuring"
></ha-spinner>`
: ""}
${this.stateObj.attributes.submit_caption} ${this.stateObj.attributes.submit_caption}
</mwc-button> </ha-button>
</p>` </p>`
: ""} : ""}
</div> </div>
@ -113,12 +106,6 @@ export class MoreInfoConfigurator extends LitElement {
text-align: center; text-align: center;
height: 41px; 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 type { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { isUnavailableState } from "../../../data/entity"; import { isUnavailableState } from "../../../data/entity";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "../../../components/ha-button";
@customElement("more-info-counter") @customElement("more-info-counter")
class MoreInfoCounter extends LitElement { class MoreInfoCounter extends LitElement {
@ -20,29 +20,35 @@ class MoreInfoCounter extends LitElement {
return html` return html`
<div class="actions"> <div class="actions">
<mwc-button <ha-button
appearance="plain"
size="small"
.action=${"increment"} .action=${"increment"}
@click=${this._handleActionClick} @click=${this._handleActionClick}
.disabled=${disabled || .disabled=${disabled ||
Number(this.stateObj.state) === this.stateObj.attributes.maximum} Number(this.stateObj.state) === this.stateObj.attributes.maximum}
> >
${this.hass!.localize("ui.card.counter.actions.increment")} ${this.hass!.localize("ui.card.counter.actions.increment")}
</mwc-button> </ha-button>
<mwc-button <ha-button
appearance="plain"
size="small"
.action=${"decrement"} .action=${"decrement"}
@click=${this._handleActionClick} @click=${this._handleActionClick}
.disabled=${disabled || .disabled=${disabled ||
Number(this.stateObj.state) === this.stateObj.attributes.minimum} Number(this.stateObj.state) === this.stateObj.attributes.minimum}
> >
${this.hass!.localize("ui.card.counter.actions.decrement")} ${this.hass!.localize("ui.card.counter.actions.decrement")}
</mwc-button> </ha-button>
<mwc-button <ha-button
appearance="plain"
size="small"
.action=${"reset"} .action=${"reset"}
@click=${this._handleActionClick} @click=${this._handleActionClick}
.disabled=${disabled} .disabled=${disabled}
> >
${this.hass!.localize("ui.card.counter.actions.reset")} ${this.hass!.localize("ui.card.counter.actions.reset")}
</mwc-button> </ha-button>
</div> </div>
`; `;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -160,7 +160,7 @@ class DialogEditSidebar extends LitElement {
</ha-dialog-header> </ha-dialog-header>
<div slot="content" class="content">${this._renderContent()}</div> <div slot="content" class="content">${this._renderContent()}</div>
<div slot="actions"> <div slot="actions">
<ha-button @click=${this.closeDialog}> <ha-button appearance="plain" @click=${this.closeDialog}>
${this.hass.localize("ui.common.cancel")} ${this.hass.localize("ui.common.cancel")}
</ha-button> </ha-button>
<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 { customElement, property, query, state } from "lit/decorators";
import { storage } from "../../common/decorators/storage"; import { storage } from "../../common/decorators/storage";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import "../../components/buttons/ha-progress-button";
import { createCloseHeading } from "../../components/ha-dialog"; import { createCloseHeading } from "../../components/ha-dialog";
import "../../components/ha-textarea"; import "../../components/ha-textarea";
import type { HaTextArea } from "../../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 type { HomeAssistant } from "../../types";
import { showAlertDialog } from "../generic/show-dialog-box"; import { showAlertDialog } from "../generic/show-dialog-box";
import type { TTSTryDialogParams } from "./show-dialog-tts-try"; import type { TTSTryDialogParams } from "./show-dialog-tts-try";
import "../../components/buttons/ha-progress-button";
@customElement("dialog-tts-try") @customElement("dialog-tts-try")
export class TTSTryDialog extends LitElement { export class TTSTryDialog extends LitElement {
@ -85,11 +85,11 @@ export class TTSTryDialog extends LitElement {
.progress=${this._loadingExample} .progress=${this._loadingExample}
?dialogInitialFocus=${Boolean(this._defaultMessage)} ?dialogInitialFocus=${Boolean(this._defaultMessage)}
slot="primaryAction" slot="primaryAction"
.label=${this.hass.localize("ui.dialogs.tts-try.play")}
@click=${this._playExample} @click=${this._playExample}
.disabled=${!this._valid} .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-progress-button>
</ha-dialog> </ha-dialog>
`; `;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
import type { PropertyValues } from "lit"; import type { PropertyValues } from "lit";
import { css, html, LitElement } from "lit"; import { css, html, LitElement } from "lit";
import { property, state } from "lit/decorators"; import { property, state } from "lit/decorators";
import "@material/mwc-button";
import "../components/ha-spinner"; import "../components/ha-spinner";
import "../components/ha-button";
class HaInitPage extends LitElement { class HaInitPage extends LitElement {
@property({ type: Boolean }) public error = false; @property({ type: Boolean }) public error = false;
@ -22,7 +22,7 @@ class HaInitPage extends LitElement {
<p class="retry-text"> <p class="retry-text">
Retrying in ${this._retryInSeconds} seconds... Retrying in ${this._retryInSeconds} seconds...
</p> </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") ${location.host.includes("ui.nabu.casa")
? html` ? html`
<p> <p>
@ -66,7 +66,7 @@ class HaInitPage extends LitElement {
protected willUpdate(changedProperties: PropertyValues<this>) { protected willUpdate(changedProperties: PropertyValues<this>) {
if (changedProperties.has("error") && this.error) { 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 type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit"; import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import "../components/ha-icon-button-arrow-prev"; import "../components/ha-icon-button-arrow-prev";
import "../components/ha-button";
import "../components/ha-menu-button"; import "../components/ha-menu-button";
import type { HomeAssistant } from "../types"; import type { HomeAssistant } from "../types";
import "../components/ha-alert"; import "../components/ha-alert";
@ -41,9 +41,9 @@ class HassErrorScreen extends LitElement {
<div class="content"> <div class="content">
<ha-alert alert-type="error">${this.error}</ha-alert> <ha-alert alert-type="error">${this.error}</ha-alert>
<slot> <slot>
<mwc-button @click=${this._handleBack}> <ha-button appearance="plain" size="small" @click=${this._handleBack}>
${this.hass?.localize("ui.common.back")} ${this.hass?.localize("ui.common.back")}
</mwc-button> </ha-button>
</slot> </slot>
</div> </div>
`; `;

View File

@ -1,5 +1,4 @@
import { ResizeController } from "@lit-labs/observers/resize-controller"; import { ResizeController } from "@lit-labs/observers/resize-controller";
import "@material/mwc-button/mwc-button";
import { import {
mdiArrowDown, mdiArrowDown,
mdiArrowUp, mdiArrowUp,
@ -768,12 +767,6 @@ export class HaTabsSubpageDataTable extends KeyboardShortcutMixin(LitElement) {
.active-filters ha-svg-icon { .active-filters ha-svg-icon {
color: var(--primary-color); 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 { .active-filters::before {
background-color: var(--primary-color); background-color: var(--primary-color);
opacity: 0.12; opacity: 0.12;

View File

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

View File

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

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