Finish new button api

This commit is contained in:
Wendelin 2025-05-22 11:54:41 +02:00
parent 422f05dc3b
commit bc3933d7d7
No known key found for this signature in database
4 changed files with 113 additions and 127 deletions

View File

@ -3,141 +3,123 @@ import styles from "@shoelace-style/shoelace/dist/components/button/button.style
import { css } from "lit";
import { customElement, property } from "lit/decorators";
/**
* Home Assistant button component
*
* @element ha-button
* @extends {Button}
*
* @summary
* A stylable button component supporting Home Assistant theming, variants, and appearances.
*
* @slot - Label of the button
* @slot prefix - The prefix container (usually for icons).
* @slot suffix - The suffix container (usually for icons).
*
* @csspart base - The component's base wrapper.
* @csspart prefix - The container that wraps the prefix.
* @csspart label - The button's label.
* @csspart suffix - 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-font-family - Font family for the button text.
* @cssprop --ha-font-weight-medium - Medium font weight for button text.
* @cssprop --ha-button-line-height - Line height for button text.
* @cssprop --ha-button-border-width - Border width for the button.
* @cssprop --ha-button-theme-color - Main color for the button.
* @cssprop --ha-button-theme-darker-color - Darker variant of the main color.
* @cssprop --ha-button-theme-lighter-color - Lighter variant of the main color.
* @cssprop --ha-button-height - Height of the button.
* @cssprop --ha-button-border-radius - Border radius for the button.
* @cssprop --ha-button-text-color - Text color for the button.
*
* @attr {("small"|"medium")} size - Sets the button size.
* @attr {("primary"|"danger"|"neutral")} variant - Sets the button color variant. "primary" is default.
* @attr {("accent"|"filled"|"plain")} appearance - Sets the button appearance.
*/
@customElement("ha-button")
export class HaButton extends Button {
@property({ type: Boolean }) pill = true;
@property() appearance?: "accent" | "filled" | "plain";
static override styles = [
styles,
css`
:host {
--sl-input-border-width: 0;
--sl-input-font-family: var(
--ha-button-font-family,
var(--ha-font-family-body)
);
--sl-font-weight-semibold: var(--ha-font-weight-medium);
--sl-transition-x-fast: 0.1s; /* ? */
--sl-focus-ring: none; /* ? */
--sl-focus-ring-offset: 0; /* ? */
--sl-font-weight-semibold: var(
--ha-button-font-weight,
var(--ha-font-weight-medium)
);
--sl-transition-x-fast: 0.4s;
--sl-focus-ring: solid 4px var(--accent-color);
--sl-focus-ring-offset: 1px;
--sl-spacing-medium: 16px;
--sl-spacing-small: 12px;
--sl-spacing-x-small: 8px;
--ha-button-theme-color: var(--primary-color);
--ha-button-theme-darker-color: var(--dark-primary-color);
--ha-button-theme-lighter-color: var(--light-primary-color);
line-height: var(--ha-button-line-height, var(--ha-line-height-normal));
--sl-input-border-width: var(--ha-button-border-width, 0);
}
:host([destructive]), /* Deprecated */
:host([variant="danger"]) {
--ha-button-theme-color: var(--error-color);
--ha-button-theme-darker-color: var(--error-color-darker);
--ha-button-theme-lighter-color: var(--error-color-lighter);
}
:host([variant="neutral"]) {
--ha-button-theme-color: var(--primary-text-color);
--ha-button-theme-darker-color: var(--dark-primary-color);
--ha-button-theme-lighter-color: var(--light-primary-color);
}
.button {
height: 40px;
height: var(--ha-button-height, var(--button-height, 40px));
align-items: center;
border-radius: var(--ha-button-border-radius, 48px);
}
.button.button--small {
height: 32px;
border-radius: var(--ha-button-border-radius, 32px);
height: var(--ha-button-height, var(--button-height, 32px));
}
/* Default */
.button--standard.button--default,
.button--standard.button--primary:active:not(.button--disabled) {
background-color: var(
--ha-button-background-color,
var(--primary-color)
);
.button,
.button:active:not(.button--disabled) {
background-color: var(--ha-button-theme-color);
color: var(--ha-button-text-color, var(--white-color));
}
.button--standard.button--default:hover:not(.button--disabled) {
background-color: var(
--ha-button-background-color,
var(--dark-primary-color)
);
color: var(--ha-button-text-color, var(--white-color));
.button:hover:not(.button--disabled) {
background-color: var(--ha-button-theme-darker-color);
}
/* Danger */
:host([destructive]) .button--standard,
.button--standard.button--danger,
.button--standard.button--danger:active:not(.button--disabled) {
background-color: var(--ha-button-background-color, var(--error-color));
color: var(--ha-button-text-color, var(--white-color));
:host([appearance="filled"]) .button,
:host([appearance="filled"]) .button:active:not(.button--disabled) {
background-color: var(--ha-button-theme-lighter-color);
color: var(--ha-button-text-color, var(--ha-button-theme-color));
}
:host([appearance="filled"]) .button:hover:not(.button--disabled) {
background-color: var(--ha-button-theme-color);
color: var(--white-color);
}
:host([destructive]) .button--standard:hover:not(.button--disabled),
.button--standard.button--danger:hover:not(.button--disabled) {
background-color: var(--ha-button-background-color, var(--error-color));
color: var(--ha-button-text-color, var(--white-color));
}
/*
* Text buttons
*/
.button--text,
.button--text:active:not(.button--disabled) {
color: var(--ha-button-text-color, var(--primary-color));
}
.button--text:hover:not(.button--disabled),
.button--text:focus-visible:not(.button--disabled) {
:host([appearance="plain"]) .button,
:host([appearance="plain"]) .button:active:not(.button--disabled) {
background-color: transparent;
border-color: transparent;
color: var(--ha-button-text-color, var(--dark-primary-color));
color: var(--ha-button-text-color, var(--ha-button-theme-color));
}
.button--pill.button--small {
border-radius: 30px;
}
.button--pill.button--medium {
border-radius: 48px;
}
/*
* Button spacing
*/
.button--has-label.button--small .button__label {
padding: 0 12px;
}
.button--has-label.button--medium .button__label {
padding: 0 16px;
}
.button--has-prefix.button--small,
.button--has-prefix.button--small .button__label {
padding-inline-start: 8px;
}
.button--has-prefix.button--medium,
.button--has-prefix.button--medium .button__label {
padding-inline-start: 12px;
}
.button--has-suffix.button--small,
.button--caret.button--small,
.button--has-suffix.button--small .button__label,
.button--caret.button--small .button__label {
padding-inline-end: 8px;
}
.button--has-suffix.button--medium,
.button--caret.button--medium,
.button--has-suffix.button--medium .button__label,
.button--caret.button--medium .button__label {
padding-inline-end: 12px;
}
::slotted([slot="icon"]) {
margin-inline-start: 0px;
margin-inline-end: 8px;
direction: var(--direction);
display: block;
}
.mdc-button {
height: var(--button-height, 36px);
}
.trailing-icon {
display: flex;
}
.slot-container {
overflow: var(--button-slot-container-overflow, visible);
}
:host([destructive]) {
--mdc-theme-primary: var(--error-color);
:host([appearance="plain"]) .button:hover:not(.button--disabled) {
background-color: var(--ha-button-theme-lighter-color);
color: var(--ha-button-text-color, var(--ha-button-theme-darker-color));
}
`,
];

View File

@ -4,6 +4,9 @@ import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-button";
import "../../../components/ha-button-menu";
import "../../../components/ha-list-item";
import {
ATTENTION_SOURCES,
DISCOVERY_SOURCES,
@ -17,9 +20,6 @@ import type { HomeAssistant } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url";
import type { DataEntryFlowProgressExtended } from "./ha-config-integrations";
import "./ha-integration-action-card";
import "../../../components/ha-button-menu";
import "../../../components/ha-button";
import "../../../components/ha-list-item";
@customElement("ha-config-flow-card")
export class HaConfigFlowCard extends LitElement {
@ -41,24 +41,25 @@ export class HaConfigFlowCard extends LitElement {
.domain=${this.flow.handler}
.label=${this.flow.localized_title}
>
${DISCOVERY_SOURCES.includes(this.flow.context.source) &&
this.flow.context.unique_id
? html`<ha-button appearance="plain" @click=${this._ignoreFlow}
>${this.hass.localize(
"ui.panel.config.integrations.ignore.ignore"
)}</ha-button
>`
: ""}
<ha-button
unelevated
@click=${this._continueFlow}
.label=${this.hass.localize(
variant=${attention ? "danger" : "primary"}
appearance="filled"
>
${this.hass.localize(
attention
? "ui.panel.config.integrations.reconfigure"
: "ui.common.add"
)}
></ha-button>
${DISCOVERY_SOURCES.includes(this.flow.context.source) &&
this.flow.context.unique_id
? html`<ha-button
@click=${this._ignoreFlow}
.label=${this.hass.localize(
"ui.panel.config.integrations.ignore.ignore"
)}
></ha-button>`
: ""}
</ha-button>
${this.flow.context.configuration_url || this.manifest
? html`<ha-button-menu slot="header-button">
<ha-icon-button

View File

@ -4,6 +4,7 @@ import { LitElement, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import { PROTOCOL_INTEGRATIONS } from "../../../common/integrations/protocolIntegrationPicked";
import { computeRTL } from "../../../common/util/compute_rtl";
import "../../../components/ha-button";
import "../../../components/ha-card";
@ -23,7 +24,6 @@ import { haStyle } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types";
import type { ConfigEntryExtended } from "./ha-config-integrations";
import "./ha-integration-header";
import { PROTOCOL_INTEGRATIONS } from "../../../common/integrations/protocolIntegrationPicked";
@customElement("ha-integration-card")
export class HaIntegrationCard extends LitElement {
@ -120,7 +120,7 @@ export class HaIntegrationCard extends LitElement {
? `/config/devices/device/${devices[0].id}`
: `/config/devices/dashboard?historyBack=1&domain=${this.domain}`}
>
<ha-button>
<ha-button appearance="plain">
${this.hass.localize(
`ui.panel.config.integrations.config_entry.${
services ? "services" : "devices"
@ -133,7 +133,7 @@ export class HaIntegrationCard extends LitElement {
? html`<a
href=${`/config/entities?historyBack=1&domain=${this.domain}`}
>
<ha-button>
<ha-button appearance="plain">
${this.hass.localize(
`ui.panel.config.integrations.config_entry.entities`,
{ count: entitiesCount }
@ -144,7 +144,7 @@ export class HaIntegrationCard extends LitElement {
? html`<a
href=${`/config/integrations/integration/${this.domain}`}
>
<ha-button>
<ha-button appearance="plain">
${this.hass.localize(
`ui.panel.config.integrations.config_entry.entries`,
{
@ -309,6 +309,7 @@ export class HaIntegrationCard extends LitElement {
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px 16px 4px 4px;
}
.debug-logging {
--state-color: var(--warning-color);

View File

@ -34,6 +34,8 @@ export const colorStyles = css`
--scrollbar-thumb-color: rgb(194, 194, 194);
--error-color: #db4437;
--error-color-lighter: #ffdedc;
--error-color-darker: #b30532;
--warning-color: #ffa600;
--success-color: #43a047;
--info-color: #039be5;