Mushroom Cards - Build a beautiful dashboard easily šŸ„ (Part 1)

Iā€™ve finally started investing some limited time in converting my dashboards over to these cards. Iā€™m making some good progress so thought Iā€™d share.

This card allows me to control the Harmony Hub activities. There is some automations in the background that manage the sleep timers but thatā€™s out of scope for this thread. The sleep timers section is only shown if there is an active activity. The sleep timer countdown is only visible if the sleep timer is active.

By default the Harmony integration does not enable switches for the activities and I wanted to keep the integrations as close to default as possible. So, this implementation will take the options from the select entity and create the card.

I use decluttering-card to generalise it so that it is reusable but hopefully this might give some ideas.
The YAML (not using decluttering-card) is as follows.

Other cards required (besides mushroom): -

type: vertical-stack
cards:
  - type: custom:mushroom-title-card
    title: '{{ area_name(''select.lounge_activities'') }} - Media Activities'
  - type: entities
    entities:
      - type: custom:auto-entities
        card:
          type: custom:layout-card
          layout_type: custom:grid-layout
          layout:
            grid-auto-columns: 1fr
            grid-auto-flow: column
            margin: 0
            padding: 0
            card_margin: 0
        card_param: cards
        filter:
          template: >
            {% set ns = namespace(activities=[]) %} {% for opt in
            state_attr('select.lounge_activities', 'options') if opt |
            lower != 'poweroff' %}
              {% set icon = iif(opt | lower == 'watch films', 'mdi:filmstrip', '') %}
              {% set icon = iif(opt | lower == 'watch tv', 'mdi:television', icon) %}
              {% set icon = iif(opt | lower == 'watch roku', 'mdi:play-box-multiple-outline', icon) %}
              {% set icon = iif(opt | lower == 'watch tv app', 'mdi:television-guide', icon) %}
              {% set icon = iif((opt | lower).startswith('listen to music'), 'mdi:music-box-outline', icon) %}
              {% set icon = iif(opt | lower == 'listen to music - upstairs', 'mdi:music-box-multiple-outline', icon) %}
              {% set icon = iif(icon == '', 'mdi:help', icon) %}
              {% set action_option = iif(is_state('select.lounge_activities', opt), 'PowerOff', opt) %}
              {% set ns.activities = ns.activities + [{
                  'type': 'custom:mushroom-template-card',
                  'card_mod': {
                    'style': {
                      '.': 'ha-card { --ha-card-box-shadow: none; --card-primary-font-weight: normal; } mushroom-card { height: 100%; }',
                      'mushroom-state-info': {
                        '$': '.primary { white-space: unset !Important; }'
                      }
                    }
                  },
                  'badge_color': 'var(--rgb-green)',
                  'badge_icon': '{{ iif(is_state(entity, "' ~ opt ~ '"), "mdi:check") }}',
                  'entity': 'select.lounge_activities',
                  'fill_container': true,
                  'icon': icon,
                  'icon_color': '{{ iif(is_state(entity, "' ~ opt ~ '"), "blue") }}',
                  'layout': 'vertical',
                  'primary': opt,
                  'tap_action': {
                    'action': 'call-service',
                    'service': 'select.select_option',
                    'data': {
                      'entity_id': 'select.lounge_activities',
                      'option': action_option
                    }
                  }
                }] %}
            {% endfor %} {{ ns.activities }}
      - type: conditional
        conditions:
          - entity: select.lounge_activities
            state_not: PowerOff
        row:
          type: section
          label: Sleep timer
      - type: custom:layout-card
        layout_type: custom:grid-layout
        layout:
          grid-template-columns: 1fr 25%
          margin: 0
          padding: 0
          card_margin: 0
        cards:
          - type: conditional
            conditions:
              - entity: select.lounge_activities
                state_not: PowerOff
            card:
              type: custom:mushroom-chips-card
              card_mod:
                style:
                  .: >
                    ha-card { background-color:
                    var(--card-background-color) !important; }
                  mushroom-template-chip:
                    $:
                      mushroom-chip:
                        $: |
                          ha-card {  } ha-card .content { width: 100%; }
              chips:
                - type: template
                  content: 'Off'
                  tap_action:
                    action: call-service
                    service: input_select.select_option
                    data:
                      entity_id: input_select.sleep_timer_duration_lounge
                      option: 'Off'
                  card_mod:
                    style: >
                      {% if
                      is_state('timer.sleep_timer_remaining_lounge',
                      'idle') %}
                        ha-card { background-color: rgba(var(--rgb-blue), 0.2) !important; }
                      {% else %}
                        ha-card { background-color: rgba(var(--rgb-grey), 0.2) !important; }
                      {% endif %}
                - type: template
                  content: '30'
                  tap_action:
                    action: call-service
                    service: input_select.select_option
                    data:
                      entity_id: input_select.sleep_timer_duration_lounge
                      option: '30'
                  card_mod:
                    style: >
                      {% set entity =
                      'timer.sleep_timer_remaining_lounge' %} {% if not
                      is_state(entity, 'idle') %}
                        {% set ns = namespace(mins=0, duration=30) %}
                        {% set duration = state_attr(entity, 'duration') %}
                        {% set mins = 0 %}
                        {% for tp in duration.split(":") %}
                          {% if loop.index == 1 %}
                            {% set ns.mins = ns.mins + tp | int(0) * 60 %}
                          {% elif loop.index == 2 %}
                            {% set ns.mins = ns.mins + tp | int(0) %}
                          {% elif loop.index == 3 %}
                            {% set ns.mins = int(ns.mins + tp | int(0) / 60, 0) %}
                          {% endif %}
                        {% endfor %}
                        {% if ns.mins == ns.duration %}
                          ha-card { background-color: rgba(var(--rgb-blue), 0.2) !important; }
                        {% else %}
                          ha-card { background-color: rgba(var(--rgb-grey), 0.2) !important; }
                        {% endif %}
                      {% else %}
                        ha-card { background-color: rgba(var(--rgb-grey), 0.2) !important; }
                      {% endif %}
                - type: template
                  content: '60'
                  tap_action:
                    action: call-service
                    service: input_select.select_option
                    data:
                      entity_id: input_select.sleep_timer_duration_lounge
                      option: '60'
                  card_mod:
                    style: >
                      {% set entity =
                      'timer.sleep_timer_remaining_lounge' %} {% if not
                      is_state(entity, 'idle') %}
                        {% set ns = namespace(mins=0, duration=60) %}
                        {% set duration = state_attr(entity, 'duration') %}
                        {% set mins = 0 %}
                        {% for tp in duration.split(":") %}
                          {% if loop.index == 1 %}
                            {% set ns.mins = ns.mins + tp | int(0) * 60 %}
                          {% elif loop.index == 2 %}
                            {% set ns.mins = ns.mins + tp | int(0) %}
                          {% elif loop.index == 3 %}
                            {% set ns.mins = int(ns.mins + tp | int(0) / 60, 0) %}
                          {% endif %}
                        {% endfor %}
                        {% if ns.mins == ns.duration %}
                          ha-card { background-color: rgba(var(--rgb-blue), 0.2) !important; }
                        {% else %}
                          ha-card { background-color: rgba(var(--rgb-grey), 0.2) !important; }
                        {% endif %}
                      {% else %}
                        ha-card { background-color: rgba(var(--rgb-grey), 0.2) !important; }
                      {% endif %}
          - type: conditional
            conditions:
              - entity: timer.sleep_timer_remaining_lounge
                state_not: idle
            card:
              type: entities
              card_mod:
                style:
                  .: |
                    ha-card { --ha-card-box-shadow: none; }
                    #states { padding: 0px; }
                  hui-timer-entity-row$:
                    hui-generic-entity-row$: |
                      state-badge { visibility: hidden; }
                      state-badge + div { visibility: hidden; }
              entities:
                - entity: timer.sleep_timer_remaining_lounge
4 Likes

With a HUGE Thank you to @Posreg hereā€™s my rendition of the ā€˜personā€™ card:

When you are driving the location will change to ā€œJohn is: Drivingā€ when you become stationary
it will display your location. Will be adding a tap_action to the location to pop up a map to show
your location [makes my wife happy :slight_smile: Iā€™m a contractor and from day to day I can be anywhere].

Must also install this ā†’
Places

here

and the code:

- type: custom:stack-in-card
        mode: vertical
        cards:
          - type: custom:stack-in-card
            mode: horizontal
            # card_mod:
            # style: |
            #   ha-card {
            #   background-color: rgba(255, 255, 255, .1);
            #   }
            cards:
              - type: custom:mushroom-person-card
                entity: device_tracker.sm_f926u1
                icon_type: entity-picture
                hide_name: true
                layout: vertical
                secondary_info: state
              - type: conditional
                conditions:
                  - entity: sensor.sm_f926u1_battery_state
                    state: "charging"
                card:
                  type: custom:mushroom-template-card
                  entity: sensor.sm_f926u1_battery_level
                  layout: vertical
                  icon_color: light-green
                  fill_container: true
                  name: SG21
                  icon: mdi:battery-charging-medium
                  hide_name: true
                  primary: "{{ states('sensor.sm_f926u1_battery_level') }}%"
                  secondary: "{{ states('sensor.sm_f926u1_battery_temperature') }}Ā°"
                  card_mod:
                    style: |
                      mushroom-shape-icon {
                        animation: blink 1s linear infinite;
                      }          
                      @keyframes blink {
                        50% {opacity: 0;}
                      }
              - type: conditional
                conditions:
                  - entity: sensor.sm_f926u1_battery_state
                    state: "discharging"
                card:
                  type: custom:mushroom-template-card
                  entity: sensor.sm_f926u1_battery_level
                  layout: vertical
                  icon: |2
                      {% set bl = states('sensor.sm_f926u1_battery_level') | int %}
                      {% if bl < 10 %} mdi:battery-outline
                      {% elif bl < 20 %} mdi:battery-10
                      {% elif bl < 30 %} mdi:battery-20
                      {% elif bl < 40 %} mdi:battery-30
                      {% elif bl < 50 %} mdi:battery-40
                      {% elif bl < 60 %} mdi:battery-50
                      {% elif bl < 70 %} mdi:battery-60
                      {% elif bl < 80 %} mdi:battery-70
                      {% elif bl < 90 %} mdi:battery-80
                      {% elif bl < 100 %} mdi:battery-90
                      {% elif bl == 100 %} mdi:battery
                      {% else %} mdi:battery-unknown
                      {% endif %}
                  icon_color: |2-
                              {% set bl = states('sensor.sm_f926u1_battery_level') | int %}
                              {% if bl < 10 %} #cc0c16
                              {% elif bl < 20 %} #e61e28
                              {% elif bl < 30 %} #e3464e
                              {% elif bl < 40 %} orange
                              {% elif bl < 50 %} #f0b93a
                              {% elif bl < 60 %} #f3f56c
                              {% elif bl < 70 %} #f2f536
                              {% elif bl < 80 %} #69f095
                              {% elif bl < 90 %} #2ee669
                              {% elif bl < 100 %} #05ad3b
                              {% elif bl == 100 %} #03872d
                              {% else %} grey
                              {% endif %}
                  primary: "{{ states('sensor.sm_f926u1_battery_level') }} %"
                  secondary: "{{ states('sensor.sm_f926u1_battery_temperature') }} Ā°"
                  tap_action:
                    action: more-info
                  fill_container: true
                  #icon: mdi:battery-arrow-down
          - type: custom:mushroom-template-card
            primary: >-
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %}
              John is here:
              {% else %}
              John is
              {% endif %}
            secondary: >-
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %}
              Location: {{ state_attr('sensor.john','street_number') }} {{
              state_attr('sensor.john','street') }}, {{
              state_attr('sensor.john','city') }}, {{
              state_attr('sensor.john','postal_code') }}
              {% else %}
              Driving...
              {% endif %}
            icon: |
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %} mdi:home-account
              {% else %} mdi:home-search
              {% endif %}
            icon_color: |
              {% if is_state('device_tracker.john_s_z_fold3', 'home') %} green
              {% else %} cyan
              {% endif %}
            multiline_secondary: true
3 Likes

This worked and has opened up another closet now for stuff to do lol.

Thanks again

martyn

1 Like

Mushroom template card questionā€¦ trying to get this working but no luck [tap_action part]. Is it possible?

Trying to get the map to popup to show my location

Thank you!

- type: custom:mushroom-template-card
            primary: >-
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %}
              John is here:
              {% else %}
              John is
              {% endif %}
            secondary: >-
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %}
              Location: {{ state_attr('sensor.john','street_number') }} {{
              state_attr('sensor.john','street') }}, {{
              state_attr('sensor.john','city') }}, {{
              state_attr('sensor.john','postal_code') }}
              {% else %}
              Driving...
              {% endif %}
            icon: |
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %} mdi:home-account
              {% else %} mdi:home-search
              {% endif %}
            icon_color: |
              {% if is_state('device_tracker.john_s_z_fold3', 'home') %} green
              {% else %} cyan
              {% endif %}
            tap_action:
              type: picture-elements
              entity: sensor.john
              image: >-
                {{ state_attr('sensor.john', 'map_link') }}

I donā€™t believe the tap_action can be templated.

1 Like

Ok Thank you!!! That answers the why it isnā€™t working :rofl:

Iā€™m wondering if any of the mushroom cards can be templatedā€¦

The template one can. :wink:
lovelace-mushroom/docs/cards at main Ā· piitaya/lovelace-mushroom Ā· GitHub details what attributes the cards can have and (normally) if they can be templated.

Youā€™ll notice, for example, that the title card says which attributes accept templates.

1 Like

Thank you!!! Now if I can a picture to popup on tap_action Iā€™d be happy.

Iā€™ve tried to add it to thisā€¦but no luckā€¦

 - type: custom:mushroom-template-card
            primary: >-
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %}
              John is here:
              {% else %}
              John is
              {% endif %}
            secondary: >-
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %}
              Location: {{ state_attr('sensor.john','street_number') }} {{
              state_attr('sensor.john','street') }}, {{
              state_attr('sensor.john','city') }}, {{
              state_attr('sensor.john','postal_code') }}
              {% else %}
              Driving...
              {% endif %}
            icon: |
              {% if (state_attr('sensor.john','direction_of_travel') == 'stationary') %} mdi:home-account
              {% else %} mdi:home-search
              {% endif %}
            icon_color: |
              {% if is_state('device_tracker.john_s_z_fold3', 'home') %} green
              {% else %} cyan
              {% endif %}
            tap_action:
              content: |
                {{ state_attr('sensor.john', 'map_link') }}
1 Like

If you wrap your card in config-template-card youā€™ll be able to template all parts of the card using JavaScript templates. Hierarchy will cause the mushroom-template-card to not see it as a template.

1 Like

are you sure?

in the post from Rhys ist works:

hello,
yes if have added the sensor.moon integration.

I can see the moon state.

But If I try your code:
type: custom:mushroom-chips-card
chips:

  • type: template
    card_mod:
    style: |
    ha-card {
    {% set phase = states(ā€˜sensor.moonā€™) %}
    ā€“chip-background: url( ā€˜/local/moon_phases/{{ phase }}.pngā€™ ) no-repeat center center;
    }
    I see only a black cicle

Hello,
I would like to put an titel on my dashboard, but only if one of many entities is on.

At the moment I have it with the following code:

type: custom:mushroom-title-card
title: |-
  {% set x = expand(
    'binary_sensor.flur_bewegungssensor_motion',  'binary_sensor.bad_bewegungssensor_motion',  'binary_sensor.kuche_bewegunssensor_motion', 'binary_sensor.schlafzimmer_bewegungssensor_motion', 'binary_sensor.homematicip_bewegungsmelder_innen'

    )
       | selectattr('state', 'eq', 'on')
       | map(attribute='name') | list %}
    {{  'Bewegung' if x | length > 0 else '' }}


The text ā€œBewegungā€ only displayed if one of the entities is on. That works. But if no entity is on, I get a placeholder displayed:

What code do I have to use so that the entire line is not displayed?

How can I remove the bottom gap in Title card?Screen Shot 2022-07-02 at 10.29.50 AM

I believe itā€™s configurable with a theme. Check your inspector.

I still canā€™t figure this one out. Not sure whatā€™s wrong with it.

You canā€™t use card-mod like that. You canā€™t mix the text and YAML shadow-rooting, youā€™re going to have to use YAML only. Also have you considered shortening the names, eg by removing the ā€œlightsā€ at the end?

I still strongly recommend shortening your names. Itā€™ll make your UI easier to parse. However:
You probably want something like

        style:
          .: |
            mushroom-shape-icon {
              --shape-color: none !important;
              --shape-color-disabled: none !important;
            }
            ha-card {
              --ha-card-background: transparent;
              --card-primary-font-size: 12px;
            }
          mushroom-card:
            mushroom-state-item 
              mushroom-state-info:
                $: |
                  .container .primary {
                    white-space: normal;
                  }
              .: |
                mushroom-state-item {
                  margin-bottom: 0px;
                }

Be careful with complex selector for css overriding. I can not guarantee this override will work with the future updates. :sweat_smile: Mushroom is not designed for that.

2 Likes

If you want a card to appear or disappear based on some status, the best route is to use the condition card: Conditional Card - Home Assistant Iā€™ve used all of the Mushroom cards and chips with conditions to keep my dashboard decluttered. Works well ā€¦ just sub in the code for the card you want after the conditions you set.

I had gaps and extra space at a few of my cards as I was doing stack-in-card things. I found that playing with the styling worked for me. Not sure if there are better options, but the below worked after trial and error on many other possible ways.

The ā€˜topā€™ command when applied to the second card in the stack can move that card up closer to the previous card. I used the ā€˜heightā€™ command to also shorten the second card a bit so it didnā€™t have as much trailing space at the bottom.

Make sure to adjust the spacing correctly to make sure the style goes to the correct card(s).

        style: |
          ha-card {
            top: -10px;
            height:5px !important;
          }
1 Like