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

Yes.


type: custom:stack-in-card
cards:
  - type: custom:mushroom-template-card
    primary: Laundry Motion
    secondary: '{{''{0:,.0f}''.format(states(entity)|int)}} %'
    icon: >
      {% set battery_level = (states(entity) | int / 10) | round(0) | int * 10
      %}

      {% if battery_level == 100 %}
        mdi:battery
      {% elif battery_level > 0 %}
        mdi:battery-{{ battery_level }}
      {% else %}
        mdi:battery-alert-variant-outline
      {% endif %}
    entity: sensor.motion_sensor_battery_level
    icon_color: |-
      {% set battery_level = states(entity) | int %}
      {% if battery_level > 90 %} 
        green
      {% elif battery_level > 60 %}
        light-green
      {% elif battery_level > 50 %}
        lime
      {% elif battery_level > 40 %}
        yellow
      {% elif battery_level > 30 %}
        amber
      {% elif battery_level > 20 %}
        orange
      {% elif battery_level > 10 %}
        deep-orange
      {% else %}
        red
      {% endif %}
    tap_action:
      action: more-info
    fill_container: true
    card_mod:
      style: |
        :host {
          --mush-icon-size: 76px;
          height: 66px;
          margin-left: -20px !important;
        }
        ha-card {
          box-shadow: none;
          --card-primary-font-size: 12px;
          --card-secondary-font-size: 20px;
        }

2 Likes

No, this is for logged in users so they can either see a different view or a different action
So the question remains, can a template be modified to process different actions

hold_action:
  action: {%if user=='Joe'%}more-info{%else%}none{%endif%}

@SpookyAwol
What I would do is to disable hold action, and add a chip if Joe is logged in with the same entity, and enable action on that.

Looks like you have not installed card-mod.

How do you add a chip only if Joe is logged in?
So far the only option Ive found is State Switch

Templating this way works:

double_tap_action:
  action: none
badge_icon: |-
  {% if is_state('person.joe','home') %}
  mdi:home
  {%else%}
  mdi:home-import-outline
  {%endif%}

But not this?

double_tap_action:
  action:  |-
     {% if user=='Joe' %}
     none
     {%else%}
     more-info
     {%endif%}
badge_icon: |-
  {% if is_state('person.joe','home') %}
  mdi:home
  {%else%}
  mdi:home-import-outline
  {%endif%}
As per docs, not a function of template card, so will use state change

You can stop it going transparent by adding a background to the shadow host:

    :host {
      background: var(--card-background-color);
      border-radius: var(--ha-card-border-radius);
    }

This is it added to my room card:

background

type: custom:stack-in-card
cards:
  - type: custom:mushroom-template-card
    primary: Lounge
    secondary: '{{ states("sensor.lounge_sensor_temperature") | round(0) }} Ā°C'
    icon: mdi:sofa
    entity: light.lounge_light
    tap_action:
      action: navigate
      navigation_path: lounge
    hold_action:
      action: toggle
    icon_color: '{{ ''red'' if is_state(entity, ''on'') else ''disabled'' }}'
    fill_container: true
    layout: horizontal
    multiline_secondary: false
    card_mod:
      style: |
        :host([dark-mode]) {
          background: rgba(var(--rgb-primary-background-color), 0.2);
        } 
        :host {
          background: rgba(var(--rgb-primary-text-color), 0.025);
          --mush-icon-size: 76px;
          height: 66px;
          margin-left: -18px !important;
        }
  - type: custom:mushroom-chips-card
    chips:
      - type: conditional
        conditions:
          - entity: binary_sensor.lounge_motion_occupancy
            state: 'on'
        chip:
          type: template
          icon_color: disabled
          icon: mdi:motion-sensor
          tap_action:
            action: none
          hold_action:
            action: none
      - type: conditional
        conditions:
          - entity: media_player.lounge_tv
            state_not: 'off'
          - entity: media_player.lounge_tv
            state_not: unavailable
        chip:
          type: template
          icon_color: disabled
          icon: |-
            {% set media_type = state_attr('media_player.lounge_tv',
            'media_content_type') %}
            {% if media_type == 'tvshow' %}
              mdi:television-classic
            {% elif media_type == 'movie' %}
              mdi:movie-open
            {% elif media_type == 'music' %}
              mdi:music
            {% elif media_type == 'playlist' %}
              mdi:music
            {% else %}
              mdi:plex
            {% endif %}
          tap_action:
            action: none
          hold_action:
            action: none
      - type: conditional
        conditions:
          - entity: climate.air_conditioner
            state_not: 'off'
        chip:
          type: template
          entity: climate.air_conditioner
          icon_color: disabled
          icon: |-
            {% if is_state(entity, 'heat_cool') %}
              mdi:sync 
            {% elif is_state(entity, 'heat') %}
              mdi:fire
            {% elif is_state(entity, 'cool') %}
              mdi:snowflake
            {% elif is_state(entity, 'dry') %}
              mdi:water-percent
            {% elif is_state(entity, 'fan_only') %}
              mdi:fan
            {% else %}
              mdi:air-conditioner
            {% endif %}
          tap_action:
            action: none
          hold_action:
            action: none
          card_mod:
            style: |
              @keyframes rotation {
                0% {
                  transform: rotate(0deg);
                }
                100% {
                  transform: rotate(360deg);
                }
              }
              ha-card {
                {% if is_state('climate.air_conditioner', 'fan_only') %}
                   animation: rotation 2s linear infinite;
                {% endif %}
              }
      - type: conditional
        conditions:
          - entity: group.lounge_windows
            state: 'on'
        chip:
          type: template
          icon_color: disabled
          icon: mdi:window-open
          tap_action:
            action: none
          hold_action:
            action: none
    alignment: end
    card_mod:
      style: |
        ha-card {
          --chip-box-shadow: none;
          --chip-background: none;
          --chip-spacing: 0;
        }
card_mod:
  style: |
    ha-card {
      height: 102px;
      {% if is_state('light.lounge_light', 'on') %}
        background: rgba(244, 67, 54, 0.1);
      {% endif %}
    }
    :host {
      background: var(--card-background-color);
      border-radius: var(--ha-card-border-radius);
    }
9 Likes

Yes, like this:

type: custom:mushroom-template-card
primary: Pretty Mushrooms
icon: mdi:mushroom
icon_color: red
card_mod:
  style: |
    ha-card {
      background: url( '/local/mushroom.png' ) center no-repeat;
      background-size: cover;
    }

This may make the text a bit hard to see, so we can blend it like this:

type: custom:mushroom-template-card
primary: Pretty Mushrooms
icon: mdi:mushroom
icon_color: red
card_mod:
  style: |
    ha-card {
      background: rgba(var(--rgb-card-background-color), 0.7) url( '/local/mushroom.png' ) center no-repeat;
      background-size: cover;
      background-blend-mode: overlay;
    }
4 Likes

Aha, I have not! Then I will do that and try again.
Many thanks for your replay.

/Thekholm

1 Like

If anyone is looking for a way to add a pulse effect to their cards to indicate something is on or charging etc, heres a quick way:

style: |-
  {% if is_state("switch.something", "on") %}
  mushroom-shape-icon {
    display: flex;
    border-radius: 50%;
    animation: pulse-black 2s infinite;
  }
    
  @keyframes pulse-black {
    0% {
      box-shadow: 0 0 0 0 rgb(var(--rgb-orange), 0.7);
    }
    
    70% {
      box-shadow: 0 0 0 10px rgba(var(--rgb-orange), 0);
    }
    
    100% {
      box-shadow: 0 0 0 0 rgba(var(--rgb-orange), 0);
    }
  }
  {% endif %}

There is probably a better way to do this but itā€™s what I made work. Maybe the author could include a custom CSS box for each card so we donā€™t need to add styles manually.

7 Likes

Wow, so nice. Could you also do this to a vertical/hor stack?

Yes, the CSS can be applied to most cards.

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