From f9dea24f9dbd9bcdeb97add730d47101a223b089 Mon Sep 17 00:00:00 2001 From: Ingolf Becker Date: Sun, 12 Jan 2025 16:47:51 +0000 Subject: [PATCH] Improve weather forecast card layout --- .../cards/hui-weather-forecast-card.ts | 64 +++++++++++-------- src/panels/lovelace/cards/types.ts | 1 + .../hui-weather-forecast-card-editor.ts | 20 +++++- src/translations/en.json | 1 + 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index ca8fc571af5e..628825ef8cf8 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -134,12 +134,15 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { } public getCardSize(): number { - let cardSize = 0; + let cardSize = 1; if (this._config?.show_current !== false) { - cardSize += 2; + cardSize += 1; } if (this._config?.show_forecast !== false) { - cardSize += 3; + cardSize += 1; + } + if (this._config?.forecast_type === "daily") { + cardSize += 1; } return cardSize; } @@ -218,12 +221,19 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { this._forecastEvent, this._config?.forecast_type ); + + let itemsToShow = this._config?.forecast_slots ?? 5; + if (this._sizeController.value === "very-very-narrow") { + itemsToShow = Math.min(3, itemsToShow); + } else if (this._sizeController.value === "very-narrow") { + itemsToShow = Math.min(5, itemsToShow); + } else if (this._sizeController.value === "narrow") { + itemsToShow = Math.min(7, itemsToShow); + } + const forecast = this._config?.show_forecast !== false && forecastData?.forecast?.length - ? forecastData.forecast.slice( - 0, - this._sizeController.value === "very-very-narrow" ? 3 : 5 - ) + ? forecastData.forecast.slice(0, itemsToShow) : undefined; const weather = !forecast || this._config?.show_current !== false; @@ -419,30 +429,24 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { } public getGridOptions(): LovelaceGridOptions { - if ( - this._config?.show_current !== false && - this._config?.show_forecast !== false - ) { - return { - columns: 12, - rows: 4, - min_columns: 6, - min_rows: 4, - }; + let rows = 1; + let min_rows = 1; + if (this._config?.show_current !== false) { + rows += 1; + min_rows += 1; } if (this._config?.show_forecast !== false) { - return { - columns: 12, - rows: 3, - min_columns: 6, - min_rows: 3, - }; + rows += 1; + min_rows += 1; + } + if (this._config?.forecast_type === "daily") { + rows += 1; } return { columns: 12, - rows: 2, + rows: rows, min_columns: 6, - min_rows: 2, + min_rows: min_rows, }; } @@ -462,7 +466,6 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { display: flex; flex-direction: column; justify-content: center; - padding: 16px; box-sizing: border-box; } @@ -471,6 +474,11 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { flex-wrap: nowrap; justify-content: space-between; align-items: center; + padding: 0px 16px; + } + + .content + .forecast { + padding-top: 8px; } .icon-image { @@ -549,7 +557,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { .forecast { display: flex; justify-content: space-around; - padding-top: 16px; + padding: 0px 16px; } .forecast > div { @@ -558,7 +566,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { .forecast .icon, .forecast .temp { - margin: 4px 0; + margin: 0px 0; } .forecast .temp { diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 36b5345784eb..2bda16dc2441 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -506,6 +506,7 @@ export interface WeatherForecastCardConfig extends LovelaceCardConfig { show_current?: boolean; show_forecast?: boolean; forecast_type?: ForecastType; + forecast_slots?: number; secondary_info_attribute?: keyof TranslationDict["ui"]["card"]["weather"]["attributes"]; theme?: string; tap_action?: ActionConfig; diff --git a/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts index 7e49985c40bd..69042598352f 100644 --- a/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts @@ -1,7 +1,15 @@ import { html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; -import { assert, assign, boolean, object, optional, string } from "superstruct"; +import { + assert, + assign, + boolean, + object, + optional, + string, + number, +} from "superstruct"; import { fireEvent } from "../../../../common/dom/fire_event"; import type { LocalizeFunc } from "../../../../common/translations/localize"; import "../../../../components/ha-form/ha-form"; @@ -25,6 +33,7 @@ const cardConfigStruct = assign( show_current: optional(boolean()), show_forecast: optional(boolean()), forecast_type: optional(string()), + forecast_slots: optional(number()), secondary_info_attribute: optional(string()), tap_action: optional(actionConfigStruct), hold_action: optional(actionConfigStruct), @@ -225,6 +234,11 @@ export class HuiWeatherForecastCardEditor }, }, }, + { + name: "forecast_slots", + selector: { number: { min: 1, max: 12 } }, + default: 5, + }, ] as const) : []), ] as const @@ -304,6 +318,10 @@ export class HuiWeatherForecastCardEditor return this.hass!.localize( "ui.panel.lovelace.editor.card.weather-forecast.forecast_type" ); + case "forecast_slots": + return this.hass!.localize( + "ui.panel.lovelace.editor.card.weather-forecast.forecast_slots" + ); case "forecast": return this.hass!.localize( "ui.panel.lovelace.editor.card.weather-forecast.weather_to_show" diff --git a/src/translations/en.json b/src/translations/en.json index 26bdffec7577..34a5ddcadf55 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -6993,6 +6993,7 @@ "show_only_current": "Show only current Weather", "show_only_forecast": "Show only forecast", "forecast_type": "Select forecast type", + "forecast_slots": "How many forecast elements to show", "no_type": "No type", "daily": "Daily", "hourly": "Hourly",