Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add (i) tooltip button for More Info functionality on mobile devices & tooltip z-index fix #19144

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/components/chart/ha-chart-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export class HaChartBase extends LitElement {
${this._tooltip.footer.map((item) => html`${item}<br />`)}
</div>`
: ""}
<slot name="tooltip-footer"></slot>
</div>`
: ""}
</div>
Expand Down Expand Up @@ -449,9 +450,12 @@ export class HaChartBase extends LitElement {
color: white;
border-radius: 4px;
pointer-events: none;
z-index: 1000;
z-index: 1;
width: 200px;
box-sizing: border-box;
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
}
:host([rtl]) .chartTooltip {
direction: rtl;
Expand Down
94 changes: 72 additions & 22 deletions src/components/chart/state-history-chart-line.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import type { ChartData, ChartDataset, ChartOptions } from "chart.js";
import { html, LitElement, PropertyValues } from "lit";
import type {
ChartData,
ChartDataset,
ChartOptions,
ChartEvent,
ActiveElement,
Chart,
} from "chart.js";
import { mdiInformationOutline } from "@mdi/js";
import { html, css, CSSResultGroup, LitElement, PropertyValues } from "lit";
import { property, query, state } from "lit/decorators";
import { getGraphColorByIndex } from "../../common/color/colors";
import { fireEvent } from "../../common/dom/fire_event";
Expand All @@ -16,6 +24,7 @@ import {
HaChartBase,
MIN_TIME_BETWEEN_UPDATES,
} from "./ha-chart-base";
import "../ha-svg-icon";

const safeParseFloat = (value) => {
const parsed = parseFloat(value);
Expand Down Expand Up @@ -57,6 +66,10 @@ export class StateHistoryChartLine extends LitElement {

@state() private _yWidth = 0;

@state() private _showMoreInfoTooltipButton = false;

@state() private _moreInfoEntityId = "";

private _chartTime: Date = new Date();

@query("ha-chart-base") private _chart?: HaChartBase;
Expand All @@ -73,7 +86,16 @@ export class StateHistoryChartLine extends LitElement {
.options=${this._chartOptions}
.paddingYAxis=${this.paddingYAxis - this._yWidth}
chart-type="line"
></ha-chart-base>
>
${this._showMoreInfoTooltipButton
? html`<ha-svg-icon
class="more-info-button"
slot="tooltip-footer"
.path=${mdiInformationOutline}
@click=${this._moreInfoClick}
></ha-svg-icon>`
: ""}
</ha-chart-base>
`;
}

Expand Down Expand Up @@ -206,28 +228,17 @@ export class StateHistoryChartLine extends LitElement {
},
// @ts-expect-error
locale: numberFormatToLocale(this.hass.locale),
onClick: (e: any) => {
if (!this.clickForMoreInfo) {
return;
}
onClick: (e, elements, chart) => {
this._handleClickOrHover(e, elements, chart);

const chart = e.chart;

const points = chart.getElementsAtEventForMode(
e,
"nearest",
{ intersect: true },
true
);

if (points.length) {
const firstPoint = points[0];
fireEvent(this, "hass-more-info", {
entityId: this._entityIds[firstPoint.datasetIndex],
});
chart.canvas.dispatchEvent(new Event("mouseout")); // to hide tooltip
// if the More Info tooltip button is not shown, the pointer used to make
// this event was a mouse so open the more info dialog now
if (this.clickForMoreInfo && !this._showMoreInfoTooltipButton) {
this._moreInfoClick();
}
},
onHover: (e, elements, chart) =>
this._handleClickOrHover(e, elements, chart),
};
}
if (
Expand Down Expand Up @@ -573,6 +584,45 @@ export class StateHistoryChartLine extends LitElement {
this._entityIds = entityIds;
this._datasetToDataIndex = datasetToDataIndex;
}

private _handleClickOrHover(
e: ChartEvent,
_elements: ActiveElement[],
chart: Chart
) {
if (!this.clickForMoreInfo) {
return;
}

const points = chart.getElementsAtEventForMode(
e as any,
"nearest",
{ intersect: true },
true
);

if (points.length) {
const firstPoint = points[0];
this._moreInfoEntityId = this._entityIds[firstPoint.datasetIndex];

// display More Info toottip button for non-mouse events
this._showMoreInfoTooltipButton ||= !(e.native instanceof MouseEvent);
}
}

private _moreInfoClick() {
fireEvent(this, "hass-more-info", {
entityId: this._moreInfoEntityId,
});
}

static get styles(): CSSResultGroup {
return css`
.more-info-button {
pointer-events: auto;
}
`;
}
}
customElements.define("state-history-chart-line", StateHistoryChartLine);

Expand Down
80 changes: 63 additions & 17 deletions src/components/chart/state-history-chart-timeline.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import type { ChartData, ChartDataset, ChartOptions } from "chart.js";
import type {
ChartData,
ChartDataset,
ChartOptions,
ChartEvent,
ActiveElement,
Chart,
} from "chart.js";
import { mdiInformationOutline } from "@mdi/js";
import { getRelativePosition } from "chart.js/helpers";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import { customElement, property, query, state } from "lit/decorators";
Expand All @@ -16,6 +24,7 @@ import {
} from "./ha-chart-base";
import type { TimeLineData } from "./timeline-chart/const";
import { computeTimelineColor } from "./timeline-chart/timeline-color";
import "../ha-svg-icon";

@customElement("state-history-chart-timeline")
export class StateHistoryChartTimeline extends LitElement {
Expand Down Expand Up @@ -51,6 +60,10 @@ export class StateHistoryChartTimeline extends LitElement {

@state() private _yWidth = 0;

@state() private _showMoreInfoTooltipButton = false;

@state() private _moreInfoEntityId = "";

private _chartTime: Date = new Date();

@query("ha-chart-base") private _chart?: HaChartBase;
Expand All @@ -68,7 +81,16 @@ export class StateHistoryChartTimeline extends LitElement {
.height=${this.data.length * 30 + 30}
.paddingYAxis=${this.paddingYAxis - this._yWidth}
chart-type="timeline"
></ha-chart-base>
>
${this._showMoreInfoTooltipButton
? html`<ha-svg-icon
class="more-info-button"
slot="tooltip-footer"
.path=${mdiInformationOutline}
@click=${this._moreInfoClick}
></ha-svg-icon>`
: ""}
</ha-chart-base>
`;
}

Expand Down Expand Up @@ -223,23 +245,17 @@ export class StateHistoryChartTimeline extends LitElement {
},
// @ts-expect-error
locale: numberFormatToLocale(this.hass.locale),
onClick: (e: any) => {
if (!this.clickForMoreInfo) {
return;
}

const chart = e.chart;
const canvasPosition = getRelativePosition(e, chart);
onClick: (e, elements, chart) => {
this._handleClickOrHover(e, elements, chart);

const index = Math.abs(
chart.scales.y.getValueForPixel(canvasPosition.y)
);
fireEvent(this, "hass-more-info", {
// @ts-ignore
entityId: this._chartData?.datasets[index]?.label,
});
chart.canvas.dispatchEvent(new Event("mouseout")); // to hide tooltip
// if the More Info tooltip button is not shown, the pointer used to make
// this event was a mouse so open the more info dialog now
if (this.clickForMoreInfo && !this._showMoreInfoTooltipButton) {
this._moreInfoClick();
}
},
onHover: (e, elements, chart) =>
this._handleClickOrHover(e, elements, chart),
};
}

Expand Down Expand Up @@ -327,11 +343,41 @@ export class StateHistoryChartTimeline extends LitElement {
};
}

private _handleClickOrHover(
e: ChartEvent,
_elements: ActiveElement[],
chart: Chart
) {
if (!this.clickForMoreInfo) {
return;
}

const canvasPosition = getRelativePosition(e, chart as any);

const index = chart.scales.y.getValueForPixel(canvasPosition.y);

if (index !== undefined && index >= 0) {
this._moreInfoEntityId = this._chartData?.datasets[index]?.label ?? "";

// display More Info toottip button for non-mouse events
this._showMoreInfoTooltipButton ||= !(e.native instanceof MouseEvent);
}
}

private _moreInfoClick() {
fireEvent(this, "hass-more-info", {
entityId: this._moreInfoEntityId,
});
}

static get styles(): CSSResultGroup {
return css`
ha-chart-base {
--chart-max-height: none;
}
.more-info-button {
pointer-events: auto;
}
`;
}
}
Expand Down
Loading