Lovelace: Decluttering Card

Hey,

I’ve created a new card that helps you declutter your LL config if you use multiple times the same block of cards with small differences (like an entity for example) to display things in LL.

Visit github for installation instructions, up to date documentation and troubleshooting guide

GitHub Release GitHub Activity custom_updater Project Maintenance


decluttering-card

This card is for Lovelace on Home Assistant.

We all use multiple times the same block of configuration across our lovelace configuration and we don’t want to change the same things in a hundred places across our configuration each time we want to modify something.

declutterring-card to the rescue!! This card allows you to reuse multiple times the same configuration in your lovelace configuration to avoid repetition and supports variables and default values.

Configuration

Defining your templates

First, you need to define your templates.

The templates are defined in an object at the root of your lovelace configuration. This object needs to be named decluttering_templates.

This object needs to contains your templates declaration, each template has a name and can contain variables. A variable needs to be enclosed in double square brackets [[variable_name]]. It will later be replaced by a real value when you instanciate a card which uses this template. If a variable is alone on it’s line, enclose it in single quotes: '[[variable_name]]'.

You can also define default values for your variables in the default object.

decluttering_templates:
  <template_name>
    default:  # This is optional
      - <variable_name>: <variable_value>
      - <variable_name>: <variable_value>
      [...]
    card:  # This is where you put your card config (it can be a card embedding other cards)
      type: custom:my-super-card
      [...]

Example in your lovelace-ui.yaml:

resources:
  - url: /local/decluttering-card.js
    type: module

decluttering_templates:
  my_first_template:     # This is the name of a template
    default:
      - icon: fire
    card:
      type: custom:button-card
      name: '[[name]]'
      icon: 'mdi:[[icon]]'

  my_second_template:    # This is the name of another template
    card:
      type: custom:vertical-stack-in-card
      cards:
        - type: horizontal-stack
          cards:
            - type: custom:button-card
              entity: '[[entity_1]]'
            - type: custom:button-card
              entity: '[[entity_2]]'

Using the card

Name Type Requirement Description
type string Required custom:decluttering-card
template object Required The template to use from decluttering_templates
variables list Optional List of variables and their value to replace in the template

Example which references the previous templates:

- type: custom:decluttering-card
  template: my_first_template
  variables:
    - name: Test Button
    - icon: arrow-up

- type: custom:decluttering-card
  template: my_first_template
  variables:
    - name: Default Icon Button

- type: custom:decluterring-card
  template: my_second_template
  variables:
    - entity_1: switch.my_switch
    - entity_2: light.my_light
35 Likes

Thanks @RomRider :+1:
This is exactly the thing I was looking for today after I had no luck trying to use !include in Lovelace UI editor.

2 Likes

I definitely will use this.

1 Like

One example where I’m using that card in my config (I have 8 covers):
image

Each cover is actually composed of 5 elements in a custom:vertical-stack-in-card:

  • 3 custom:button-card on top (each one has a button-card specific template associated to it, that’s a feature of the button-card itself)
  • 1 custom:slider-entity-row in the middle associated with custom:card-modder
  • 1 custom:button-card at the bottom

In ui-lovelace.yaml:

cover_button:
  type: custom:vertical-stack-in-card
  cards:
    - type: horizontal-stack
      cards:
        - type: custom:button-card
          size: '[[size]]'
          entity: '[[entity]]'
          template: cover_up
        - type: custom:button-card
          size: '[[size]]'
          entity: '[[entity]]'
          template: cover_stop
        - type: custom:button-card
          size: '[[size]]'
          entity: '[[entity]]'
          template: cover_down
    - type: custom:card-modder
      extra_styles: >
        .card-content {
          padding: 0px 0px
        }
      card:
        type: entities
        entities:
          - type: custom:slider-entity-row
            entity: '[[entity]]'
            full_row: true
            hide_state: true
    - type: custom:button-card
      name: '[[name]]'
      template: cover_name

Used like this:

    - type: horizontal-stack
      cards:
        - type: custom:decluttering-card
          template: cover_button
          variables:
            - size: 80%
            - entity: cover.cover_1
            - name: Window 1

        - type: custom:decluttering-card
          template: cover_button
          variables:
            - size: 80%
            - entity: cover.cover_2
            - name: Window 2

        - type: custom:decluttering-card
          template: cover_button
          variables:
            - size: 80%
            - entity: cover.cover_3
            - name: Window 3
7 Likes

I had to sit down and really process the impact of this card before I truly understood its purpose. You, sir, are a godsend. Thank you!

Interesting behavior I’ve discovered with the new templating system. It appears that
custom:button-cards (specifically color_type: blank-card) nested inside of a horizontal-stack are not being rendered. This happens with and without the use of button-card templates. It just has to be color_type: blank-card.

Decluttered Card (Notice the missing spacing and border radius on the left and right side.)

Non-Decluttered Card

Here’s the corresponding yaml

Button Card Template

button_card_templates:
  vertical-divider-grey:
    color_type: blank-card
    styles:
      card:
        - width: 3px
        - color: '#292929'

  horizontal-divider-grey:
    color_type: blank-card
    styles:
      card:
        - height: 3px
        - background-color: '#292929'

Decluttered Card Template

decluttering_templates:
  # Button Templates For Use Throughout Lovelace
  custom_dimmer_card_template:
    type: custom:vertical-stack-in-card
    cards:
      - type: custom:button-card
        template: horizontal-divider-grey
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            # template: vertical-divider-grey
            color_type: blank-card
            styles:
              card:
                - width: 3px
                - color: '#292929'
          - type: custom:button-card
            template: vertical-divider-grey
          - type: custom:button-card
            template: dimmer-left-button-settings
            entity: '[[entity]]'
            name: '[[name]]'
          - type: custom:card-modder
            style:
              background-color: '#222222'
              border-radius: 0px 10px 10px 0px
              height: 39px
              padding: 8px
            card:
              type: custom:slider-entity-row
              entity: '[[entity]]'
              step: 2
              full_row: true
          - type: custom:button-card
            template: vertical-divider-grey
          - type: custom:button-card
            template: vertical-divider-grey
      - type: custom:button-card
        template: horizontal-divider-grey

Decluttered Card Declaration

- type: custom:decluttering-card
  template: custom_dimmer_card_template
  variables:
    - entity: light.kitchen_dimmer
    - name: Kitchen

Original, Non-Declutterified Card Declaration

- type: custom:vertical-stack-in-card
  cards:
    - type: custom:button-card
      template: horizontal-divider-grey
    - type: horizontal-stack
      cards:
        - type: custom:button-card
          template: vertical-divider-grey
        - type: custom:button-card
          template: vertical-divider-grey
        - type: custom:button-card
          template: dimmer-left-button-settings
          entity: light.kitchen_dimmer
          name: Kitchen
        - type: custom:card-modder
          style:
            background-color: '#222222'
            border-radius: 0px 10px 10px 0px
            height: 39px
            padding: 8px
          card:
            type: custom:slider-entity-row
            entity: light.kitchen_dimmer
            step: 2
            full_row: true
        - type: custom:button-card
          template: vertical-divider-grey
        - type: custom:button-card
          template: vertical-divider-grey
    - type: custom:button-card
      template: horizontal-divider-grey
3 Likes

I’ll have a look but I don’t understand the purpose of the horizontal divider? By default there is a margin of 4px between cards.

Also I don’t understand how you managed to have the initial render with this config, as the border radius are those from the vertical-stack-in-card but they display around the horizontal-stack embedded inside (that is unexpected), excluding the “spacers” on the left and on the right.

I think it just needs some refactoring :blush:

EDIT: does the layout change if you use the refresh button from lovelace (top right)?

I should probably clarify that I am encompassing my buttons inside of a vertical-stack-in-card in order to control the spacing between cards. This is how I achieved the effect of two buttons looking like one button. Of course, using vertical-stack-in-card also means that I have to explicitly create my own gaps, hence the horizontal and vertical dividers using the blank-card feature of custom:button-card.

EDIT: No, the built in refresh button has no effect. Neither does clearing the cache.

Okay I see, that adds some complexity. I had issues with vertical-stack-in-card embedded in vertical-stack-in-card.
I’ll have a look ASAP with what you provided.

I am storing your card localy.

Do I track the card version using, custom_updater, and:
https://raw.githubusercontent.com/custom-cards/decluttering-card/master/package-lock.json
or
https://raw.githubusercontent.com/custom-cards/decluttering-card/master/package.json

Please advise.

You don’t have to add anything to custom updater. It will be automatic.

1 Like

Oh My God! What a huge help for us!!!
Many-many Thanx!!! :+1:
Only 6 rows instead of 60 rows / button!!!

1 Like

My lovelace picture elements for floorplant so long.

- type: image
  elements:
    - type: image
      entity: switch.sofa_light
      hold_action: none
      state_image:
        'on': /local/sofa.png?v=1
      style:
        left: 0%
        top: 0%
        transform: none
      tap_action: none
    - type: image
      entity: switch.tv_light
      hold_action: none
      state_image:
        'on': /local/tv.png?v=1
      style:
        left: 0%
        top: 0%
        transform: none
      tap_action: none

and template

decluttering_templates:
  image_on:
    entity: '[[entity]]'
    hold_action: none
    state_image:
      'on': '/local/''[[name]]''.png?v=1'
    style:
      left: 0%
      top: 0%
      transform: none
    tap_action: none
    type: image

How can I reduce my lovelace code?

Look at the example in the first post, the template has to be a card, with variables, and then you assign the variables when you use the card.
Your template is not a card, it’s something strange.

decluttering_templates:
  image_on
    type: image
    entity: '[[entity]]'
    hold_action: none
    state_image:
      'on': '/local/[[name]].png?v=1'
    style:
      left: 0%
      top: 0%
      transform: none
    tap_action: none

And then you use it like this:

- type: image
  elements:
    - type: custom:decluttering-card
      template: image_on
      variables:
        - entity: switch.sofa_light
        - name: sofa
    - type: custom:decluttering-card
      template: image_on
      [...]

I’m not sure this works (embedding a decluttering-card inside an image card) but worth trying. :slight_smile:

1 Like

You’re a legend, this is great! I’ve been looking for something like this for a while now and it seems to be working perfectly so far. :clap:

1 Like

Has anyone found a way to incorporate a label template within Decluttering Card? I’m specifically looking to use:

label_template: >
      var bri = states['[[entity]]'].attributes.brightness;
      return 'Brightness: ' + (bri ? bri : '0') + '%';

where entity is passed back from the card declaration. I’ve tried using:

decluttering_templates:
  homekit_dimmer_card:
    type: custom:button-card
    template: homekit_dimmer
    label_template: >
      var bri = states['[[entity]]'].attributes.brightness;
      return 'Brightness: ' + (bri ? bri : '0') + '%';

but that did not work.

Use the button card template for that, no need to use this one and then pass the entity in the button-card entity field (entity: '[[entity]]'). You can also use entity.attributes.brightness instead of state[...]... in button card, entity is a variable with your entity state object:

label_template: >
      var bri = entity.attributes.brightness;
      return 'Brightness: ' + (bri ? bri : '0') + '%';

Keep it simple :slightly_smiling_face:

1 Like

Thanks! :trophy: @RomRider :tada: I 've been doing a massive .yaml reduction and this is the :bomb: Perfect timing :raised_hands:

1 Like

Hi @RomRider

I am getting some odd behaviour with spacing of templated button cards. Any ideas? I basically want all of the button cards left aligned within the stack but they are evenly spacing with the decluttering-card.

I have multiple horizontal stacks within a vertical stack.
My standard cards look like this:
image

But when I recreate them with the decluttering card I get this: (bottom row is standard config, top is decluttering-card)
image

Config for the buttons:

      - cards:
          - type: 'custom:decluttering-card'
            template: light_button_with_brightness
            variables:
              - entity: light.stairwell_lights_81
              - name: Stairwell
              - icon: stairs
          - type: 'custom:decluttering-card'
            template: light_button
            variables:
              - entity: light.hobb_led_153
              - name: Hobb LED
              - icon: led-strip
          - type: 'custom:decluttering-card'
            template: light_button
            variables:
              - entity: light.bench_pendants_236
              - name: Bench
              - icon: ceiling-light
          - type: 'custom:decluttering-card'
            template: light_button_with_brightness
            variables:
              - entity: light.kitchen_lights_79
              - name: Kitchen
              - icon: lightbulb
        type: horizontal-stack

One of my templates:

decluttering_templates:
  light_button_with_brightness:
    entity: '[[entity]]'
    icon: 'mdi:[[icon]]'
    name: '[[name]]'
    type: 'custom:button-card'
    tap_action:
      action: toggle
    hold_action:
      action: more-info
    layout: icon_label
    show_label: true
    label_template: >
      var bri = Math.round(entity.attributes.brightness / 2.55);  return (bri ?
      bri : '0') + '%';
    show_name: true
    state:
      - styles:
          card:
            - box-shadow: 0px 0px 10px 3px var(--paper-item-icon-active-color)
          icon:
            - color: var(--paper-item-icon-active-color)
        value: 'on'
    styles:
      card:
        - border-radius: 15px
        - height: 76px
        - width: 76px
        - margin: 5px 5px 0px 0px
        - padding: 0px 0px
        - '--paper-card-background-color': 'rgba(40, 40, 40, 0.5)'
      grid:
        - grid-template-rows: 42px auto 0px
        - grid-template-columns: 42px auto
      icon:
        - width: 30px
        - color: white
      label:
        - font-size: 12px
        - font-weight: bold
        - color: white
      name:
        - justify-self: start
        - align-self: end
        - padding: 9px 10px
        - font-size: 12px
        - font-weight: bold
        - color: white
1 Like

Much like @petro with his use of anchors, this card is going to make my life SO much easier once I sort out that spacing issue. 5 lines of YAML per button rather than 46 is pure gold!! Considering I have around 200 buttons, my config was getting crazy. I would go down the anchor route except I’m not using YAML mode for Lovelace so this card is perfect. Thanks @RomRider.