My Custom Cards for Minimalist UI

These are amazing and your work is greatly appreciated.

I can’t wait for your wiki. I can’t figure out the template crap. I have minimalist installed and using it and mushroom cards, but don’t know where to put the code for your cards. Somewhat of a newb without some UI help.

I was inspired by the look as well and modified my button cards a while back. No confusing templates


All the icons trigger different cards below and use color change or animation based on states. These 2 button cards alone tell me just about everything going on at one glance

3 Likes

i have started work on the wikiin dev, see here for now. more to come.

1 Like

Looks grate, glad you where inspired, this is what the community is all about. How are you doing your animations, are you using SVG or card-mod ?

here an axample of mine

garage-door_animation:
  variables:
    timeout: "[[[ return Date.now() - Date.parse(entity.last_changed); ]]]"
  # triggers_update: "all"
  show_icon: false
  custom_fields:
    icon: >
      [[[
        let path = `
        <path d="M22 9V20H20V11H4V20H2V9L12 5L22 9M19 12H5V14H19V12M19 18H5V20H19V18M19 15H5V17H19V15Z" />
        `,
        style = `
          <svg viewBox="0 0 24 24">
            <style>
              @keyframes door_open {
                0% { clip-path: inset(0 0 0 0); }
                25%  { clip-path: polygon(0 0, 100% 0, 100% 100%, 85% 100%, 85% 83%, 15% 83%, 14% 100%, 0 100%); }
                50%  { clip-path: polygon(0 0, 100% 0, 100% 100%, 85% 100%, 85% 61%, 15% 61%, 14% 100%, 0 100%); }
                75% { clip-path: polygon(0 0, 100% 0, 100% 100%, 85% 100%, 85% 45%, 15% 45%, 14% 100%, 0 100%); }
              }
              @keyframes door_close {
                0% { clip-path: polygon(0 0, 100% 0, 100% 100%, 85% 100%, 85% 45%, 15% 45%, 14% 100%, 0 100%); }
                25%  { clip-path: polygon(0 0, 100% 0, 100% 100%, 85% 100%, 85% 61%, 15% 61%, 14% 100%, 0 100%); }
                50%  { clip-path: polygon(0 0, 100% 0, 100% 100%, 85% 100%, 86% 83%, 15% 83%, 14% 100%, 0 100%); }
                75% { clip-path: inset(0 0 0 0); }
              }
              .start {
                animation: door_open 3s steps(1);
              }
              .on {
                clip-path: polygon(0 0, 0 100%, 10% 100%, 10% 45%, 85% 45%, 85% 100%, 100% 100%, 100% 0);
              }
              .end {
                animation: door_close 3s steps(1);
              }
              .start_timeout {
                clip-path: polygon(0 0, 0 100%, 10% 100%, 10% 45%, 85% 45%, 85% 100%, 100% 100%, 100% 0);
              }
              .end_timeout {
                transform-origin: center;
                will-change: transform;
              }
            </style>
        `;
        if (entity.state === 'open' && variables.timeout < -1000) {
          return `${style}<g class="start">${path}</g></svg>`;
        }
        if (entity.state === 'closed' && variables.timeout < 1000) {
          return `${style}<g class="end">${path}</g></svg>`;
        }
        if (entity.state === 'open' ) {
          return `${style}<g class="start_timeout">${path}</g></svg>`;
        } else {
          return `${style}<g class="end_timeout">${path}</g></svg>`;
        }
      ]]]

    img_cell: "[[[  return `<svg viewBox='0 0 24 24'><ellipse stroke='none' fill='none'></ellipse></svg>`; ]]]"

Well tbh I’m not doing much other than basic fan spin and vacuum . I mainly just use color states to give me an idea, like I know a window is open when it yellow then I can press and see all my windows. Etc. Animations can be distracting or not necessarily as not staring at the dash all the time. Had these button layouts before mushrooms and your sweet designs came around, I just liked the circle icon background look.

I have just merged the latest cards to the main git.

documents are here

hi guys,

I have been working on adding support for custom popups (requires browser_mod) for my Status Card

you can do stuff like.

yaml code for main card

  - type: custom:button-card
    entity: sensor.security_state
    template:
      - custom_card_andyblac_status
    variables:
      button:
        popup_content: !include popup.yaml
        templates: 
          - custom_popup_andyblac_status

yaml code for popup card, just call the named yaml file.

type: vertical-stack
cards:
  - type: horizontal-stack
    cards:
      - type: tile
        entity: alarm_control_panel.house_alarm
        vertical: true
        features:
          - type: alarm-modes
            modes:
              - armed_away
              - disarmed
      - type: tile
        entity: alarm_control_panel.garage_alarm
        vertical: true
        features:
          - type: alarm-modes
            modes:
              - armed_away
              - disarmed
  - type: tile
    entity: cover.roller_door
    vertical: true
    features:
      - type: cover-open-close
  - type: horizontal-stack
    cards:
      - type: tile
        entity: binary_sensor.garage_door
        vertical: true
        features:
          - type: cover-open-close
        color: red
      - type: horizontal-stack
        cards:
          - type: tile
            entity: binary_sensor.back_door
            vertical: true
            color: red
      - type: horizontal-stack
        cards:
          - type: tile
            entity: binary_sensor.front_door
            vertical: true
            color: red

Man, I am dying to get these cards working, but still have not figured it out. Forgive my ignorance, I’m still pretty new to this.

What else do I need to do besides drop your card’s yaml files in the folder and reboot?

I have them like this for example:
/config/ui_lovelace_minimalist/custom_cards/custom_card_andyblac_scene.yaml

I still get template not found error when I try to add a card, so I am missing a step.

hi,

place the folder structure like /config/ui_lovelace_minimalist/custom_cards/custom_card_andyblac_room/custom_card_andyblac_room.yaml then go to developer tools and restart UI Lovelace Minimalist

Appreciate the help. I changed the file structure and still getting the same template error. I dont know anything about templates, are they located in the card’s yaml file, or do I need to add them somewhere else?


99 Problems 1

it looks like you have not installed all the required frontend integrations for Lovelace UI Minimalist,

goto to HACS → frontend and install these:

button-card
lovelace-card-mod
mini-graph-card
mini-media-player
my-cards-slider-card
light-entity-card
auto-entities
simple-weather-card

i assume you have isnatlled Lovelace UI minimalist too ?

got popup working with my template sensors

template and instructions added to dev branch git.

if you guys are interested in my template sensors, I can post them here.

Thank you for making these. They look great. Any thoughts on adding different colors for on devices?

Hi,

Thanks, for the sensor icon you can do with the following variable ulm_custom_card_andyblac_room_sensor_color_on

docs are here.

and for the entity icon color see here

Yeah, that’d be great too.

reworked them, see below

1 Like

custom_templates/tools.jinja

{% macro list_entities(type, device_class='', state='off', select='', reject='', area='', exclude_area='') %}
{% set ns = namespace(sensors=[]) %}
{% if device_class and area %}
  {% for entity in type | selectattr('attributes.device_class', 'eq', device_class) | selectattr('entity_id', 'in', area_entities(area)) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif device_class %}
  {% for entity in type | selectattr('attributes.device_class', 'eq', device_class) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif area and reject %}
  {% for entity in type | selectattr('entity_id', 'in', area_entities(area)) | rejectattr('entity_id', 'search', reject) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif area and select %}
  {% for entity in type | selectattr('entity_id', 'in', area_entities(area)) | selectattr('entity_id', 'match', select) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif area %}
  {% for entity in type | selectattr('entity_id', 'in', area_entities(area)) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif exclude_area and reject %}
  {% for entity in type | rejectattr('entity_id', 'in', area_entities(exclude_area)) | rejectattr('entity_id', 'search', reject) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif exclude_area %}
  {% for entity in type | rejectattr('entity_id', 'in', area_entities(exclude_area)) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif select and reject %}
  {% for entity in type | selectattr('entity_id', 'match', select) | rejectattr('entity_id', 'search', reject) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif select %}
  {% for entity in type | selectattr('entity_id', 'match', select) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% elif reject %}
  {% for entity in type | rejectattr('entity_id', 'search', reject) | selectattr('state','eq',state) %}
    {% set ns.sensors = ns.sensors + [dict(entity_id = entity.entity_id, name = entity.name, state = entity.state)] %}
  {% endfor %}
{% endif %}
{{ ns.sensors | to_json }}
{% endmacro %}

{% macro count_entities(type, device_class='', state='off', select='', reject='', area='', exclude_area='') %}
{% from 'tools.jinja' import list_entities %}
{{ list_entities(type,device_class,state,select,reject,area,exclude_area) | from_json | count }}
{% endmacro %}

Batttery Template sensor

    - name: "Devices with low battery"
      unique_id: e9da96dc-aa51-47c1-8a6d-435de1ce5149
      attributes:
        navigation: batteries
        entities: >
          {% set ns = namespace(sensors=[]) %}
          {% set ignore_entities = ['sensor.andys_iphone_battery_level','sensor.andys_iphone_icloudv3_battery','sensor.christines_iphone_battery_level','sensor.christines_iphone_icloudv3_battery','sensor.ipad_battery_level','sensor.mums_ipad_battery_level'] %}
          {% set battery_level = 55 %}
          {% for state in states | selectattr('attributes.device_class', 'eq', 'battery') | rejectattr('entity_id', 'in', ignore_entities) %}
            {% if 0 <= state.state | int(-1) <= battery_level | int %}
              {% set ns.sensors = ns.sensors + [dict(entity_id = state.entity_id, name = state.name | replace(' battery', '') | replace(' Battery', ''), state = state.state | int)] %}
            {% endif %}
          {% endfor %}
          {% set low_batteries = ns.sensors | sort (attribute='state') %}
          {{ low_batteries }}
      state: "{{ this.attributes.entities | count }}"
      icon: >
        {% if this.state not in ['unavailable','unknown'] %}
          {% if this.state | int > 0 %}
            mdi:battery-alert
          {% else %}
            mdi:battery
          {% endif %}
        {% else %}
          mdi:battery
        {% endif %}

Lights on

   - name: "Number of Lights On"
      unique_id: 3b279d97-e05a-4c8b-9368-2ce58d7fd46c
      attributes:
        navigation: lights
        label: >
          {% if this.state not in ['unavailable','unknown'] %}
            {% if this.state | int > 0 %}
            {{ this.state }} On
            {% else %}
            All Off
            {% endif %}
          {% else %}
          All Off
          {% endif %}
        entities: >
          {% from 'tools.jinja' import list_entities %}
          {{ list_entities(states.light,exclude_area='groups',state='on') }}
        count: >
          {% from 'tools.jinja' import count_entities %}
          {% set ns = namespace(entities=[]) %}
          {% for s in states.light | map(attribute='entity_id') | map('area_name') | unique | reject('none') | list %}
            {% set ns.entities = ns.entities + [ (s, count_entities(states.light,state='on',area=s,exclude_area='groups') | from_json )] %}
          {% endfor %}
          {{ dict.from_keys(ns.entities) }}
      state: "{{ this.attributes.entities | count }}"
      icon: >
        {% if this.state not in ['unavailable','unknown'] %}
          {% if this.state | int > 0 %}
          mdi:lightbulb-group
          {% else %}
          mdi:lightbulb-group-outline
          {% endif %}
        {% else %}
        mdi:lightbulb-group-outline
        {% endif %}

Doors Open

    - name: "Number of Doors Open"
      unique_id: 905cf252-7adb-4b68-b696-ae089d96b11f
      attributes:
        navigation: doors
        label: >
          {% if this.state not in ['unavailable','unknown'] %}
            {% if this.state | int > 0 %}
            {{ this.state }} Open
            {% else %}
            All Closed
            {% endif %}
          {% else %}
          All Closed
          {% endif %}
        entities: >
          {% from 'tools.jinja' import list_entities %}
          {{ list_entities(states.binary_sensor,device_class='door',state='on') }}
        count: >
          {% from 'tools.jinja' import count_entities %}
          {% set ns = namespace(entities=[]) %}
          {% for s in states.binary_sensor | map(attribute='entity_id') | map('area_name') | unique | reject('none') | list %}
            {% set ns.entities = ns.entities + [ (s, count_entities(states.binary_sensor,device_class='door',state='on',area=s) | from_json )] %}
          {% endfor %}
          {{ dict.from_keys(ns.entities) }}
      state: "{{ this.attributes.entities | count }}"
      icon: >
        {% if this.state not in ['unavailable','unknown'] %}
          {% if this.state | int > 0 %}
          mdi:door-open
          {% else %}
          mdi:door
          {% endif %}
        {% else %}
        mdi:door
        {% endif %}

Sockets on

    - name: "Number of Sockets On"
      unique_id: c838cee8-1919-4000-8fc0-d6587433e6fc
      attributes:
        navigation: sockets
        label: >
          {% if this.state not in ['unavailable','unknown'] %}
            {% if this.state | int > 0 %}
            {{ this.state }} On
            {% else %}
            All Off
            {% endif %}
          {% else %}
          All Off
          {% endif %}
        entities: >
          {% from 'tools.jinja' import list_entities %}
          {{ list_entities(states.switch,device_class='outlet',state='on') }}
        count: >
          {% from 'tools.jinja' import count_entities %}
          {% set ns = namespace(entities=[]) %}
          {% for s in states.switch | map(attribute='entity_id') | map('area_name') | unique | reject('none') | list %}
            {% set ns.entities = ns.entities + [ (s, count_entities(states.switch,device_class='outlet',state='on',area=s) | from_json )] %}
          {% endfor %}
          {{ dict.from_keys(ns.entities) }}
      state: "{{ this.attributes.entities | count }}"
      icon: mdi:power-socket-uk

Motion Detected

    - name: "Number of Motion Detected"
      unique_id: 156e99a5-cdb6-4d6b-9bea-5e05d5a3c548
      attributes:
        navigation: motion-sensors
        label: >
          {% if this.state not in ['unavailable','unknown'] %}
            {% if this.state | int > 0 %}
            {{ this.state }} Detected
            {% else %}
            All Clear
            {% endif %}
          {% else %}
          All Clear
          {% endif %}
        entities: >
          {% from 'tools.jinja' import list_entities %}
          {{ list_entities(states.binary_sensor,device_class='motion',state='on') }}
        count: >
          {% from 'tools.jinja' import count_entities %}
          {% set ns = namespace(entities=[]) %}
          {% for s in states.binary_sensor | map(attribute='entity_id') | map('area_name') | unique | reject('none') | list %}
            {% set ns.entities = ns.entities + [ (s, count_entities(states.binary_sensor,device_class='motion',state='on',area=s) | from_json )] %}
          {% endfor %}
          {{ dict.from_keys(ns.entities) }}
      state: "{{ this.attributes.entities | count }}"
      icon: mdi:motion-sensor

for sidebar

 - type: horizontal-stack
    cards:
      - type: custom:button-card
        entity: sensor.number_of_lights_on
        template:
          - custom_card_andyblac_count_info
          - custom_popup_andyblac_tap
        variables:
          ulm_custom_card_andyblac_count_info_color_on: yellow
          popup_title: "Lights"
          popup_content: !include popups/lights.yaml
          # hold_action:
          #   action: navigate
      - type: custom:button-card
        entity: sensor.number_of_sockets_on
        template:
          - custom_card_andyblac_count_info
          - custom_popup_andyblac_tap
        variables:
          ulm_custom_card_andyblac_count_info_color_on: blue
          popup_title: "Sockets"
          popup_content: !include popups/sockets.yaml
          # hold_action:
          #   action: navigate
      - type: custom:button-card
        entity: sensor.number_of_doors_open
        template:
          - custom_card_andyblac_count_info
          - custom_popup_andyblac_tap
        variables:
          ulm_custom_card_andyblac_count_info_color_on: blue
          popup_title: "Doors"
          popup_content: !include popups/doors.yaml
      - type: custom:button-card
        entity: sensor.number_of_motion_detected
        template:
          - custom_card_andyblac_count_info
          - custom_popup_andyblac_tap
        variables:
          ulm_custom_card_andyblac_count_info_color_on: blue
          popup_title: "Motion"
          popup_content: !include popups/motion.yaml
      - type: custom:button-card
        entity: sensor.devices_with_low_battery
        template:
          - custom_card_andyblac_count_info
          - custom_popup_andyblac_tap
        variables:
          ulm_custom_card_andyblac_count_info_color_on: blue
          popup_title: "Low Batteries"
          popup_content: !include popups/battery.yaml

for individual room

  - type: custom:mushroom-chips-card
    view_layout:
      grid-area: header
    chips:
      - type: back
      - type: entity
        entity: binary_sensor.office_door_contact
        content_info: none
        tap_action:
          action: more-info
      - type: entity
        entity: sensor.wiser_lts_temperature_office
      - type: template
        icon: mdi:power-socket-uk
        content: "{{ state_attr('sensor.number_of_sockets_on', 'count')['Office'] }}"
      - type: template
        icon: mdi:lightbulb
        content: "{{ state_attr('sensor.number_of_lights_on', 'count')['Office'] }}"

I love these room cards - it’s great that they’re so colourful. Any chance you could post your code?