Migrate ha-tooltip to webawesome (#26540)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Simon Lamon
2025-09-12 13:09:24 +02:00
committed by GitHub
parent 0d8d18617c
commit dcbc8b627f
34 changed files with 451 additions and 449 deletions

View File

@@ -6,21 +6,23 @@ A tooltip's target is its _first child element_, so you should only wrap one ele
Tooltips use `display: contents` so they won't interfere with how elements are positioned in a flex or grid layout. Tooltips use `display: contents` so they won't interfere with how elements are positioned in a flex or grid layout.
<ha-tooltip content="This is a tooltip"> <ha-button id="hover">Hover Me</ha-button>
<ha-button>Hover Me</ha-button> <ha-tooltip for="hover">
This is a tooltip
</ha-tooltip> </ha-tooltip>
``` ```
<ha-tooltip content="This is a tooltip"> <ha-button id="hover">Hover Me</ha-button>
<ha-button>Hover Me</ha-button> <ha-tooltip for="hover">
This is a tooltip
</ha-tooltip> </ha-tooltip>
``` ```
## Documentation ## Documentation
This element is based on shoelace `sl-tooltip` it only sets some css tokens and has a custom show/hide animation. This element is based on webawesome `wa-tooltip` it only sets some css tokens and has a custom show/hide animation.
<a href="https://shoelace.style/components/tooltip" target="_blank" rel="noopener noreferrer">Shoelace documentation</a> <a href="https://webawesome.com/docs/components/tooltip/" target="_blank" rel="noopener noreferrer">Webawesome documentation</a>
### HA style tokens ### HA style tokens
@@ -28,7 +30,7 @@ In your theme settings use this without the prefixed `--`.
- `--ha-tooltip-border-radius` (Default: 4px) - `--ha-tooltip-border-radius` (Default: 4px)
- `--ha-tooltip-arrow-size` (Default: 8px) - `--ha-tooltip-arrow-size` (Default: 8px)
- `--sl-tooltip-font-family` (Default: `var(--ha-font-family-body)`) - `--wa-tooltip-font-family` (Default: `var(--ha-font-family-body)`)
- `--ha-tooltip-font-size` (Default: `var(--ha-font-size-s)`) - `--ha-tooltip-font-size` (Default: `var(--ha-font-size-s)`)
- `--sl-tooltip-font-weight` (Default: `var(--ha-font-weight-normal)`) - `--wa-tooltip-font-weight` (Default: `var(--ha-font-weight-normal)`)
- `--sl-tooltip-line-height` (Default: `var(--ha-line-height-condensed)`) - `--wa-tooltip-line-height` (Default: `var(--ha-line-height-condensed)`)

View File

@@ -119,26 +119,27 @@ class HassioRepositoriesDialog extends LitElement {
<div>${repo.url}</div> <div>${repo.url}</div>
</div> </div>
<ha-tooltip <ha-tooltip
.for="icon-button-${repo.slug}"
class="delete" class="delete"
slot="end" slot="end"
.content=${this._dialogParams!.supervisor.localize( >
${this._dialogParams!.supervisor.localize(
usedRepositories.includes(repo.slug) usedRepositories.includes(repo.slug)
? "dialog.repositories.used" ? "dialog.repositories.used"
: "dialog.repositories.remove" : "dialog.repositories.remove"
)} )}
>
<div>
<ha-icon-button
.disabled=${usedRepositories.includes(repo.slug)}
.slug=${repo.slug}
.path=${usedRepositories.includes(repo.slug)
? mdiDeleteOff
: mdiDelete}
@click=${this._removeRepository}
>
</ha-icon-button>
</div>
</ha-tooltip> </ha-tooltip>
<div .id="icon-button-${repo.slug}">
<ha-icon-button
.disabled=${usedRepositories.includes(repo.slug)}
.slug=${repo.slug}
.path=${usedRepositories.includes(repo.slug)
? mdiDeleteOff
: mdiDelete}
@click=${this._removeRepository}
>
</ha-icon-button>
</div>
</ha-md-list-item> </ha-md-list-item>
` `
) )

View File

@@ -51,7 +51,7 @@
"@fullcalendar/list": "6.1.19", "@fullcalendar/list": "6.1.19",
"@fullcalendar/luxon3": "6.1.19", "@fullcalendar/luxon3": "6.1.19",
"@fullcalendar/timegrid": "6.1.19", "@fullcalendar/timegrid": "6.1.19",
"@home-assistant/webawesome": "3.0.0-beta.4.ha.2", "@home-assistant/webawesome": "3.0.0-beta.4.ha.3",
"@lezer/highlight": "1.2.1", "@lezer/highlight": "1.2.1",
"@lit-labs/motion": "1.0.9", "@lit-labs/motion": "1.0.9",
"@lit-labs/observers": "2.0.6", "@lit-labs/observers": "2.0.6",
@@ -84,7 +84,6 @@
"@mdi/js": "7.4.47", "@mdi/js": "7.4.47",
"@mdi/svg": "7.4.47", "@mdi/svg": "7.4.47",
"@replit/codemirror-indentation-markers": "6.5.3", "@replit/codemirror-indentation-markers": "6.5.3",
"@shoelace-style/shoelace": "2.20.1",
"@swc/helpers": "0.5.17", "@swc/helpers": "0.5.17",
"@thomasloven/round-slider": "0.6.0", "@thomasloven/round-slider": "0.6.0",
"@tsparticles/engine": "3.9.1", "@tsparticles/engine": "3.9.1",

View File

@@ -12,9 +12,8 @@ class HaDataTableIcon extends LitElement {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<ha-tooltip .content=${this.tooltip}> <ha-tooltip for="svg-icon">${this.tooltip}</ha-tooltip>
<ha-svg-icon .path=${this.path}></ha-svg-icon> <ha-svg-icon id="svg-icon" .path=${this.path}></ha-svg-icon>
</ha-tooltip>
`; `;
} }

View File

@@ -36,39 +36,38 @@ class StateInfo extends LitElement {
</div> </div>
${this.inDialog ${this.inDialog
? html`<div class="time-ago"> ? html`<div class="time-ago">
<ha-tooltip> <ha-tooltip for="relative-time">
<ha-relative-time <div class="row">
.hass=${this.hass} <span class="column-name">
.datetime=${this.stateObj.last_changed} ${this.hass.localize(
capitalize "ui.dialogs.more_info_control.last_changed"
></ha-relative-time> )}:
<div slot="content"> </span>
<div class="row"> <ha-relative-time
<span class="column-name"> .hass=${this.hass}
${this.hass.localize( .datetime=${this.stateObj.last_changed}
"ui.dialogs.more_info_control.last_changed" capitalize
)}: ></ha-relative-time>
</span> </div>
<ha-relative-time <div class="row">
.hass=${this.hass} <span>
.datetime=${this.stateObj.last_changed} ${this.hass.localize(
capitalize "ui.dialogs.more_info_control.last_updated"
></ha-relative-time> )}:
</div> </span>
<div class="row"> <ha-relative-time
<span> .hass=${this.hass}
${this.hass.localize( .datetime=${this.stateObj.last_updated}
"ui.dialogs.more_info_control.last_updated" capitalize
)}: ></ha-relative-time>
</span>
<ha-relative-time
.hass=${this.hass}
.datetime=${this.stateObj.last_updated}
capitalize
></ha-relative-time>
</div>
</div> </div>
</ha-tooltip> </ha-tooltip>
<ha-relative-time
id="relative-time"
.hass=${this.hass}
.datetime=${this.stateObj.last_changed}
capitalize
></ha-relative-time>
</div>` </div>`
: html`<div class="extra-info"><slot></slot></div>`} : html`<div class="extra-info"><slot></slot></div>`}
</div>`; </div>`;

View File

@@ -67,20 +67,19 @@ export class HaAnalytics extends LitElement {
)} )}
</span> </span>
<span> <span>
<ha-tooltip <ha-switch
content=${this.localize( .id="switch-${preference}"
`ui.panel.${this.translationKeyPanel}.analytics.need_base_enabled` @change=${this._handleRowClick}
)} .checked=${this.analytics?.preferences[preference]}
placement="right" .preference=${preference}
name=${preference}
?disabled=${baseEnabled} ?disabled=${baseEnabled}
> >
<ha-switch </ha-switch>
@change=${this._handleRowClick} <ha-tooltip .for="switch-${preference}" placement="right">
.checked=${this.analytics?.preferences[preference]} ${this.localize(
.preference=${preference} `ui.panel.${this.translationKeyPanel}.analytics.need_base_enabled`
name=${preference} )}
>
</ha-switch>
</ha-tooltip> </ha-tooltip>
</span> </span>
</ha-settings-row> </ha-settings-row>

View File

@@ -25,8 +25,9 @@ export class HaHelpTooltip extends LitElement {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<ha-tooltip .placement=${this.position} .content=${this.label}> <ha-svg-icon id="svg-icon" .path=${mdiHelpCircle}></ha-svg-icon>
<ha-svg-icon .path=${mdiHelpCircle}></ha-svg-icon> <ha-tooltip for="svg-icon" .placement=${this.position}>
${this.label}
</ha-tooltip> </ha-tooltip>
`; `;
} }

View File

@@ -74,16 +74,16 @@ export class HaIconOverflowMenu extends LitElement {
: item.divider : item.divider
? html`<div role="separator"></div>` ? html`<div role="separator"></div>`
: html`<ha-tooltip : html`<ha-tooltip
.disabled=${!item.tooltip} .disabled=${!item.tooltip}
.content=${item.tooltip ?? ""} .for="icon-button-${item.label}"
> >${item.tooltip ?? ""} </ha-tooltip
<ha-icon-button ><ha-icon-button
.id="icon-button-${item.label}"
@click=${item.action} @click=${item.action}
.label=${item.label} .label=${item.label}
.path=${item.path} .path=${item.path}
?disabled=${item.disabled} ?disabled=${item.disabled}
></ha-icon-button> ></ha-icon-button> `
</ha-tooltip>`
)} )}
`} `}
`; `;

View File

@@ -343,40 +343,36 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
${type === "entity_id" ${type === "entity_id"
? "" ? ""
: html`<span role="gridcell"> : html`<span role="gridcell">
<ha-tooltip <ha-tooltip .for="expand-${id}"
.content=${this.hass.localize( >${this.hass.localize(
`ui.components.target-picker.expand_${type}` `ui.components.target-picker.expand_${type}`
)} )}
>
<ha-icon-button
class="expand-btn mdc-chip__icon mdc-chip__icon--trailing"
.label=${this.hass.localize(
"ui.components.target-picker.expand"
)}
.path=${mdiUnfoldMoreVertical}
hide-title
.id=${id}
.type=${type}
@click=${this._handleExpand}
></ha-icon-button>
</ha-tooltip> </ha-tooltip>
<ha-icon-button
class="expand-btn mdc-chip__icon mdc-chip__icon--trailing"
.label=${this.hass.localize(
"ui.components.target-picker.expand"
)}
.path=${mdiUnfoldMoreVertical}
hide-title
.id="expand-${id}"
.type=${type}
@click=${this._handleExpand}
></ha-icon-button>
</span>`} </span>`}
<span role="gridcell"> <span role="gridcell">
<ha-tooltip <ha-tooltip .for="remove-${id}">
.content=${this.hass.localize( ${this.hass.localize(`ui.components.target-picker.remove_${type}`)}
`ui.components.target-picker.remove_${type}`
)}
>
<ha-icon-button
class="mdc-chip__icon mdc-chip__icon--trailing"
.label=${this.hass.localize("ui.components.target-picker.remove")}
.path=${mdiClose}
hide-title
.id=${id}
.type=${type}
@click=${this._handleRemove}
></ha-icon-button>
</ha-tooltip> </ha-tooltip>
<ha-icon-button
class="mdc-chip__icon mdc-chip__icon--trailing"
.label=${this.hass.localize("ui.components.target-picker.remove")}
.path=${mdiClose}
hide-title
.id="remove-${id}"
.type=${type}
@click=${this._handleRemove}
></ha-icon-button>
</span> </span>
</div> </div>
`; `;

View File

@@ -1,50 +1,47 @@
import SlTooltip from "@shoelace-style/shoelace/dist/components/tooltip/tooltip.component"; import Tooltip from "@home-assistant/webawesome/dist/components/tooltip/tooltip";
import styles from "@shoelace-style/shoelace/dist/components/tooltip/tooltip.styles";
import { css } from "lit"; import { css } from "lit";
import { customElement } from "lit/decorators"; import type { CSSResultGroup } from "lit";
import { setDefaultAnimation } from "@shoelace-style/shoelace/dist/utilities/animation-registry"; import { customElement, property } from "lit/decorators";
setDefaultAnimation("tooltip.show", {
keyframes: [{ opacity: 0 }, { opacity: 1 }],
options: { duration: 150, easing: "ease" },
});
setDefaultAnimation("tooltip.hide", {
keyframes: [{ opacity: 1 }, { opacity: 0 }],
options: { duration: 400, easing: "ease" },
});
@customElement("ha-tooltip") @customElement("ha-tooltip")
export class HaTooltip extends SlTooltip { export class HaTooltip extends Tooltip {
static override styles = [ /** The amount of time to wait before showing the tooltip when the user mouses in. */
styles, @property({ attribute: "show-delay", type: Number }) showDelay = 150;
css`
:host { /** The amount of time to wait before hiding the tooltip when the user mouses out.. */
--sl-tooltip-background-color: var(--secondary-background-color); @property({ attribute: "hide-delay", type: Number }) hideDelay = 400;
--sl-tooltip-color: var(--primary-text-color);
--sl-tooltip-font-family: var( static get styles(): CSSResultGroup {
--ha-tooltip-font-family, return [
var(--ha-font-family-body) Tooltip.styles,
); css`
--sl-tooltip-font-size: var( :host {
--ha-tooltip-font-size, --wa-tooltip-background-color: var(--secondary-background-color);
var(--ha-font-size-s) --wa-tooltip-color: var(--primary-text-color);
); --wa-tooltip-font-family: var(
--sl-tooltip-font-weight: var( --ha-tooltip-font-family,
--ha-tooltip-font-weight, var(--ha-font-family-body)
var(--ha-font-weight-normal) );
); --wa-tooltip-font-size: var(
--sl-tooltip-line-height: var( --ha-tooltip-font-size,
--ha-tooltip-line-height, var(--ha-font-size-s)
var(--ha-line-height-condensed) );
); --wa-tooltip-font-weight: var(
--sl-tooltip-padding: 8px; --ha-tooltip-font-weight,
--sl-tooltip-border-radius: var(--ha-tooltip-border-radius, 4px); var(--ha-font-weight-normal)
--sl-tooltip-arrow-size: var(--ha-tooltip-arrow-size, 8px); );
--sl-z-index-tooltip: var(--ha-tooltip-z-index, 1000); --wa-tooltip-line-height: var(
} --ha-tooltip-line-height,
`, var(--ha-line-height-condensed)
]; );
--wa-tooltip-padding: 8px;
--wa-tooltip-border-radius: var(--ha-tooltip-border-radius, 4px);
--wa-tooltip-arrow-size: var(--ha-tooltip-arrow-size, 8px);
--wa-z-index-tooltip: var(--ha-tooltip-z-index, 1000);
}
`,
];
}
} }
declare global { declare global {

View File

@@ -642,9 +642,10 @@ export class HaMediaPlayerBrowse extends LitElement {
` `
: ""} : ""}
</div> </div>
<ha-tooltip distance="-4" .content=${child.title}> <ha-tooltip .for="grid-${child.title}" distance="-4">
<div class="title">${child.title}</div> ${child.title}
</ha-tooltip> </ha-tooltip>
<div .id="grid-${child.title}" class="title">${child.title}</div>
</ha-card> </ha-card>
</div> </div>
`; `;

View File

@@ -166,37 +166,36 @@ class MoreInfoWeather extends LitElement {
${this.hass.formatEntityState(this.stateObj)} ${this.hass.formatEntityState(this.stateObj)}
</div> </div>
<div class="time-ago"> <div class="time-ago">
<ha-tooltip> <ha-relative-time
<ha-relative-time id="relative-time"
.hass=${this.hass} .hass=${this.hass}
.datetime=${this.stateObj.last_changed} .datetime=${this.stateObj.last_changed}
capitalize capitalize
></ha-relative-time> ></ha-relative-time>
<div slot="content"> <ha-tooltip for="relative-time">
<div class="row"> <div class="row">
<span class="column-name"> <span class="column-name">
${this.hass.localize( ${this.hass.localize(
"ui.dialogs.more_info_control.last_changed" "ui.dialogs.more_info_control.last_changed"
)}: )}:
</span> </span>
<ha-relative-time <ha-relative-time
.hass=${this.hass} .hass=${this.hass}
.datetime=${this.stateObj.last_changed} .datetime=${this.stateObj.last_changed}
capitalize capitalize
></ha-relative-time> ></ha-relative-time>
</div> </div>
<div class="row"> <div class="row">
<span> <span>
${this.hass.localize( ${this.hass.localize(
"ui.dialogs.more_info_control.last_updated" "ui.dialogs.more_info_control.last_updated"
)}: )}:
</span> </span>
<ha-relative-time <ha-relative-time
.hass=${this.hass} .hass=${this.hass}
.datetime=${this.stateObj.last_updated} .datetime=${this.stateObj.last_updated}
capitalize capitalize
></ha-relative-time> ></ha-relative-time>
</div>
</div> </div>
</ha-tooltip> </ha-tooltip>
</div> </div>

View File

@@ -28,15 +28,14 @@ export class HuiPersistentNotificationItem extends LitElement {
<div class="time"> <div class="time">
<span> <span>
<ha-tooltip <ha-relative-time
.content=${this._computeTooltip(this.hass, this.notification)} id="relative-time"
placement="bottom" .hass=${this.hass}
> .datetime=${this.notification.created_at}
<ha-relative-time capitalize
.hass=${this.hass} ></ha-relative-time>
.datetime=${this.notification.created_at} <ha-tooltip for="relative-time" placement="bottom">
capitalize ${this._computeTooltip(this.hass, this.notification)}
></ha-relative-time>
</ha-tooltip> </ha-tooltip>
</span> </span>
</div> </div>

View File

@@ -51,6 +51,7 @@ import {
loadAreaRegistryDetailDialog, loadAreaRegistryDetailDialog,
showAreaRegistryDetailDialog, showAreaRegistryDetailDialog,
} from "./show-dialog-area-registry-detail"; } from "./show-dialog-area-registry-detail";
import { slugify } from "../../../common/string/slugify";
declare interface NameAndEntity<EntityType extends HassEntity> { declare interface NameAndEntity<EntityType extends HassEntity> {
name: string; name: string;
@@ -549,11 +550,14 @@ class HaConfigAreaPage extends LitElement {
private _renderScene(name: string, entityState: SceneEntity) { private _renderScene(name: string, entityState: SceneEntity) {
return html`<ha-tooltip return html`<ha-tooltip
.distance=${-4} .for="scene-${slugify(entityState.entity_id)}"
.disabled=${!!entityState.attributes.id} .distance=${-4}
.content=${this.hass.localize("ui.panel.config.devices.cant_edit")} .disabled=${!!entityState.attributes.id}
> >
${this.hass.localize("ui.panel.config.devices.cant_edit")}
</ha-tooltip>
<a <a
.id="scene-${slugify(entityState.entity_id)}"
href=${ifDefined( href=${ifDefined(
entityState.attributes.id entityState.attributes.id
? `/config/scene/edit/${entityState.attributes.id}` ? `/config/scene/edit/${entityState.attributes.id}`
@@ -564,17 +568,12 @@ class HaConfigAreaPage extends LitElement {
<span>${name}</span> <span>${name}</span>
<ha-icon-next slot="meta"></ha-icon-next> <ha-icon-next slot="meta"></ha-icon-next>
</ha-list-item> </ha-list-item>
</a> </a> `;
</ha-tooltip>`;
} }
private _renderAutomation(name: string, entityState: AutomationEntity) { private _renderAutomation(name: string, entityState: AutomationEntity) {
return html`<ha-tooltip return html`<a
.disabled=${!!entityState.attributes.id} id="automation-${slugify(entityState.entity_id)}"
.distance=${-4}
.content=${this.hass.localize("ui.panel.config.devices.cant_edit")}
>
<a
href=${ifDefined( href=${ifDefined(
entityState.attributes.id entityState.attributes.id
? `/config/automation/edit/${encodeURIComponent(entityState.attributes.id)}` ? `/config/automation/edit/${encodeURIComponent(entityState.attributes.id)}`
@@ -586,7 +585,12 @@ class HaConfigAreaPage extends LitElement {
<ha-icon-next slot="meta"></ha-icon-next> <ha-icon-next slot="meta"></ha-icon-next>
</ha-list-item> </ha-list-item>
</a> </a>
</ha-tooltip>`; <ha-tooltip
for="automation-${slugify(entityState.entity_id)}"
.disabled=${!!entityState.attributes.id}
.distance=${-4}
>${this.hass.localize("ui.panel.config.devices.cant_edit")}
</ha-tooltip>`;
} }
private _renderScript(name: string, entityState: ScriptEntity) { private _renderScript(name: string, entityState: ScriptEntity) {

View File

@@ -258,14 +258,16 @@ export default class HaAutomationActionRow extends LitElement {
${type !== "condition" && ${type !== "condition" &&
(this.action as NonConditionAction).continue_on_error === true (this.action as NonConditionAction).continue_on_error === true
? html`<ha-tooltip ? html`<ha-svg-icon
slot="icons" id="svg-icon"
.content=${this.hass.localize( slot="icons"
"ui.panel.config.automation.editor.actions.continue_on_error" .path=${mdiAlertCircleCheck}
)} ></ha-svg-icon>
> <ha-tooltip for="svg-icon">
<ha-svg-icon .path=${mdiAlertCircleCheck}></ha-svg-icon> ${this.hass.localize(
</ha-tooltip>` "ui.panel.config.automation.editor.actions.continue_on_error"
)}
</ha-tooltip>`
: nothing} : nothing}
${!this.optionsInSidebar ${!this.optionsInSidebar
? html`<ha-md-button-menu ? html`<ha-md-button-menu

View File

@@ -89,6 +89,7 @@ import {
loadDeviceRegistryDetailDialog, loadDeviceRegistryDetailDialog,
showDeviceRegistryDetailDialog, showDeviceRegistryDetailDialog,
} from "./device-registry-detail/show-dialog-device-registry-detail"; } from "./device-registry-detail/show-dialog-device-registry-detail";
import { slugify } from "../../../common/string/slugify";
export interface EntityRegistryStateEntry extends EntityRegistryEntry { export interface EntityRegistryStateEntry extends EntityRegistryEntry {
stateName?: string | null; stateName?: string | null;
@@ -555,16 +556,21 @@ export class HaConfigDevicePage extends LitElement {
</a> </a>
` `
: html` : html`
<ha-list-item
.id="scene-${slugify(entityState.entity_id)}"
hasMeta
.scene=${entityState}
>
${computeStateName(entityState)}
<ha-icon-next slot="meta"></ha-icon-next>
</ha-list-item>
<ha-tooltip <ha-tooltip
.for="scene-${slugify(entityState.entity_id)}"
placement="left" placement="left"
.content=${this.hass.localize( >
${this.hass.localize(
"ui.panel.config.devices.cant_edit" "ui.panel.config.devices.cant_edit"
)} )}
>
<ha-list-item hasMeta .scene=${entityState}>
${computeStateName(entityState)}
<ha-icon-next slot="meta"></ha-icon-next>
</ha-list-item>
</ha-tooltip> </ha-tooltip>
`; `;
})} })}

View File

@@ -671,13 +671,14 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
tabindex="0" tabindex="0"
style="display:inline-block; position: relative;" style="display:inline-block; position: relative;"
> >
<ha-tooltip <ha-svg-icon
placement="left" .id="svg-icon-${device.id}"
.content=${this.hass.localize( .path=${mdiCancel}
></ha-svg-icon>
<ha-tooltip .for="svg-icon-${device.id}" placement="left">
${this.hass.localize(
"ui.panel.config.entities.picker.status.disabled" "ui.panel.config.entities.picker.status.disabled"
)} )}
>
<ha-svg-icon .path=${mdiCancel}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
</div> </div>
` `

View File

@@ -114,6 +114,7 @@ import { isHelperDomain } from "../helpers/const";
import "../integrations/ha-integration-overflow-menu"; import "../integrations/ha-integration-overflow-menu";
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { slugify } from "../../../common/string/slugify";
export interface StateEntity export interface StateEntity
extends Omit<EntityRegistryEntry, "id" | "unique_id"> { extends Omit<EntityRegistryEntry, "id" | "unique_id"> {
@@ -392,9 +393,27 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
tabindex="0" tabindex="0"
style="display:inline-block; position: relative;" style="display:inline-block; position: relative;"
> >
<ha-svg-icon
.id="status-icon-${slugify(entry.entity_id)}"
style=${styleMap({
color: entry.unavailable ? "var(--error-color)" : "",
})}
.path=${entry.restored
? mdiRestoreAlert
: entry.unavailable
? mdiAlertCircle
: entry.disabled_by
? mdiCancel
: entry.hidden_by
? mdiEyeOff
: mdiPencilOff}
></ha-svg-icon>
<ha-tooltip <ha-tooltip
.for="status-icon-${slugify(entry.entity_id)}"
placement="left" placement="left"
.content=${entry.restored >
${entry.restored
? this.hass.localize( ? this.hass.localize(
"ui.panel.config.entities.picker.status.not_provided" "ui.panel.config.entities.picker.status.not_provided"
) )
@@ -413,21 +432,6 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
: this.hass.localize( : this.hass.localize(
"ui.panel.config.entities.picker.status.unmanageable" "ui.panel.config.entities.picker.status.unmanageable"
)} )}
>
<ha-svg-icon
style=${styleMap({
color: entry.unavailable ? "var(--error-color)" : "",
})}
.path=${entry.restored
? mdiRestoreAlert
: entry.unavailable
? mdiAlertCircle
: entry.disabled_by
? mdiCancel
: entry.hidden_by
? mdiEyeOff
: mdiPencilOff}
></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
</div> </div>
` `

View File

@@ -236,17 +236,18 @@ export class DialogHelperDetail extends LitElement {
<span class="item-text"> ${label} </span> <span class="item-text"> ${label} </span>
${isLoaded ${isLoaded
? html`<ha-icon-next slot="meta"></ha-icon-next>` ? html`<ha-icon-next slot="meta"></ha-icon-next>`
: html`<ha-tooltip : html` <ha-svg-icon
hoist slot="meta"
slot="meta" .id="icon-${domain}"
.content=${this.hass.localize( path=${mdiAlertOutline}
"ui.dialogs.helper_settings.platform_not_loaded", @click=${stopPropagation}
{ platform: domain } ></ha-svg-icon>
)} <ha-tooltip .for="icon-${domain}">
@click=${stopPropagation} ${this.hass.localize(
> "ui.dialogs.helper_settings.platform_not_loaded",
<ha-svg-icon path=${mdiAlertOutline}></ha-svg-icon> { platform: domain }
</ha-tooltip>`} )}
</ha-tooltip>`}
</ha-list-item> </ha-list-item>
`; `;
})} })}

View File

@@ -110,6 +110,7 @@ import { renderConfigEntryError } from "../integrations/ha-config-integration-pa
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { isHelperDomain } from "./const"; import { isHelperDomain } from "./const";
import { showHelperDetailDialog } from "./show-dialog-helper-detail"; import { showHelperDetailDialog } from "./show-dialog-helper-detail";
import { slugify } from "../../../common/string/slugify";
interface HelperItem { interface HelperItem {
id: string; id: string;
@@ -361,13 +362,16 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
tabindex="0" tabindex="0"
style="display:inline-block; position: relative;" style="display:inline-block; position: relative;"
> >
<ha-svg-icon
.id="icon-edit-${slugify(helper.entity_id)}"
.path=${mdiPencilOff}
></ha-svg-icon>
<ha-tooltip <ha-tooltip
.for="icon-edit-${slugify(helper.entity_id)}"
placement="left" placement="left"
.content=${this.hass.localize( >${this.hass.localize(
"ui.panel.config.entities.picker.status.unmanageable" "ui.panel.config.entities.picker.status.unmanageable"
)} )}
>
<ha-svg-icon .path=${mdiPencilOff}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
</div> </div>
` `

View File

@@ -159,29 +159,32 @@ export class HaIntegrationCard extends LitElement {
? "overwrites" ? "overwrites"
: "custom"}" : "custom"}"
> >
<ha-svg-icon
id="icon-custom"
.path=${mdiPackageVariant}
></ha-svg-icon>
<ha-tooltip <ha-tooltip
hoist for="icon-custom"
.placement=${computeRTL(this.hass) ? "right" : "left"} .placement=${computeRTL(this.hass) ? "right" : "left"}
.content=${this.hass.localize( >
${this.hass.localize(
this.manifest.overwrites_built_in this.manifest.overwrites_built_in
? "ui.panel.config.integrations.config_entry.custom_overwrites_core" ? "ui.panel.config.integrations.config_entry.custom_overwrites_core"
: "ui.panel.config.integrations.config_entry.custom_integration" : "ui.panel.config.integrations.config_entry.custom_integration"
)} )}
>
<ha-svg-icon .path=${mdiPackageVariant}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
</span>` </span>`
: nothing} : nothing}
${this.manifest && this.manifest.iot_class?.startsWith("cloud_") ${this.manifest && this.manifest.iot_class?.startsWith("cloud_")
? html`<div class="icon cloud"> ? html`<div class="icon cloud">
<ha-svg-icon id="icon-cloud" .path=${mdiWeb}></ha-svg-icon>
<ha-tooltip <ha-tooltip
hoist for="icon-cloud"
.placement=${computeRTL(this.hass) ? "right" : "left"} .placement=${computeRTL(this.hass) ? "right" : "left"}
.content=${this.hass.localize( >
${this.hass.localize(
"ui.panel.config.integrations.config_entry.depends_on_cloud" "ui.panel.config.integrations.config_entry.depends_on_cloud"
)} )}
>
<ha-svg-icon .path=${mdiWeb}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
</div>` </div>`
: nothing} : nothing}
@@ -189,15 +192,18 @@ export class HaIntegrationCard extends LitElement {
!this.manifest?.config_flow && !this.manifest?.config_flow &&
!this.items.every((itm) => itm.source === "system") !this.items.every((itm) => itm.source === "system")
? html`<div class="icon yaml"> ? html`<div class="icon yaml">
<ha-svg-icon
id="icon-yaml"
.path=${mdiFileCodeOutline}
></ha-svg-icon>
<ha-tooltip <ha-tooltip
hoist for="icon-yaml"
.placement=${computeRTL(this.hass) ? "right" : "left"} .placement=${computeRTL(this.hass) ? "right" : "left"}
.content=${this.hass.localize( >
${this.hass.localize(
"ui.panel.config.integrations.config_entry.no_config_flow" "ui.panel.config.integrations.config_entry.no_config_flow"
)} )}
> </ha-tooltip>
<ha-svg-icon .path=${mdiFileCodeOutline}></ha-svg-icon
></ha-tooltip>
</div>` </div>`
: nothing} : nothing}
</div> </div>

View File

@@ -74,45 +74,45 @@ export class HaIntegrationListItem extends ListItemBase {
} }
return html`<span class="mdc-deprecated-list-item__meta material-icons"> return html`<span class="mdc-deprecated-list-item__meta material-icons">
${this.integration.cloud ${this.integration.cloud
? html`<ha-tooltip ? html` <ha-svg-icon id="icon-cloud" .path=${mdiWeb}></ha-svg-icon>
placement="left" <ha-tooltip for="icon-cloud" placement="left"
.content=${this.hass.localize( >${this.hass.localize(
"ui.panel.config.integrations.config_entry.depends_on_cloud" "ui.panel.config.integrations.config_entry.depends_on_cloud"
)} )}
><ha-svg-icon .path=${mdiWeb}></ha-svg-icon </ha-tooltip>`
></ha-tooltip>`
: nothing} : nothing}
${!this.integration.is_built_in ${!this.integration.is_built_in
? html`<span ? html`<span
class=${this.integration.overwrites_built_in class=${this.integration.overwrites_built_in
? "overwrites" ? "overwrites"
: "custom"} : "custom"}
><ha-tooltip >
placement="left" <ha-svg-icon
.content=${this.hass.localize( id="icon-custom"
.path=${mdiPackageVariant}
></ha-svg-icon>
<ha-tooltip for="icon-custom" placement="left"
>${this.hass.localize(
this.integration.overwrites_built_in this.integration.overwrites_built_in
? "ui.panel.config.integrations.config_entry.custom_overwrites_core" ? "ui.panel.config.integrations.config_entry.custom_overwrites_core"
: "ui.panel.config.integrations.config_entry.custom_integration" : "ui.panel.config.integrations.config_entry.custom_integration"
)} )}</ha-tooltip
><ha-svg-icon ></span
.path=${mdiPackageVariant} >`
></ha-svg-icon></ha-tooltip
></span>`
: nothing} : nothing}
${!this.integration.config_flow && ${!this.integration.config_flow &&
!this.integration.integrations && !this.integration.integrations &&
!this.integration.iot_standards !this.integration.iot_standards
? html`<ha-tooltip ? html` <ha-svg-icon
placement="left" id="icon-yaml"
.content=${this.hass.localize(
"ui.panel.config.integrations.config_entry.yaml_only"
)}
>
<ha-svg-icon
.path=${mdiFileCodeOutline} .path=${mdiFileCodeOutline}
class="open-in-new" class="open-in-new"
></ha-svg-icon> ></ha-svg-icon>
</ha-tooltip>` <ha-tooltip for="icon-yaml" placement="left">
${this.hass.localize(
"ui.panel.config.integrations.config_entry.yaml_only"
)}
</ha-tooltip>`
: html`<ha-icon-next></ha-icon-next>`} : html`<ha-icon-next></ha-icon-next>`}
</span>`; </span>`;
} }

View File

@@ -307,14 +307,18 @@ class DialogZHAReconfigureDevice extends LitElement {
` `
: html` : html`
<span class="stage"> <span class="stage">
<ha-svg-icon
.id="svg-icon-${clusterStatus
.cluster.name}"
.path=${mdiCloseCircle}
class="failed"
></ha-svg-icon>
<ha-tooltip <ha-tooltip
.for="svg-icon-${clusterStatus
.cluster.name}"
placement="top" placement="top"
.content=${attribute.status}
> >
<ha-svg-icon ${attribute.status}
.path=${mdiCloseCircle}
class="failed"
></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
</span> </span>
`} `}

View File

@@ -156,16 +156,18 @@ export class HaConfigLovelaceDashboards extends LitElement {
${dashboard.title} ${dashboard.title}
${dashboard.default ${dashboard.default
? html` ? html`
<ha-svg-icon
.id="default-icon-${dashboard.title}"
style="padding-left: 10px; padding-inline-start: 10px; padding-inline-end: initial; direction: var(--direction);"
.path=${mdiCheckCircleOutline}
></ha-svg-icon>
<ha-tooltip <ha-tooltip
.content=${this.hass.localize( .for="default-icon-${dashboard.title}"
`ui.panel.config.lovelace.dashboards.default_dashboard`
)}
placement="right" placement="right"
> >
<ha-svg-icon ${this.hass.localize(
style="padding-left: 10px; padding-inline-start: 10px; padding-inline-end: initial; direction: var(--direction);" `ui.panel.config.lovelace.dashboards.default_dashboard`
.path=${mdiCheckCircleOutline} )}
></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
` `
: nothing} : nothing}

View File

@@ -106,6 +106,7 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor
import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail"; import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
import { configSections } from "../ha-panel-config"; import { configSections } from "../ha-panel-config";
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { slugify } from "../../../common/string/slugify";
type SceneItem = SceneEntity & { type SceneItem = SceneEntity & {
name: string; name: string;
@@ -318,16 +319,18 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
template: (scene) => template: (scene) =>
!scene.attributes.id !scene.attributes.id
? html` ? html`
<ha-svg-icon
.id="svg-icon-${slugify(scene.entity_id)}"
.path=${mdiPencilOff}
style="color: var(--secondary-text-color)"
></ha-svg-icon>
<ha-tooltip <ha-tooltip
.for="svg-icon-${slugify(scene.entity_id)}"
placement="left" placement="left"
.content=${this.hass.localize( >
${this.hass.localize(
"ui.panel.config.scene.picker.only_editable" "ui.panel.config.scene.picker.only_editable"
)} )}
>
<ha-svg-icon
.path=${mdiPencilOff}
style="color: var(--secondary-text-color)"
></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
` `
: nothing, : nothing,

View File

@@ -25,48 +25,47 @@ export class VoiceAssistantExposeAssistantIcon extends LitElement {
if (!this.assistant || !voiceAssistants[this.assistant]) return nothing; if (!this.assistant || !voiceAssistants[this.assistant]) return nothing;
return html` return html`
<div class="container" id="container">
<img
class="logo"
style=${styleMap({
filter: this.manual ? "grayscale(100%)" : undefined,
})}
alt=${voiceAssistants[this.assistant].name}
src=${brandsUrl({
domain: voiceAssistants[this.assistant].domain,
type: "icon",
darkOptimized: this.hass.themes?.darkMode,
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
slot="prefix"
/>
${this.unsupported
? html`
<ha-svg-icon
.path=${mdiAlertCircle}
class="unsupported"
></ha-svg-icon>
`
: nothing}
</div>
<ha-tooltip <ha-tooltip
.disabled=${!this.unsupported && !this.manual} for="container"
placement="left" placement="left"
.disabled=${!this.unsupported && !this.manual}
> >
<div class="container"> ${this.unsupported
<img ? this.hass.localize(
class="logo" "ui.panel.config.voice_assistants.expose.not_supported"
style=${styleMap({ )
filter: this.manual ? "grayscale(100%)" : undefined, : ""}
})} ${this.unsupported && this.manual ? html`<br />` : nothing}
alt=${voiceAssistants[this.assistant].name} ${this.manual
src=${brandsUrl({ ? this.hass.localize(
domain: voiceAssistants[this.assistant].domain, "ui.panel.config.voice_assistants.expose.manually_configured"
type: "icon", )
darkOptimized: this.hass.themes?.darkMode, : nothing}
})}
crossorigin="anonymous"
referrerpolicy="no-referrer"
slot="prefix"
/>
${this.unsupported
? html`
<ha-svg-icon
.path=${mdiAlertCircle}
class="unsupported"
></ha-svg-icon>
`
: nothing}
</div>
<span slot="content">
${this.unsupported
? this.hass.localize(
"ui.panel.config.voice_assistants.expose.not_supported"
)
: ""}
${this.unsupported && this.manual ? html`<br />` : nothing}
${this.manual
? this.hass.localize(
"ui.panel.config.voice_assistants.expose.manually_configured"
)
: nothing}
</span>
</ha-tooltip> </ha-tooltip>
`; `;
} }

View File

@@ -607,34 +607,32 @@ export class VoiceAssistantsExpose extends LitElement {
> >
` `
: html` : html`
<ha-tooltip <ha-icon-button
.content=${this.hass.localize( id="expose-button"
@click=${this._exposeSelected}
.path=${mdiPlusBoxMultiple}
.label=${this.hass.localize(
"ui.panel.config.voice_assistants.expose.expose"
)}
></ha-icon-button>
<ha-tooltip for="expose-button" placement="left">
${this.hass.localize(
"ui.panel.config.voice_assistants.expose.expose" "ui.panel.config.voice_assistants.expose.expose"
)} )}
placement="left"
>
<ha-icon-button
@click=${this._exposeSelected}
.path=${mdiPlusBoxMultiple}
.label=${this.hass.localize(
"ui.panel.config.voice_assistants.expose.expose"
)}
></ha-icon-button>
</ha-tooltip> </ha-tooltip>
<ha-tooltip <ha-tooltip for="unexpose-button" placement="left">
content=${this.hass.localize( ${this.hass.localize(
"ui.panel.config.voice_assistants.expose.unexpose" "ui.panel.config.voice_assistants.expose.unexpose"
)} )}
placement="left"
>
<ha-icon-button
@click=${this._unexposeSelected}
.path=${mdiCloseBoxMultiple}
.label=${this.hass.localize(
"ui.panel.config.voice_assistants.expose.unexpose"
)}
></ha-icon-button>
</ha-tooltip> </ha-tooltip>
<ha-icon-button
id="unexpose-button"
@click=${this._unexposeSelected}
.path=${mdiCloseBoxMultiple}
.label=${this.hass.localize(
"ui.panel.config.voice_assistants.expose.unexpose"
)}
></ha-icon-button>
`} `}
</div> </div>
` `

View File

@@ -46,6 +46,7 @@ import "../ha-config-section";
import { configSections } from "../ha-panel-config"; import { configSections } from "../ha-panel-config";
import { showHomeZoneDetailDialog } from "./show-dialog-home-zone-detail"; import { showHomeZoneDetailDialog } from "./show-dialog-home-zone-detail";
import { showZoneDetailDialog } from "./show-dialog-zone-detail"; import { showZoneDetailDialog } from "./show-dialog-zone-detail";
import { slugify } from "../../../common/string/slugify";
@customElement("ha-config-zone") @customElement("ha-config-zone")
export class HaConfigZone extends SubscribeMixin(LitElement) { export class HaConfigZone extends SubscribeMixin(LitElement) {
@@ -200,17 +201,8 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
stateObject.entity_id === "zone.home" && stateObject.entity_id === "zone.home" &&
!this._canEditCore !this._canEditCore
? nothing ? nothing
: html`<ha-tooltip : html`<ha-icon-button
slot="meta" .id="zone-${slugify(stateObject.entity_id)}"
placement="left"
.content=${hass.localize(
"ui.panel.config.zone.configured_in_yaml"
)}
.disabled=${stateObject.entity_id === "zone.home"}
hoist
>
<ha-icon-button
.id=${!this.narrow ? stateObject.entity_id : ""}
.entityId=${stateObject.entity_id} .entityId=${stateObject.entity_id}
.noEdit=${stateObject.entity_id !== "zone.home" || .noEdit=${stateObject.entity_id !== "zone.home" ||
!this._canEditCore} !this._canEditCore}
@@ -222,8 +214,18 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
name: hass.config.location_name, name: hass.config.location_name,
})} })}
@click=${this._editHomeZone} @click=${this._editHomeZone}
slot="meta"
></ha-icon-button> ></ha-icon-button>
</ha-tooltip>`} <ha-tooltip
.for="zone-${slugify(stateObject.entity_id)}"
placement="left"
.disabled=${stateObject.entity_id === "zone.home"}
hoist
>
${hass.localize(
"ui.panel.config.zone.configured_in_yaml"
)}
</ha-tooltip>`}
</ha-list-item> </ha-list-item>
` `
)} )}

View File

@@ -133,14 +133,12 @@ class HuiEnergyCarbonGaugeCard
"--gauge-color": this._computeSeverity(value), "--gauge-color": this._computeSeverity(value),
})} })}
></ha-gauge> ></ha-gauge>
<ha-tooltip
.content=${this.hass.localize( <ha-svg-icon id="info" .path=${mdiInformation}></ha-svg-icon>
<ha-tooltip for="info" placement="left">
${this.hass.localize(
"ui.panel.lovelace.cards.energy.carbon_consumed_gauge.card_indicates_energy_used" "ui.panel.lovelace.cards.energy.carbon_consumed_gauge.card_indicates_energy_used"
)} )}
placement="left"
hoist
>
<ha-svg-icon .path=${mdiInformation}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
<div class="name"> <div class="name">
${this.hass.localize( ${this.hass.localize(

View File

@@ -114,17 +114,15 @@ class HuiEnergyGridGaugeCard
label="kWh" label="kWh"
needle needle
></ha-gauge> ></ha-gauge>
<ha-tooltip placement="left" hoist> <ha-svg-icon id="info" .path=${mdiInformation}></ha-svg-icon>
<span slot="content"> <ha-tooltip for="info" placement="left">
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.cards.energy.grid_neutrality_gauge.energy_dependency" "ui.panel.lovelace.cards.energy.grid_neutrality_gauge.energy_dependency"
)} )}
<br /><br /> <br /><br />
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.cards.energy.grid_neutrality_gauge.color_explain" "ui.panel.lovelace.cards.energy.grid_neutrality_gauge.color_explain"
)} )}
</span>
<ha-svg-icon .path=${mdiInformation}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
<div class="name"> <div class="name">
${returnedToGrid! >= consumedFromGrid! ${returnedToGrid! >= consumedFromGrid!

View File

@@ -110,14 +110,11 @@ class HuiEnergySelfSufficiencyGaugeCard
"--gauge-color": this._computeSeverity(value), "--gauge-color": this._computeSeverity(value),
})} })}
></ha-gauge> ></ha-gauge>
<ha-tooltip <ha-svg-icon id="info" .path=${mdiInformation}></ha-svg-icon>
placement="left" <ha-tooltip for="info" placement="left">
.content=${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.cards.energy.self_sufficiency_gauge.card_indicates_self_sufficiency_quota" "ui.panel.lovelace.cards.energy.self_sufficiency_gauge.card_indicates_self_sufficiency_quota"
)} )}
hoist
>
<ha-svg-icon .path=${mdiInformation}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
<div class="name"> <div class="name">
${this.hass.localize( ${this.hass.localize(

View File

@@ -102,17 +102,15 @@ class HuiEnergySolarGaugeCard
"--gauge-color": this._computeSeverity(value), "--gauge-color": this._computeSeverity(value),
})} })}
></ha-gauge> ></ha-gauge>
<ha-tooltip placement="left" hoist> <ha-svg-icon id="info" .path=${mdiInformation}></ha-svg-icon>
<span slot="content"> <ha-tooltip for="info" placement="left">
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.cards.energy.solar_consumed_gauge.card_indicates_solar_energy_used" "ui.panel.lovelace.cards.energy.solar_consumed_gauge.card_indicates_solar_energy_used"
)} )}
<br /><br /> <br /><br />
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.cards.energy.solar_consumed_gauge.card_indicates_solar_energy_used_charge_home_bat" "ui.panel.lovelace.cards.energy.solar_consumed_gauge.card_indicates_solar_energy_used_charge_home_bat"
)} )}
</span>
<ha-svg-icon .path=${mdiInformation}></ha-svg-icon>
</ha-tooltip> </ha-tooltip>
<div class="name"> <div class="name">
${this.hass.localize( ${this.hass.localize(
@@ -176,10 +174,6 @@ class HuiEnergySolarGaugeCard
top: 4px; top: 4px;
color: var(--secondary-text-color); color: var(--secondary-text-color);
} }
ha-tooltip::part(base__popup) {
margin-top: 4px;
}
`; `;
} }

View File

@@ -47,6 +47,7 @@ import "../../components/ha-menu-button";
import "../../components/ha-svg-icon"; import "../../components/ha-svg-icon";
import "../../components/ha-tab-group"; import "../../components/ha-tab-group";
import "../../components/ha-tab-group-tab"; import "../../components/ha-tab-group-tab";
import "../../components/ha-tooltip";
import { createAreaRegistryEntry } from "../../data/area_registry"; import { createAreaRegistryEntry } from "../../data/area_registry";
import type { LovelacePanelConfig } from "../../data/lovelace"; import type { LovelacePanelConfig } from "../../data/lovelace";
import type { LovelaceConfig } from "../../data/lovelace/config/types"; import type { LovelaceConfig } from "../../data/lovelace/config/types";
@@ -307,7 +308,7 @@ class HUIRoot extends LitElement {
(i) => i.visible && (!i.overflow || overflowCanPromote) (i) => i.visible && (!i.overflow || overflowCanPromote)
); );
buttonItems.forEach((item) => { buttonItems.forEach((item, index) => {
const label = [this.hass!.localize(item.key), item.suffix].join(" "); const label = [this.hass!.localize(item.key), item.suffix].join(" ");
const button = item.subItems const button = item.subItems
? html` ? html`
@@ -341,11 +342,14 @@ class HUIRoot extends LitElement {
</ha-button-menu> </ha-button-menu>
` `
: html` : html`
<ha-tooltip slot="actionItems" placement="bottom" .content=${label}> <ha-icon-button
<ha-icon-button slot="actionItems"
.path=${item.icon} .id="button-${index}"
@click=${item.buttonAction} .path=${item.icon}
></ha-icon-button> @click=${item.buttonAction}
></ha-icon-button>
<ha-tooltip placement="bottom" .for="button-${index}">
${label}
</ha-tooltip> </ha-tooltip>
`; `;
result.push(button); result.push(button);

View File

@@ -1644,7 +1644,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@floating-ui/dom@npm:^1.6.12, @floating-ui/dom@npm:^1.6.13": "@floating-ui/dom@npm:^1.6.13":
version: 1.7.3 version: 1.7.3
resolution: "@floating-ui/dom@npm:1.7.3" resolution: "@floating-ui/dom@npm:1.7.3"
dependencies: dependencies:
@@ -1905,9 +1905,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@home-assistant/webawesome@npm:3.0.0-beta.4.ha.2": "@home-assistant/webawesome@npm:3.0.0-beta.4.ha.3":
version: 3.0.0-beta.4.ha.2 version: 3.0.0-beta.4.ha.3
resolution: "@home-assistant/webawesome@npm:3.0.0-beta.4.ha.2" resolution: "@home-assistant/webawesome@npm:3.0.0-beta.4.ha.3"
dependencies: dependencies:
"@ctrl/tinycolor": "npm:^4.1.0" "@ctrl/tinycolor": "npm:^4.1.0"
"@floating-ui/dom": "npm:^1.6.13" "@floating-ui/dom": "npm:^1.6.13"
@@ -1919,7 +1919,7 @@ __metadata:
nanoid: "npm:^5.1.5" nanoid: "npm:^5.1.5"
qr-creator: "npm:^1.0.0" qr-creator: "npm:^1.0.0"
style-observer: "npm:^0.0.7" style-observer: "npm:^0.0.7"
checksum: 10/0ac66d43050571e2b86bb7b0181d428aa2a064e25745075b207a8fe96d873398eaead663172130dfe8d9ac0be575028f8f9f6b9f8a9cd12f81c8c82e9f60a0e9 checksum: 10/b9241821ed471ccbad86b0ea4697a2d41395f05fdc26f46e5edbc7f6b5eeab5d248251ef702326312ded00d5bf850ce0dcdcf7cd5e2e542b9d9cb9a84f3726da
languageName: node languageName: node
linkType: hard linkType: hard
@@ -2326,7 +2326,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@lit/react@npm:^1.0.6, @lit/react@npm:^1.0.8": "@lit/react@npm:^1.0.8":
version: 1.0.8 version: 1.0.8
resolution: "@lit/react@npm:1.0.8" resolution: "@lit/react@npm:1.0.8"
peerDependencies: peerDependencies:
@@ -4170,22 +4170,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@shoelace-style/shoelace@npm:2.20.1":
version: 2.20.1
resolution: "@shoelace-style/shoelace@npm:2.20.1"
dependencies:
"@ctrl/tinycolor": "npm:^4.1.0"
"@floating-ui/dom": "npm:^1.6.12"
"@lit/react": "npm:^1.0.6"
"@shoelace-style/animations": "npm:^1.2.0"
"@shoelace-style/localize": "npm:^3.2.1"
composed-offset-position: "npm:^0.0.6"
lit: "npm:^3.2.1"
qr-creator: "npm:^1.0.0"
checksum: 10/c3aabeac03d5fd5bc43799783562ab09c92bae98efbc43a931c7dcec608acc393771b6ed0da3f29e08570bb9d9a9e3bff7637cbf6f79ba7aa439f6641da4eb7c
languageName: node
linkType: hard
"@sindresorhus/merge-streams@npm:^2.1.0": "@sindresorhus/merge-streams@npm:^2.1.0":
version: 2.3.0 version: 2.3.0
resolution: "@sindresorhus/merge-streams@npm:2.3.0" resolution: "@sindresorhus/merge-streams@npm:2.3.0"
@@ -9334,7 +9318,7 @@ __metadata:
"@fullcalendar/list": "npm:6.1.19" "@fullcalendar/list": "npm:6.1.19"
"@fullcalendar/luxon3": "npm:6.1.19" "@fullcalendar/luxon3": "npm:6.1.19"
"@fullcalendar/timegrid": "npm:6.1.19" "@fullcalendar/timegrid": "npm:6.1.19"
"@home-assistant/webawesome": "npm:3.0.0-beta.4.ha.2" "@home-assistant/webawesome": "npm:3.0.0-beta.4.ha.3"
"@lezer/highlight": "npm:1.2.1" "@lezer/highlight": "npm:1.2.1"
"@lit-labs/motion": "npm:1.0.9" "@lit-labs/motion": "npm:1.0.9"
"@lit-labs/observers": "npm:2.0.6" "@lit-labs/observers": "npm:2.0.6"
@@ -9374,7 +9358,6 @@ __metadata:
"@rsdoctor/rspack-plugin": "npm:1.2.3" "@rsdoctor/rspack-plugin": "npm:1.2.3"
"@rspack/core": "npm:1.5.2" "@rspack/core": "npm:1.5.2"
"@rspack/dev-server": "npm:1.1.4" "@rspack/dev-server": "npm:1.1.4"
"@shoelace-style/shoelace": "npm:2.20.1"
"@swc/helpers": "npm:0.5.17" "@swc/helpers": "npm:0.5.17"
"@thomasloven/round-slider": "npm:0.6.0" "@thomasloven/round-slider": "npm:0.6.0"
"@tsparticles/engine": "npm:3.9.1" "@tsparticles/engine": "npm:3.9.1"