Fix theme and add docs

This commit is contained in:
Wendelin 2025-05-27 15:25:46 +02:00
parent 35b8d9d9bc
commit 98aaf1030a
No known key found for this signature in database
5 changed files with 342 additions and 53 deletions

View File

@ -0,0 +1,98 @@
---
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 shoelace button component.
Check the [shoelace documentation](https://shoelace.style/components/button) for more details.
**Slots**
- default slot: Label of the button
` - no default
- `prefix`: The prefix container (usually for icons).
` - no default
- `suffix`: The suffix container (usually for icons).
` - no default
**Properties/Attributes**
| Name | Type | Default | Description |
| ----------- | ------------------------------------------------ | --------- | ---------------------------------------------------- |
| appearance | "accent"/"filled"/"plain" | "accent" | Sets the button appearance. |
| variants | "primary"/"danger"/"neutral"/"warning"/"success" | "primary" | Sets the button color variant. "primary" is default. |
| size | "small"/"medium" | "medium" | Sets the button size. |
| hideContent | Boolean | false | Hides the button content (for overlays) |
**CSS Custom Properties**
- `--ha-button-font-family` - Font family for the button text.
- `--ha-button-font-weight` - buttons font weight.
- `--ha-button-font-size` - Font weight for the button text.
- `--ha-button-height` - Height of the button.
- `--ha-button-padding-inline-start` - padding for the button text on the left side.
- `--ha-button-padding-inline-end` - padding for the button text on the right side.
- `--ha-button-border-radius` - Border radius for the button.
- `--ha-button-border-width` - Border width for the button.
- `--ha-button-theme-color` - Main color for the button.
- `--ha-button-theme-dark-color` - Dark variant of the main color.
- `--ha-button-theme-darker-color` - Dark variant of the main color.
- `--ha-button-theme-light-color` - Light variant of the main color.
- `--ha-button-text-color` - Text color for the button.
- `--ha-button-focus-ring-color` - Focus ring color for the button.
- `--ha-button-primary-color` - Main color for the primary variant.
- `--ha-button-primary-light-color` - Light color for the primary variant.
- `--ha-button-primary-dark-color` - Dark color for the primary variant.
- `--ha-button-primary-darker-color` - Darker color for the primary variant.
- `--ha-button-error-color` - Main color for the error variant.
- `--ha-button-error-light-color` - Light color for the error variant.
- `--ha-button-error-dark-color` - Dark color for the error variant.
- `--ha-button-error-darker-color` - Darker color for the error variant.
- `--ha-button-neutral-color` - Main color for the neutral variant.
- `--ha-button-neutral-light-color` - Light color for the neutral variant.
- `--ha-button-neutral-dark-color` - Dark color for the neutral variant.
- `--ha-button-neutral-darker-color` - Darker color for the neutral variant.
- `--ha-button-warning-color` - Main color for the warning variant.
- `--ha-button-warning-light-color` - Light color for the warning variant.
- `--ha-button-warning-dark-color` - Dark color for the warning variant.
- `--ha-button-warning-darker-color` - Darker color for the warning variant.
- `--ha-button-success-color` - Main color for the success variant.
- `--ha-button-success-light-color` - Light color for the success variant.
- `--ha-button-success-dark-color` - Dark color for the success variant.
- `--ha-button-success-darker-color` - Darker color for the success variant.

View File

@ -0,0 +1,146 @@
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 = ["primary", "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="prefix"
></ha-svg-icon>
${titleCase(`${variant} ${appearance}`)}
<ha-svg-icon
.path=${mdiHome}
slot="suffix"
></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}
disabled
>
${titleCase(`${variant} ${appearance}`)}
</ha-button>
`
)}
</div>
<div>
${appearances.map(
(appearance) => html`
<ha-button
.appearance=${appearance}
.variant=${variant}
size="small"
disabled
>
${titleCase(`${variant} ${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

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

View File

@ -27,21 +27,43 @@ export type Appearance = "accent" | "filled" | "plain";
*
* @cssprop --ha-button-font-family - Font family for the button text.
* @cssprop --ha-button-font-weight - buttons font weight.
* @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.
* @cssprop --ha-button-focus-ring-color - Focus ring color for the button.
* @cssprop --ha-button-font-size - Font weight for the button text.
* @cssprop --ha-button-height - Height of the button.
* @cssprop --ha-button-padding-inline-start - padding for the button text on the left side.
* @cssprop --ha-button-padding-inline-end - padding for the button text on the right side.
* @cssprop --ha-button-border-radius - Border radius for the button.
* @cssprop --ha-button-border-width - Border width for the button.
* @cssprop --ha-button-theme-color - Main color for the button.
* @cssprop --ha-button-theme-dark-color - Dark variant of the main color.
* @cssprop --ha-button-theme-darker-color - Dark variant of the main color.
* @cssprop --ha-button-theme-light-color - Light variant of the main color.
* @cssprop --ha-button-text-color - Text color for the button.
* @cssprop --ha-button-focus-ring-color - Focus ring color for the button.
* @cssprop --ha-button-primary-color - Main color for the primary variant.
* @cssprop --ha-button-primary-light-color - Light color for the primary variant.
* @cssprop --ha-button-primary-dark-color - Dark color for the primary variant.
* @cssprop --ha-button-primary-darker-color - Darker color for the primary variant.
* @cssprop --ha-button-error-color - Main color for the error variant.
* @cssprop --ha-button-error-light-color - Light color for the error variant.
* @cssprop --ha-button-error-dark-color - Dark color for the error variant.
* @cssprop --ha-button-error-darker-color - Darker color for the error variant.
* @cssprop --ha-button-neutral-color - Main color for the neutral variant.
* @cssprop --ha-button-neutral-light-color - Light color for the neutral variant.
* @cssprop --ha-button-neutral-dark-color - Dark color for the neutral variant.
* @cssprop --ha-button-neutral-darker-color - Darker color for the neutral variant.
* @cssprop --ha-button-warning-color - Main color for the warning variant.
* @cssprop --ha-button-warning-light-color - Light color for the warning variant.
* @cssprop --ha-button-warning-dark-color - Dark color for the warning variant.
* @cssprop --ha-button-warning-darker-color - Darker color for the warning variant.
* @cssprop --ha-button-success-color - Main color for the success variant.
* @cssprop --ha-button-success-light-color - Light color for the success variant.
* @cssprop --ha-button-success-dark-color - Dark color for the success variant.
* @cssprop --ha-button-success-darker-color - Darker color for the success variant.
*
* @attr {("small"|"medium")} size - Sets the button size.
* @attr {("primary"|"danger"|"neutral"|"warning"|"success")} variant - Sets the button color variant. "primary" is default.
* @attr {("accent"|"filled"|"plain")} appearance - Sets the button appearance.
* @attr {boolean} hideContent - Hides the button content (for overlays).
*/
@customElement("ha-button")
export class HaButton extends Button {
@ -78,41 +100,41 @@ export class HaButton extends Button {
--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-active-color: #00669c;
--ha-button-theme-lighter-color: #dff3fc;
--ha-button-theme-color: var(--ha-button-primary-color);
--ha-button-theme-light-color: var(--ha-button-primary-light-color);
--ha-button-theme-dark-color: var(--ha-button-primary-dark-color);
--ha-button-theme-darker-color: var(--ha-button-primary-darker-color);
line-height: 1;
--sl-input-border-width: var(--ha-button-border-width, 0);
}
:host([variant="danger"]) {
--ha-button-theme-color: #b30532;
--ha-button-theme-darker-color: #64031d;
--ha-button-theme-active-color: #410213;
--ha-button-theme-lighter-color: #ffdedc;
--ha-button-theme-color: var(--ha-button-error-color);
--ha-button-theme-light-color: var(--ha-button-error-light-color);
--ha-button-theme-dark-color: var(--ha-button-error-dark-color);
--ha-button-theme-darker-color: var(--ha-button-error-darker-color);
}
:host([variant="neutral"]) {
--ha-button-theme-color: #545868;
--ha-button-theme-darker-color: #373a44;
--ha-button-theme-active-color: #1c1d22;
--ha-button-theme-lighter-color: #767986;
--ha-button-theme-color: var(--ha-button-neutral-color);
--ha-button-theme-light-color: var(--ha-button-neutral-light-color);
--ha-button-theme-dark-color: var(--ha-button-neutral-dark-color);
--ha-button-theme-darker-color: var(--ha-button-neutral-darker-color);
}
:host([variant="warning"]) {
--ha-button-theme-color: #b45f04;
--ha-button-theme-darker-color: #9c5203;
--ha-button-theme-active-color: #693803;
--ha-button-theme-lighter-color: #fef3cd;
--ha-button-theme-color: var(--ha-button-warning-color);
--ha-button-theme-light-color: var(--ha-button-warning-light-color);
--ha-button-theme-dark-color: var(--ha-button-warning-dark-color);
--ha-button-theme-darker-color: var(--ha-button-warning-darker-color);
}
:host([variant="success"]) {
--ha-button-theme-color: var(--success-color);
--ha-button-theme-darker-color: #275e2a;
--ha-button-theme-active-color: #1a411c;
--ha-button-theme-lighter-color: #5ce463;
--ha-button-theme-color: var(--ha-button-success-color);
--ha-button-theme-light-color: var(--ha-button-success-light-color);
--ha-button-theme-dark-color: var(--ha-button-success-dark-color);
--ha-button-theme-darker-color: var(--ha-button-success-darker-color);
}
.button {
@ -131,9 +153,10 @@ export class HaButton extends Button {
.button--standard.button--neutral,
.button--standard.button--danger,
.button--standard.button--warning,
.button--standard.button--success {
.button--standard.button--success,
:host([appearance="filled"]) .button:hover:not(.button--disabled) {
background-color: var(--ha-button-theme-color);
color: var(--ha-button-text-color, var(--white-color));
color: var(--ha-button-text-color, var(--text-primary-color));
}
.button:hover:not(.button--disabled),
.button--standard.button--default:hover:not(.button--disabled),
@ -141,9 +164,10 @@ export class HaButton extends Button {
.button--standard.button--neutral:hover:not(.button--disabled),
.button--standard.button--warning:hover:not(.button--disabled),
.button--standard.button--success:hover:not(.button--disabled),
.button--standard.button--danger:hover:not(.button--disabled) {
background-color: var(--ha-button-theme-darker-color);
color: var(--ha-button-text-color, var(--white-color));
.button--standard.button--danger:hover:not(.button--disabled),
:host([appearance="filled"]) .button:active:not(.button--disabled) {
background-color: var(--ha-button-theme-dark-color);
color: var(--ha-button-text-color, var(--text-primary-color));
}
.button--standard.button--default:active:not(.button--disabled),
@ -153,34 +177,22 @@ export class HaButton extends Button {
.button--standard.button--warning:active:not(.button--disabled),
.button--standard.button--success:active:not(.button--disabled),
.button:active:not(.button--disabled) {
background-color: var(--ha-button-theme-active-color);
color: var(--ha-button-text-color, var(--white-color));
}
:host([appearance="filled"]) .button {
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([appearance="filled"]) .button:active:not(.button--disabled) {
background-color: var(--ha-button-theme-darker-color);
color: var(--white-color);
color: var(--ha-button-text-color, var(--text-primary-color));
}
:host([appearance="filled"]) .button,
:host([appearance="plain"]) .button:hover:not(.button--disabled) {
background-color: var(--ha-button-theme-light-color);
color: var(--ha-button-theme-color);
}
:host([appearance="plain"]) .button {
background-color: transparent;
color: var(--ha-button-text-color, var(--ha-button-theme-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));
color: var(--ha-button-theme-color);
}
:host([appearance="plain"]) .button:active:not(.button--disabled) {
background-color: var(--ha-button-theme-color);
color: var(--white-color);
color: var(--ha-button-text-color, var(--text-primary-color));
}
.button.button--medium .button__label {

View File

@ -17,6 +17,7 @@ export const colorStyles = css`
/* main interface colors */
--primary-color: #03a9f4;
--dark-primary-color: #0288d1;
--darker-primary-color: #016194;
--light-primary-color: #b3e5fc;
--accent-color: #ff9800;
--divider-color: rgba(0, 0, 0, 0.12);
@ -290,6 +291,32 @@ export const colorStyles = css`
);
--chip-background-color: rgba(var(--rgb-primary-text-color), 0.15);
/* ha-button */
--ha-button-primary-color: var(--primary-color);
--ha-button-primary-light-color: var(--light-primary-color);
--ha-button-primary-dark-color: var(--dark-primary-color);
--ha-button-primary-darker-color: var(--darker-primary-color);
--ha-button-error-color: #B30532;
--ha-button-error-light-color: #FFDEDC;
--ha-button-error-dark-color: #6e021f;
--ha-button-error-darker-color: #530016;
--ha-button-warning-color: var(--warning-color);
--ha-button-warning-light-color: #fae3b9c1;
--ha-button-warning-dark-color: #ce8600;
--ha-button-warning-darker-color: #a36a00;
--ha-button-success-color: var(--success-color);
--ha-button-success-light-color: #add1ae;
--ha-button-success-dark-color: #317534;
--ha-button-success-darker-color: #225524;
--ha-button-neutral-color: #545868;
--ha-button-neutral-light-color: #d2d5e0;
--ha-button-neutral-dark-color: #3c3f4b;
--ha-button-neutral-darker-color: #262830;
/* Vaadin */
--material-body-text-color: var(--primary-text-color);
--material-background-color: var(--card-background-color);
@ -352,6 +379,11 @@ const darkColorStyles = css`
--map-filter: invert(0.9) hue-rotate(170deg) brightness(1.5) contrast(1.2)
saturate(0.3);
--disabled-color: #464646;
--ha-button-primary-light-color: #4082a040;
--ha-button-warning-light-color: #917b54c1;
--ha-button-neutral-color: #d9dae0;
--ha-button-neutral-light-color: #6a7081;
}
`;
export const colorDerivedVariables = extractDerivedVars(colorStyles);