diff --git a/gallery/src/pages/components/ha-bar-button.markdown b/gallery/src/pages/components/ha-bar-button.markdown new file mode 100644 index 0000000000..eb265b8f1f --- /dev/null +++ b/gallery/src/pages/components/ha-bar-button.markdown @@ -0,0 +1,3 @@ +--- +title: Bar Button +--- diff --git a/gallery/src/pages/components/ha-bar-button.ts b/gallery/src/pages/components/ha-bar-button.ts new file mode 100644 index 0000000000..fcdd0f4176 --- /dev/null +++ b/gallery/src/pages/components/ha-bar-button.ts @@ -0,0 +1,189 @@ +import { + mdiFanSpeed1, + mdiFanSpeed2, + mdiFanSpeed3, + mdiLightbulb, +} from "@mdi/js"; +import { css, html, LitElement, TemplateResult } from "lit"; +import { customElement } from "lit/decorators"; +import { ifDefined } from "lit/directives/if-defined"; +import { repeat } from "lit/directives/repeat"; +import "../../../../src/components/ha-bar-button"; +import "../../../../src/components/ha-card"; +import "../../../../src/components/ha-svg-icon"; +import "../../../../src/components/ha-bar-button-group"; + +type Button = { + label: string; + icon?: string; + class?: string; + disabled?: boolean; +}; + +const buttons: Button[] = [ + { + label: "Button", + }, + { + label: "Button and custom style", + class: "custom", + }, + { + label: "Disabled Button", + disabled: true, + }, +]; + +type ButtonGroup = { + vertical?: boolean; + class?: string; +}; + +const buttonGroups: ButtonGroup[] = [ + {}, + { + class: "custom-group", + }, +]; + +@customElement("demo-components-ha-bar-button") +export class DemoHaBarButton extends LitElement { + protected render(): TemplateResult { + return html` + + ${repeat( + buttons, + (btn) => html` +
+
Config: ${JSON.stringify(btn)}
+ + + +
+ ` + )} +
+ + + ${repeat( + buttonGroups, + (group) => html` +
+
Config: ${JSON.stringify(group)}
+ + + + + + + + + + + +
+ ` + )} +
+ +
+

Vertical

+
+ ${repeat( + buttonGroups, + (group) => html` + + + + + + + + + + + + ` + )} +
+
+
+ `; + } + + static get styles() { + return css` + ha-card { + max-width: 600px; + margin: 24px auto; + } + pre { + margin-top: 0; + margin-bottom: 8px; + } + p { + margin: 0; + } + label { + font-weight: 600; + } + .custom { + --button-bar-icon-color: var(--primary-color); + --button-bar-background-color: var(--primary-color); + --button-bar-background-opacity: 0.2; + --button-bar-border-radius: 18px; + height: 100px; + width: 100px; + } + .custom-group { + --button-bar-group-thickness: 100px; + --button-bar-group-border-radius: 18px; + --button-bar-group-spacing: 20px; + } + .custom-group ha-bar-button { + --button-bar-border-radius: 18px; + --mdc-icon-size: 32px; + } + .vertical-buttons { + height: 300px; + display: flex; + flex-direction: row; + justify-content: space-between; + } + p.title { + margin-bottom: 12px; + } + .vertical-switches > *:not(:last-child) { + margin-right: 4px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "demo-components-ha-bar-button": DemoHaBarButton; + } +} diff --git a/src/components/ha-bar-button-group.ts b/src/components/ha-bar-button-group.ts new file mode 100644 index 0000000000..030e4a9e3c --- /dev/null +++ b/src/components/ha-bar-button-group.ts @@ -0,0 +1,63 @@ +import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { customElement, property } from "lit/decorators"; + +@customElement("ha-bar-button-group") +export class HaBarButtonGroup extends LitElement { + @property({ type: Boolean, reflect: true }) + public vertical = false; + + protected render(): TemplateResult { + return html` +
+ +
+ `; + } + + static get styles(): CSSResultGroup { + return css` + :host { + --button-bar-group-spacing: 12px; + --button-bar-group-thickness: 40px; + height: var(--button-bar-group-thickness); + width: auto; + display: block; + } + .container { + display: flex; + flex-direction: row; + width: 100%; + height: 100%; + } + ::slotted(*) { + flex: 1; + height: 100%; + width: 100%; + } + ::slotted(*:not(:last-child)) { + margin-right: var(--button-bar-group-spacing); + margin-inline-end: var(--button-bar-group-spacing); + margin-inline-start: initial; + direction: var(--direction); + } + :host([vertical]) { + width: var(--button-bar-group-thickness); + height: auto; + } + :host([vertical]) .container { + flex-direction: column; + } + :host([vertical]) ::slotted(ha-bar-button:not(:last-child)) { + margin-right: initial; + margin-inline-end: initial; + margin-bottom: var(--button-bar-group-spacing); + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-bar-button-group": HaBarButtonGroup; + } +} diff --git a/src/components/tile/ha-tile-button.ts b/src/components/ha-bar-button.ts similarity index 78% rename from src/components/tile/ha-tile-button.ts rename to src/components/ha-bar-button.ts index 321536d8eb..e8a8f6f47e 100644 --- a/src/components/tile/ha-tile-button.ts +++ b/src/components/ha-bar-button.ts @@ -9,11 +9,9 @@ import { state, } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; -import "../ha-icon"; -import "../ha-svg-icon"; -@customElement("ha-tile-button") -export class HaTileButton extends LitElement { +@customElement("ha-bar-button") +export class HaBarButton extends LitElement { @property({ type: Boolean, reflect: true }) disabled = false; @property() public label?: string; @@ -28,7 +26,7 @@ export class HaTileButton extends LitElement { type="button" class="button" aria-label=${ifDefined(this.label)} - .title=${this.label} + title=${ifDefined(this.label)} .disabled=${Boolean(this.disabled)} @focus=${this.handleRippleFocus} @blur=${this.handleRippleBlur} @@ -81,9 +79,11 @@ export class HaTileButton extends LitElement { static get styles(): CSSResultGroup { return css` :host { - --tile-button-icon-color: var(--primary-text-color); - --tile-button-background-color: var(--disabled-color); - --tile-button-background-opacity: 0.2; + display: block; + --button-bar-icon-color: var(--primary-text-color); + --button-bar-background-color: var(--disabled-color); + --button-bar-background-opacity: 0.2; + --button-bar-border-radius: 10px; width: 40px; height: 40px; -webkit-tap-highlight-color: transparent; @@ -97,7 +97,7 @@ export class HaTileButton extends LitElement { justify-content: center; width: 100%; height: 100%; - border-radius: 10px; + border-radius: var(--button-bar-border-radius); border: none; margin: 0; padding: 0; @@ -106,7 +106,8 @@ export class HaTileButton extends LitElement { outline: none; overflow: hidden; background: none; - --mdc-ripple-color: var(--tile-button-background-color); + z-index: 1; + --mdc-ripple-color: var(--button-bar-background-color); } .button::before { content: ""; @@ -115,22 +116,21 @@ export class HaTileButton extends LitElement { left: 0; height: 100%; width: 100%; - background-color: var(--tile-button-background-color); + background-color: var(--button-bar-background-color); transition: background-color 180ms ease-in-out, opacity 180ms ease-in-out; - opacity: var(--tile-button-background-opacity); + opacity: var(--button-bar-background-opacity); } .button ::slotted(*) { - --mdc-icon-size: 20px; transition: color 180ms ease-in-out; - color: var(--tile-button-icon-color); + color: var(--button-bar-icon-color); pointer-events: none; } .button:disabled { cursor: not-allowed; - --tile-button-background-color: var(--disabled-color); - --tile-button-icon-color: var(--disabled-text-color); - --tile-button-background-opacity: 0.2; + --button-bar-background-color: var(--disabled-color); + --button-bar-icon-color: var(--disabled-text-color); + --button-bar-background-opacity: 0.2; } `; } @@ -138,6 +138,6 @@ export class HaTileButton extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-tile-button": HaTileButton; + "ha-bar-button": HaBarButton; } } diff --git a/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts index 05d4e6dce7..6f75c8c4cf 100644 --- a/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts @@ -7,7 +7,8 @@ import { computeOpenIcon, } from "../../../common/entity/cover_icon"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import "../../../components/tile/ha-tile-button"; +import "../../../components/ha-bar-button"; +import "../../../components/ha-bar-button-group"; import { canClose, canOpen, @@ -69,10 +70,10 @@ class HuiCoverOpenCloseTileFeature } return html` -
+ ${supportsFeature(this.stateObj, CoverEntityFeature.OPEN) ? html` - - + ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.STOP) ? html` - - + ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.CLOSE) ? html` - - + ` : undefined} -
+ `; } static get styles() { return css` - .container { - display: flex; - flex-direction: row; - padding: 0 12px 12px 12px; - width: auto; - } - ha-tile-button { - flex: 1; - } - ha-tile-button:not(:last-child) { - margin-right: 12px; - margin-inline-end: 12px; - margin-inline-start: initial; - direction: var(--direction); + ha-bar-button-group { + margin: 0 12px 12px 12px; + --button-bar-group-spacing: 12px; } `; } diff --git a/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts index 018a0fb307..ca22b29fc1 100644 --- a/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts @@ -3,7 +3,8 @@ import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import "../../../components/tile/ha-tile-button"; +import "../../../components/ha-bar-button"; +import "../../../components/ha-bar-button-group"; import { canCloseTilt, canOpenTilt, @@ -65,10 +66,10 @@ class HuiCoverTiltTileFeature } return html` -
+ ${supportsFeature(this.stateObj, CoverEntityFeature.OPEN_TILT) ? html` - - + ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.STOP_TILT) ? html` - - + ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.CLOSE_TILT) ? html` - - + ` : undefined} -
+ `; } static get styles() { return css` - .container { - display: flex; - flex-direction: row; - padding: 0 12px 12px 12px; - width: auto; - } - ha-tile-button { - flex: 1; - } - ha-tile-button:not(:last-child) { - margin-right: 12px; - margin-inline-end: 12px; - margin-inline-start: initial; - direction: var(--direction); + ha-bar-button-group { + margin: 0 12px 12px 12px; + --button-bar-group-spacing: 12px; } `; } diff --git a/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts b/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts index 6c19958a77..b99671770e 100644 --- a/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts @@ -11,7 +11,8 @@ import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import "../../../components/tile/ha-tile-button"; +import "../../../components/ha-bar-button"; +import "../../../components/ha-bar-button-group"; import { UNAVAILABLE } from "../../../data/entity"; import { canReturnHome, @@ -167,7 +168,7 @@ class HuiVacuumCommandTileFeature const stateObj = this.stateObj as VacuumEntity; return html` -
+ ${VACUUM_COMMANDS.filter( (command) => supportsVacuumCommand(stateObj, command) && @@ -175,7 +176,7 @@ class HuiVacuumCommandTileFeature ).map((command) => { const button = VACUUM_COMMANDS_BUTTONS[command](stateObj); return html` - - + `; })} -
+ `; } static get styles() { return css` - .container { - display: flex; - flex-direction: row; - padding: 0 12px 12px 12px; - width: auto; - } - ha-tile-button { - flex: 1; - } - ha-tile-button:not(:last-child) { - margin-right: 12px; - margin-inline-end: 12px; - margin-inline-start: initial; - direction: var(--direction); + ha-bar-button-group { + margin: 0 12px 12px 12px; + --button-bar-group-spacing: 12px; } `; }