TBens / lovelace-ui-minimalist

🌻 Lovelace UI • Minimalist
194 stars 31 forks source link

My Home Assistant

At the top of each page we find the chips which allow me to quickly visualize the important information of the page. Then title to separate the different sections and cards to represent and interact with devices, sensors, etc … I used the custom component button-card for all these cards. I drew a lot of inspiration from 7ahang’s work that I found on Behance.

Table of Contents

Installation

  1. Add button_card_templates in ui-lovelace.yaml file.
    button_card_templates: !include lovelace/button_card_templates/button_card_templates.yaml
  2. Add resources in your configuration.yaml file. You will need at least button-card
    lovelace:
      mode: yaml
      resources: !include lovelace/resources/resources.yaml
  3. Add themes in your configuration.yaml file
    frontend: 
      themes: !include configuration/themes.yaml

Design system

Colors

I tried to set up a consistency between the colors used to represent the entities.

Color Type
![orange](https://user-images.githubusercontent.com/12232620/127771417-73385ee2-8c31-47a4-8438-472826184ea1.png) 💡 Light ⚡ Electricity
![red](https://user-images.githubusercontent.com/12232620/127771470-38b1eba2-fc8a-41a8-a1fa-5fa249619af6.png) 🔥 Heating
![Blue](https://user-images.githubusercontent.com/12232620/127771485-615cf15e-d7fe-4528-8ccb-db3c307c3428.png) ☑️ On/off devices 🏠 Home
![green](https://user-images.githubusercontent.com/12232620/127771492-1abcd92b-8261-45e6-bdfb-d7987dcb6c76.png) 🌲 Exterior

Chips

Chips

Code template
Template
```yaml chips: tap_action: action: more-info show_icon: false show_name: false show_state: false show_label: true size: 80% styles: img_cell: - width: 24px card: - border-radius: 18px - box-shadow: var(--box-shadow) - height: 36px - width: auto - padding-left: 6px - padding-right: 6px grid: - grid-template-areas: '"l"' label: - justify-self: center - padding: 0px 6px - font-weight: bold - font-size: 14px ```

Temperature

Chips - Temperature

Code
Example Template
```yaml - template: chips_temperature type: 'custom:button-card' ``` ```yaml chips_temperature: template: chips tap_action: action: navigate navigation_path: /lovelace/temperature label: | [[[ var inter = states['sensor.fibaro_multisensor_salon_temperature'].state; var exter = states['sensor.fibaro_multisensor_balcon_temperature'].state; var icon = '☀️'; if (states['sensor.dark_sky_icon'].state == 'clear-day'){ var icon = '☀️'; } else if(states['sensor.dark_sky_icon'].state == 'clear-night'){ var icon = '🌙'; } else if(states['sensor.dark_sky_icon'].state == 'rain'){ var icon = '🌧️'; } else if(states['sensor.dark_sky_icon'].state == 'snow'){ var icon = '❄️'; } else if(states['sensor.dark_sky_icon'].state == 'sleet'){ var icon = '❄️'; } else if(states['sensor.dark_sky_icon'].state == 'wind'){ var icon = '🌫️'; } else if(states['sensor.dark_sky_icon'].state == 'fog'){ var icon = '🌫️'; } else if(states['sensor.dark_sky_icon'].state == 'cloudy'){ var icon = '☁️'; } else if(states['sensor.dark_sky_icon'].state == 'partly-cloudy-day'){ var icon = '⛅️'; } else if(states['sensor.dark_sky_icon'].state == 'partly-cloudy-night'){ var icon = '⛅'; } return icon + ' ' + exter + '° / ' + inter + '°' ; ]]] ```

Electric consumption

Chips - Consommation

Code
Example Template
```yaml - template: chips_power_consumption type: 'custom:button-card' ``` ```yaml chips_power_consumption: template: chips tap_action: action: navigate navigation_path: /lovelace/consommation label: | [[[ var price = states['sensor.atome_price_conso_today'].state; return '⚡ ' + price + '€' ; ]]] ```

Presence counter

Chips - Present

Code
Example Template
```yaml - template: chips_localisation_present type: 'custom:button-card' ``` ```yaml chips_localisation_present: tap_action: action: navigate navigation_path: /lovelace/localisation label: | [[[ var personnes_presentes = states['sensor.people_count_present'].state; return '🏠 ' + personnes_presentes; ]]] template: chips ```

Return button

Chips - return

Code
Example Template
```yaml - template: chips_return type: 'custom:button-card ``` ```yaml chips_return: template: chips show_icon: true icon: 'mdi:arrow-left' size: 80% styles: grid: - grid-template-areas: '"i"' tap_action: action: navigate navigation_path: /lovelace/home ```

Scene

Scene

Code
Example Template Template Blue
```yaml - entity: sensor.present template: scene_blue variables: state: "Present" type: 'custom:button-card' ``` ```yaml scene: size: 20px show_label: true label: | [[[ return (entity.attributes.value )]]] styles: card: - border-radius: var(--border-radius) - box-shadow: var(--box-shadow) - padding: 10px 0px 8px 0px grid: - grid-template-areas: '"i" "n" "l"' name: - margin-top: 10px - justify-self: center - font-weight: bold - font-size: 14px label: - justify-self: center - align-self: start - font-weight: bolder - font-size: 12px - filter: opacity(40%) icon: - color: 'rgba(var(--color-theme),0.2)' img_cell: - background-color: 'rgba(var(--color-theme),0.05)' - border-radius: 50% - place-self: center - width: 42px - height: 42px ``` ```yaml scene_blue: variables: state: "default" template: - scene state: - operator: template value: > [[[ return states['input_select.localisation_thomas'].state == variables.state ]]] styles: icon: - color: 'rgba(var(--color-blue),1)' img_cell: - background-color: 'rgba(var(--color-blue), 0.2)' card: - background-color: 'rgba(var(--color-background-blue), var(--opacity-bg))' name: - color: 'rgba(var(--color-blue-text),1)' label: - color: 'rgba(var(--color-blue-text),1)' ```

Title

Title

Code
Example Template
```yaml - template: title name: Title label: 'Subtitle' type: 'custom:button-card' ``` ```yaml title: tap_action: action: none show_icon: false show_label: true show_name: true styles: card: - background-color: rgba(0,0,0,0) - box-shadow: none - height: auto - width: auto - margin-top: 12px - margin-left: 24px - margin-bottom: 0px grid: - grid-template-areas: '"n" "l"' - grid-template-columns: 1fr - grid-template-rows: min-content min-content name: - justify-self: start - font-weight: bold - font-size: '1.5rem' label: - justify-self: start - font-weight: bold - font-size: '1rem' - opacity: '0.4' ```

Cards

Cards

Anatomy

Anatomy

  1. Dot : Visible when the device is unavailable. Also used on the entity person
  2. Icon : Icon that represents the device
  3. Primary line : Main information
  4. Secondary line : Secondary information
  5. Optionnal part : Possibility to display buttons to launch actions related to the device. Or display a graph to view the history of a sensor

Light

Light

Code
Example Template
```yaml - entity: light.example name: Lumière template: - icon_info_bg - light type: 'custom:button-card' ``` ```yaml light: tap_action: action: toggle hold_action: action: more-info label: >- [[[ if (entity.state !='unavailable'){ if (entity.state =='off'){ var bri = Math.round(entity.attributes.brightness / 2.55); return 'Off'; }else{ var bri = Math.round(entity.attributes.brightness / 2.55); return (bri ? bri : '0') + '%'; } }else{ return "Indisponible"; } ]]] template: - yellow ```

Light slider

Light-slider

Code
Example Template
```yaml - entity: light.exemple template: - light_slider variables: entity: "light.exemple" name: "Light" type: 'custom:button-card' ``` ```yaml light_slider: variables: name: "Default name" show_icon: false show_name: false show_label: false styles: card: - border-radius: var(--border-radius) - box-shadow: var(--box-shadow) - padding: 12px grid: - grid-template-areas: '"item1" "item2"' - grid-template-columns: 1fr - grid-template-rows: min-content min-content - row-gap: 12px state: - operator: template value: > [[[ return entity.state == 'on' ]]] styles: card: - background-color: 'rgba(var(--color-background-yellow),var(--opacity-bg))' custom_fields: item1: card: entity: '[[[ return variables.entity ]]]' name: '[[[ return variables.name ]]]' template: - icon_info - light type: 'custom:button-card' item2: card: type: 'custom:slider-card' entity: '[[[ return variables.entity ]]]' radius: 14px height: 42px mainSliderColor: rgba(var(--color-yellow),1) secondarySliderColor: rgba(var(--color-yellow),0.2) mainSliderColorOff: rgba(var(--color-theme),0.05) secondarySliderColorOff: rgba(var(--color-theme),0.05) thumbHorizontalPadding: '0px' thumbVerticalPadding: '0px' thumbWidth: 0px card_mod: style: | ha-card { border-radius: 14px; box-shadow: none; } ```

Outlet

Prise

Code
Example Template
```yaml - entity: switch.exemple name: Prise template: - icon_info_bg - outlet label: |- [[[ if (entity.state =='on') var etat = "On • " + states["sensor.exemple"].state + "W"; else var etat = "Off"; return etat ; ]]] type: 'custom:button-card' ``` ```yaml outlet: tap_action: action: more-info label: |- [[[ if (entity.state =='on') var etat = "On"; else var etat = "Off"; return etat ; ]]] template: - yellow ```

Binary sensor

Mouvements Fenêtres

Code
Example Template
```yaml - entity: binary_sensor.example name: Mouvement icon: 'mdi:run' template: - icon_info_bg - binary_sensor type: 'custom:button-card' ``` ```yaml binary_sensor: show_last_changed: true template: - blue ```

Cover

Volets

Code
Example Template
```yaml - template: cover_buttons variables: entity: "cover.example" name: "Volets" type: 'custom:button-card' ``` ```yaml cover_buttons: variables: entity: "cover.fibaro_cover_balcon" name: "Default name" styles: card: - border-radius: var(--border-radius) - box-shadow: var(--box-shadow) - padding: 12px grid: - grid-template-areas: '"item1" "item2"' - grid-template-columns: 1fr - grid-template-rows: min-content min-content - row-gap: 12px custom_fields: item1: card: entity: '[[[ return variables.entity ]]]' name: '[[[ return variables.name ]]]' tap_action: action: more-info template: - icon_info - cover type: 'custom:button-card' item2: card: template: list_items type: 'custom:button-card' custom_fields: item1: card: icon: 'mdi:arrow-down' tap_action: action: call-service service: cover.close_cover service_data: entity_id: '[[[ return variables.entity ]]]' type: 'custom:button-card' template: widget_icon item2: card: icon: 'mdi:pause' tap_action: action: call-service service: cover.stop_cover service_data: entity_id: '[[[ return variables.entity ]]]' type: 'custom:button-card' template: widget_icon item3: card: icon: 'mdi:arrow-up' tap_action: action: call-service service: cover.open_cover service_data: entity_id: '[[[ return variables.entity ]]]' type: 'custom:button-card' template: widget_icon ```

Thermostat

Thermostat

Code
Example Template
```yaml - entity: climate.example template: - icon_info_bg - thermostat type: 'custom:button-card' ``` ```yaml thermostat: hold_action: action: more-info entity: input_boolean.radiateur_arret_force label: >- [[[ if (entity.state =='off'){ return 'Off' ; }else{ if (states['light.qubino'].state == 'on'){ var etat = "Chauffe"; }else{ var etat = "Inactif"; } return (entity.attributes.temperature ) + '°' + ' • ' + etat ; } ]]] state: - operator: template value: > [[[ return states['light.qubino'].state == 'on' ]]] styles: icon: - color: 'rgba(var(--color-red),1)' img_cell: - background-color: 'rgba(var(--color-red),0.2)' card: - background-color: 'rgba(var(--color-background-red),var(--opacity-bg))' name: - color: 'rgba(var(--color-red-text),1)' label: - color: 'rgba(var(--color-red-text),1)' ```

Water heater

Chauffe-eau

Code
Example Template
```yaml - entity: switch.example name: Chauffe eau template: - icon_info_bg - water_heater type: 'custom:button-card' ``` ```yaml water_heater: icon: 'mdi:waves' tap_action: action: more-info hold_action: action: more-info label: >- [[[ if (entity.state == 'off'){ return 'Arrêt forcé'; }else{ if (states["sensor.shelly_prise_salon_conso"].state > 0){ var etat = "Chauffe • " + states["sensor.shelly_prise_salon_conso"].state + "W"; }else{ var etat = "Inactif"; } return etat ; } ]]] state: - operator: template value: > [[[ return (states['sensor.shelly_prise_salon_conso'].state > 0) ]]] styles: icon: - color: 'rgba(var(--color-red),1)' img_cell: - background-color: 'rgba(var(--color-red),0.2)' card: - background-color: 'rgba(var(--color-background-red),var(--opacity-bg))' name: - color: 'rgba(var(--color-red-text),1)' label: - color: 'rgba(var(--color-red-text),1)' ```

Media player

Enceintes

Code
Example Template
```yaml - entity: media_player.example name: Enceintes template: - icon_info_bg - media type: 'custom:button-card' ``` ```yaml media: label: >- [[[ if (entity.state =='off'){ return "Off"; }else{ return entity.state; } ]]] icon: | [[[ var application = entity.attributes.app_name; var icon = 'mdi:speaker'; if (application == 'Oto music'){ var icon = 'mdi:music-circle'; } else if(application == 'Spotify'){ var icon = 'mdi:spotify'; } else if(application == 'Google Podcasts'){ var icon = 'mdi:google-podcast'; } else if(application == 'Plex'){ var icon = 'mdi:plex'; } return icon ; ]]] styles: label: - opacity: '0.6' icon: - color: 'rgba(var(--color-theme),0.2)' img_cell: - background-color: 'rgba(var(--color-theme),0.05)' card: - background-blend-mode: multiply - background: > [[[ var image = entity.attributes.entity_picture_local; var bg = entity.attributes.entity_picture_local; if (image == null){ var bg = ''; } else{ var bg = 'center / cover url(' + image + ') rgba(0, 0, 0, 0.15)'; } return bg; ]]] state: - operator: template value: > [[[ return entity.state !='off' ]]] name: > [[[ return entity.attributes.media_title; ]]] label: > [[[ return entity.attributes.media_album_name; ]]] styles: label: - color: white - filter: opacity(100%) img_cell: - background-color: 'rgba(var(--color-theme),0.0)' icon: - color: white name: - color: white ```

Playstation

Playstation

Code
Example Template
```yaml - entity: media_player.example template: - icon_info_bg - ps4 type: 'custom:button-card' ``` ```yaml ps4: label: >- [[[ if (entity.state =='unknown'){ return "Off"; }else if (entity.state =='standby'){ return "En veille"; }else{ return "On"; } ]]] styles: icon: - color: 'rgba(var(--color-theme),0.2)' img_cell: - background-color: 'rgba(var(--color-theme),0.05)' state: - value: 'idle' styles: icon: - color: 'rgba(var(--color-blue),1)' img_cell: - background-color: 'rgba(var(--color-blue), 0.2)' - value: 'standby' styles: icon: - color: 'rgba(var(--color-theme),0.2)' img_cell: - background-color: 'rgba(var(--color-theme),0.05)' - operator: template value: > [[[ return entity.state !='unknown' ]]] name: > [[[ return entity.attributes.media_title; ]]] label: > [[[ return entity.attributes.friendly_name; ]]] styles: label: - color: white - filter: opacity(100%) img_cell: - background-color: 'none' icon: - color: white name: - color: white card: - background-blend-mode: multiply - background: > [[[ var image = entity.attributes.entity_picture; return 'center / cover url(' + image + ') rgba(0, 0, 0, 0.15)'; ]]] ```

Person

Personne

Information **Dot** : - At home : Blue - Away : Green **Dot icon** : - At home : Home - Away : Walking man - Sleeping : Moon **Comment** : The sleep state takes over the At home or Away state to display the moon icon
Code
Example Template
```yaml - entity: input_select.localisation_thomas variables: personne: "thomas" template: - icon_info_bg - personne-thomas name: Thomas type: 'custom:button-card' ``` ```yaml person: tap_action: action: more-info show_label: true label: > [[[return entity.state]]] styles: icon: - color: 'rgba(var(--color-theme),0.9)' custom_fields: notification: - border-radius: 50% - position: absolute - left: 38px - top: 8px - height: 16px - width: 16px - border: 2px solid var(--card-background-color) - font-size: 12px - line-height: 14px #################################################### person-thomas: variables: person: "thomas" template: person hold_action: action: more-info entity: input_boolean.thomas_nuit styles: custom_fields: notification: - background-color: > [[[ if (states['input_select.localisation_thomas'].state == 'Present'){ return "rgba(var(--color-blue),1)"; }else{ return "rgba(var(--color-green),1)"; } ]]] custom_fields: notification: > [[[ if (states['input_boolean.thomas_nuit'].state == 'on'){ return `` }else{ if (states['input_select.localisation_thomas'].state == 'Present'){ return `` }else{ return `` } } ]]] ```

Generic

Generic

Code
Example Template
```yaml - entity: sensor.example template: - icon_info_bg - generic type: 'custom:button-card' ``` ```yaml generic: label: > [[[return entity.state + " " + entity.attributes.unit_of_measurement]]] styles: icon: - color: 'rgba(var(--color-theme),0.9)' grid: - grid-template-areas: '"i l" "i n"' - grid-template-columns: min-content auto - grid-template-rows: min-content min-content label: - align-self: end - justify-self: start - font-weight: bold - font-size: 14px - margin-left: 12px - filter: opacity(100%) name: - justify-self: start - align-self: start - font-weight: bolder - font-size: 12px - filter: opacity(40%) - margin-left: 12px ```

Generic + graph

Entity - graph

Code
Example Template
```yaml - type: 'custom:button-card' template: graph variables: entity: "sensor.exemple" color: "var(--google-blue)" name: "Température" ``` ```yaml graph: variables: entity: "sensor.xiaomi_multisensor_salon_humidite" color: "var(--info-color)" name: "Default name" styles: card: - border-radius: var(--border-radius) - box-shadow: var(--box-shadow) - padding: 0px grid: - grid-template-areas: '"item1" "item2"' - grid-template-columns: 1fr - grid-template-rows: min-content min-content custom_fields: item1: card: entity: '[[[ return variables.entity ]]]' name: '[[[ return variables.name ]]]' template: - icon_info - generic styles: card: - padding: 12px type: 'custom:button-card' item2: card: type: 'custom:mini-graph-card' entities: - entity: '[[[ return variables.entity ]]]' line_color: '[[[ return variables.color ]]]' show: name: false icon: false legend: false state: false style: | ha-card { box-shadow: none; border-radius: var(--border-radius); } ```