Skip to content

Commit 2cfa873

Browse files
authored
Feature: add tap action (#32)
* added simple minimalistic tab action
1 parent e747ceb commit 2cfa873

2 files changed

Lines changed: 54 additions & 8 deletions

File tree

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,28 @@ Here are the available parameters for this Lovelace card.
290290
| `cheap_times` | boolean | `false` | The card highlights the cheapest times of the day in graph and the phases are displayed in text form. <ul><li>Prices are analyzed <strong>per day</strong>, so each day is evaluated on its own.</li><li>For each day, prices are normalized using a relative scale: <code>relative price = (price - daily minimum) / (daily maximum - daily minimum)</code>.</li><li>The <strong>lowest ~25%</strong> of all intervals for that day are considered <em>cheap</em>.</li><li>Consecutive cheap intervals are grouped into longer time phases.</li><li>Only <strong>future</strong> phases are shown, and only if they last <strong>at least 1 hour</strong>.</li></ul> |
291291
| `cheap_time_sources` | array of strings | `undefined` | Optional and only available in yaml mode. If `cheap_times: true` is set, you can provide a list of sensors/entity IDs to define the cheap time periods manually instead of letting the card calculate them automatically. This is useful if you already use helpers from the [ha_epex_spot_sensor](https://github.com/mampfes/ha_epex_spot_sensor) add-on – you can pass those sensor IDs here to display their cheap periods directly.|
292292

293+
---
294+
### Actions
295+
| Name | Type | Default | Description |
296+
|------------|---------|---------|-------------|
297+
| `tap_action` | object | `undefined` | Optional action when tapping the card. See [Home Assistant Actions](https://www.home-assistant.io/dashboards/actions/). Supported actions: `more-info`, `toggle`, `call-service`, `navigate`, `url`, `assist`. Requires `tap_target` for entity-based actions. |
298+
| `tap_target` | string | `undefined` | The entity ID that is the target of the `tap_action`. Required for entity-based actions (`toggle`, `more-info`, `call-service`). Not needed for navigation/url actions. |
299+
300+
**Examples:**
301+
302+
Toggle an input boolean:
303+
304+
```yaml
305+
tap_action:
306+
action: toggle
307+
tap_target: input_boolean.my_helper
308+
```
309+
Open more-info dialog:
310+
```yaml
311+
tap_action:
312+
action: more-info
313+
tap_target: sensor.tibber_prices
314+
```
293315
---
294316

295317
### 📘 Configuration

price-timeline-card.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,7 @@ class PriceTimelineCard extends LitElement {
11151115
const activeClass = this._dayOffset === 0 ? "active-today" : "active-tomorrow";
11161116

11171117
return html`
1118-
<div class="day-toggle">
1118+
<div class="day-toggle no-tap">
11191119
<div class="toggle-button ${activeClass}" @click=${this._toggleDayView}>
11201120
<div class="toggle-indicator"></div>
11211121
<span class="today">${localize("editor_start_today", lang)}</span>
@@ -1130,7 +1130,7 @@ class PriceTimelineCard extends LitElement {
11301130
//---------------------
11311131
_renderSlider(data, currentIndex) {
11321132
return html`
1133-
<div class="slider-container">
1133+
<div class="slider-container no-tap">
11341134
<input type="range" min="0" max="${data.length - 1}" .value="${currentIndex}" @input="${this._onSliderChange}" />
11351135
</div>
11361136
`
@@ -1365,17 +1365,41 @@ class PriceTimelineCard extends LitElement {
13651365
default:
13661366
cardContent = this._renderTimeline(data, currentIndex, avg, lang);
13671367
}
1368+
13681369
return html`
1369-
<ha-card>
1370+
<ha-card>
13701371
<div>
1371-
${cardContent}
1372-
${this.config.cheap_times === true ? this._renderCheapTimes(dataIntervalls) : ""}
1373-
${this.config.day_switch && this.config.view !== "graph" ? this._renderToggler(lang) : ""}
1374-
${this.config.slider ? this._renderSlider(data, currentIndex) : ""}
1372+
<div @pointerup=${(ev) => this._onTap(ev)}>${cardContent}</div>
1373+
${this.config.cheap_times === true ? this._renderCheapTimes(dataIntervalls) : ""}
1374+
${this.config.day_switch && this.config.view !== "graph" ? this._renderToggler(lang) : ""}
1375+
${this.config.slider ? this._renderSlider(data, currentIndex) : ""}
13751376
</div>
1376-
</ha-card>
1377+
</ha-card>
13771378
`;
13781379
}
1380+
1381+
_onTap(ev) {
1382+
const ignoreTags = ["BUTTON", "A", "INPUT", "SELECT", "TEXTAREA", "HA-SLIDER"];
1383+
if (ignoreTags.includes(ev.target.tagName)) return;
1384+
if (ev.target.closest(".no-tap")) return;
1385+
this._handleAction("tap");
1386+
}
1387+
1388+
_handleAction(actionType) {
1389+
if (!this.config.tap_action || !this.config.tap_target) return;
1390+
const event = new CustomEvent("hass-action", {
1391+
bubbles: true,
1392+
composed: true,
1393+
detail: {
1394+
config: {
1395+
entity: this.config.tap_target,
1396+
tap_action: this.config.tap_action,
1397+
},
1398+
action: actionType,
1399+
},
1400+
});
1401+
this.dispatchEvent(event);
1402+
}
13791403

13801404
static getConfigElement() {
13811405
return document.createElement("price-timeline-card-editor");

0 commit comments

Comments
 (0)