Fun with custom:button-card

Think I solved it!

don’t know if it is the best way, but this seems to work:

type: custom:button-card
entity: sensor.envy_inspire_7200e_all_in_one_printer_series_192_168_20_21_toestand
hold_action:
  action: navigate
  navigation_path: /lovelace/info
name: HP Printer
icon: mdi:printer-outline
color_type: card
show_state: true
show_entity_picture: true
custom_fields:
  Number:
    card:
      type: custom:button-card
      entity: sensor.hp_printer_pages_total_remaining
      tap_action:
        action: none
      show_name: false
      show_state: true
      show_icon: false
      show_entity_picture: false
      color_type: card
      color: rgba(255,255,255,0.8)
      styles:
        card:
          - width: 50px
          - height: 25px
          - padding: 0px 2px 0px 2px
          - font-size: 14px
          - text-transform: capitalize
          - font-family: Sans-serif
          - color: rgba(62, 62, 62, 1.0)
          - background-color: rgba(255,255,255,0.8)
          - border-color: "#d9d9d9"
          - background: |
              [[[ 
                if (states['sensor.hp_printer_pages_total_remaining'].state == '0') return 'rgba(247,22,46,0.8)';
              ]]]  
        state:
          - color: |
              [[[
                if (states['sensor.hp_printer_pages_total_remaining'].state >= '11') return 'rgba(62, 62, 62, 1.0)';
                if (states['sensor.hp_printer_pages_total_remaining'].state >= 5 && states['sensor.hp_printer_pages_total_remaining'].state < 11) return 'rgba(241,104,12,0.8)';
                if (states['sensor.hp_printer_pages_total_remaining'].state >= 1 && states['sensor.hp_printer_pages_total_remaining'].state < 5) return 'rgba(247,22,46,0.8)';
                if (states['sensor.hp_printer_pages_total_remaining'].state == '0') return 'rgba(62, 62, 62, 1.0)';
                else return 'white';
              ]]]
styles:
  card:
    - width: 155px
    - height: 155px
    - margin: 0px
  name:
    - display: block
    - position: absolute
    - bottom: 21px
    - left: 8px
    - font-weight: bold
    - font-size: 16px
    - font-family: Sans-serif
  img_cell:
    - margin: 0px
    - padding: 0px
  state:
    - display: block
    - position: absolute
    - bottom: 5px
    - left: 12px
    - font-color: rgba(255, 0, 0, 0.8)
    - font-size: 14px
    - font-family: Sans-serif
    - text-transform: capitalize
  icon:
    - width: 110px
    - margin: 0px 0px 1px 0px
  custom_fields:
    Number:
      - display: block
      - position: absolute
      - top: 8px
      - right: 8px
      - overflow: hidden
state:
  - value: "on"
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/hp_printer_icon-136.png?v=1
  - value: ready
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/hp_printer_envy_icon_136.png?v=1
  - value: scanprocessing
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/hp_printer_envy_icon_136.png?v=1
  - value: copying
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/hp_printer_envy_icon_136.png?v=1
  - value: processing
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/hp_printer_envy_icon_136.png?v=1
  - value: inpowersave
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/hp_printer_envy_icon_136.png?v=1

Now i would like to do the same with a custom_field without a entity sensor.

But the same code does not work here

type: custom:button-card
entity: sensor.electricity_meter_actief_tarief
name: Energie Meter
icon: mdi:counter
color_type: card
show_state: true
show_entity_picture: true
custom_fields:
  ConsumptionW: |
    [[[
      return `
        <ha-card style="width: 75px; height: 25px; padding: 0px 2px 0px 2px;
          color: rgba(62, 62, 62, 1.0); background-color: rgba(255,255,255,0.8); border-color: #d9d9d9;
          font-size: 14px; text-transform: capitalize; font-family: Sans-serif;">
          <span>${states['sensor.electricity_meter_energieverbruik_w'].state} W</span>
        </ha-card>`
    ]]]
    styles:
        state:
          - color: |
              [[[
                if (states['sensor.electricity_meter_energieverbruik_w'].state >= '2000') return 'rgba(62, 62, 62, 1.0)';
                if (states['sensor.electricity_meter_energieverbruik_w'].state >= 1000 && states['sensor.hp_printer_pages_total_remaining'].state < 2000) return 'rgba(241,104,12,0.8)';
                else return 'white';
              ]]]
styles:
  card:
    - width: 155px
    - height: 155px
    - margin: "-345px 5px 5px 5px"
  name:
    - display: block
    - position: absolute
    - bottom: 21px
    - left: 8px
    - font-weight: bold
    - font-size: 16px
    - font-family: Sans-serif
  img_cell:
    - margin: 0px
    - padding: 0px
  state:
    - display: block
    - position: absolute
    - bottom: 5px
    - left: 12px
    - font-size: 14px
    - font-family: Sans-serif
    - text-transform: capitalize
  icon:
    - width: 40px
    - margin: 0px 0px 5px 0px
  custom_fields:
    ConsumptionW:
      - display: block
      - position: absolute
      - top: 8px
      - right: 8px
      - overflow: hidden
state:
  - value: normal
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/slimmemeter_slimmelezer_icon_136.png?v=1
  - value: low
    color: rgba(241,233,233,0.6)
    entity_picture: /local/pictures/entities/device/slimmemeter_slimmelezer_icon_136.png?v=1
  - value: unavailable
    color: rgba(65,65,63,0.8)
    entity_picture: /local/pictures/entities/error_icon_136.png?v=1
    styles:
      card:
        - filter: opacity(50%)
      img_cell:
        - margin: 0px
        - padding: 0px
      icon:
        - width: 70px
        - margin: 0px 0px 10px 0px
  - value: unknown
    color: rgba(65,65,63,0.8)
    entity_picture: /local/pictures/entities/question_icon_136.png?v=1
    styles:
      card:
        - filter: opacity(50%)
      img_cell:
        - margin: 0px
        - padding: 0px
      icon:
        - width: 70px
        - margin: 0px 0px 10px 0px

1 Like

Circle to “square”.

Does someone maybe know how i can make a square field like this:
52c39e250f5b8f666f59b193088e77b66383ce5e

From this code:

custom_fields:
  Round: |
    [[[
        var fill = 'rgba(255,255,255,0.8)';
        const radius = 20.5;
        return `
          <svg viewBox="0 0 50 50">
            <circle cx="25" cy="25" r="${radius}"
              stroke="#d9d9d9" stroke-width="2" fill="${fill}"
          </svg>`;
    ]]]

79301d08f145836c8874f98dbc86fedfc7ab3c7d

const fill = 'rgba(255,255,255,0.8)';
const width = 40;
const height = 30;
const x = 5; 
const y = 10; 
const borderRadius = 5; 
return `
  <svg viewBox="0 0 50 50">
    <rect x="${x}" y="${y}" width="${width}" height="${height}" 
      rx="${borderRadius}" ry="${borderRadius}"
      stroke="#d9d9d9" stroke-width="2" fill="${fill}" />
  </svg>`;
2 Likes

Thank you!!

This is how far I got:

  Round: |
    [[[
        const fill = 'rgba(255,255,255,0.8)';
        const radius = 12; 
        return `
          <svg viewBox="0 0 100 100">
            <rect x="8" y="8" width="80px" height="25px" 
              rx="12" ry="12"
              stroke="#d9d9d9" stroke-width="2" fill="${fill}" />
          </svg>`;
    ]]]
 
  Percentage: |
    [[[
        {var percentage = Math.round(states['sensor.afzuigkap_programma_voortgang'].state/1.00);
        var rgb = (entity.state === 'on')
                ? entity.attributes.rgb_color : '211,211,211';
        var rgba = 'rgba(' + rgb + ',0.2)';
        var fill = (entity.attributes.rgb_color) ? rgba : 'rgba(255,255,255,0.8)';
        const radius = 12.0;
        const circumference = radius * 2 * Math.PI;
        return `
          <svg viewBox="0 0 100 100">
            <rect x="8" y="8" width="80px" height="25px"
              rx="12" ry="12"
              stroke="green" stroke-width="2" fill="${fill}"
              style="transform: rotate(0deg);transform-origin: 50% 50%;
              stroke-dasharray: ${circumference};
              stroke-dashoffset: ${circumference - percentage / 100 * circumference};" />
            <text x="50%" y="23%" fill="var(--text-color-on)" font-size="15" font-weight= "normal"
              text-anchor="middle" alignment-baseline="middle">
              ${states['sensor.afzuigkap_programma_voortgang'].state}<tspan font-size="15" alignment-baseline="middle">%</tspan>
            </text>
          </svg>`;}
    ]]]

style:

  custom_fields:
    Round:
      - position: absolute
      - right: 0px
      - top: 0px
      - width: 70px
      - overflow: hidden
    Percentage:
      - position: absolute
      - right: 0px
      - top: 0px
      - width: 70px
      - overflow: hidden
      - z-index: 1

But the text is no longer in the middle, it does not fit anymore.
Times also not correct.Sorry I never worked with this ‘language’

timer

  - type: custom:button-card
    show_state: false
    show_name: false
    show_icon: false
    entity: input_number.cover_position
    aspect_ratio: 1/1
    custom_fields:
      rect: >
        [[[
          const fill = 'rgba(255,255,255,0.8)';
          const width = 40;
          const height = 30;
          const x = 5;
          const y = 10;
          const borderRadius = 5;
          const strokeColor = '#4caf50'; // Color for the filled part
          const strokeBgColor = '#d9d9d9'; // Background stroke color
          const textColor = '#333'; // Text color
          const dashArray = 2 * (width + height); // Total stroke length
          const value = Math.abs(entity.state);
          const dashOffset = dashArray * (1 - value / 100); 

          return `
            <svg viewBox="0 0 50 50">
              <!-- Background stroke -->
              <rect x="${x}" y="${y}" width="${width}" height="${height}"
                rx="${borderRadius}" ry="${borderRadius}"
                stroke="${strokeBgColor}" stroke-width="2" fill="${fill}" />
              <!-- Foreground stroke (colored part) -->
              <rect x="${x}" y="${y}" width="${width}" height="${height}"
                rx="${borderRadius}" ry="${borderRadius}"
                stroke="${strokeColor}" stroke-width="2" fill="none"
                stroke-dasharray="${dashArray}" stroke-dashoffset="${dashOffset}" />
              <!-- Text value in the middle -->
              <text x="25" y="25" fill="${textColor}" font-size="14" text-anchor="middle" dominant-baseline="middle">
                ${value}%
              </text>
            </svg>`;
        ]]]
    styles:
      custom_fields:
        rect:
          - position: absolute
          - top: 8px
          - right: 8px
          - width: 30%
          - height: auto

adjust the values to your needs…

2025-01-14 04.38.38

3 Likes

Thank you very much! :smiley:

Hi Everybody,
I think I tried everything but I struggle with mini-graph styling inside custom:button-card. I want to have my mini-graph background transparent in my button-card but I can’t achieve it. I’m ready to listen everyone and try everything because I’m on it for a week now. Thank for your time.
In my Dashboard, I have 3 cards :

  • 1st one is a mini-graph with transparent background : :white_check_mark:
  • 2nd one is a button-card with a mini-graph inside :red_circle:
  • 3rd one is a button_card_template and model has the same config as the second one :red_circle:
    Here is my card.
button_card_templates:
  room:
    custom_fields:
      graph:
        card:
          type: custom:mini-graph-card
          entities:
            - entity: sensor.thermometre_buanderie_temperature
            - entity: sensor.thermometre_buanderie_humidite
              y_axis: secondary
          card_mod: 
            style: |
              ha-card {
                --ha-card-background: rgba(50,50,50,0.1);
                border: none;
              }
    styles:
      card:
        - background-color: '#AA4787'
views:
  - title: Home
    sections:
      - type: grid
        cards:
          - type: custom:mini-graph-card
            entities:
              - sensor.thermometre_buanderie_temperature
            card_mod: 
              style: |
                ha-card {
                  --ha-card-background: rgba(50,50,50,0.1);
                  border: none;
                }
          - type: custom:button-card
            entity: sensor.lumieres_salon_count
            custom_fields:
              graph:
                card:
                  type: custom:mini-graph-card
                  entities:
                    - entity: sensor.thermometre_buanderie_temperature
                    - entity: sensor.thermometre_buanderie_humidite
                      y_axis: secondary
                  style: |
                    ha-card {
                      --ha-card-background: rgba(50,50,50,0.1);
                      background: #68957D;
                      color: black;
                      box-shadow: none;
                      border: none;
                    }
                    .header, .states, ha-icon {
                      color: white;
                    }
            styles:
              card:
                - background-color: '#AA4787'
          - type: custom:button-card
            entity: sensor.lumieres_salon_count
            template: room
    background:
      opacity: 33
      alignment: center
      size: cover
      repeat: repeat
      attachment: fixed
      image: /api/image/serve/64be908f395d615a7f3e29afd1bf76c7/original
    cards: []

Have everything working now :slight_smile:
One more question, is it also possible to style the color depending on the state of %?
Like:

if entity.name_of_entity >= 0 {
  const strokeColor = 'red';
}else if entity.name_of_entity >= 25 {
  const strokeColor = 'orange';
}else if entity.name_of_entity >= 50 {
  const strokeColor = 'green';
}

I tried the if and els after the ‘const’ and before the ‘return’, but it did not work.

First else needs to be an elif, and need an endif at the end after the else.

1 Like
1 Like

So i need to change it to a VAR.

This seems to work:

    [[[ 
      const fill = 'rgba(255,255,255,0.7)';
      const bgColor = '#d9d9d9';
      var bgActiveColor = '#4caf50';
      const width = 60;
      const height = 26;
      const dashArray = 2 * (width + height); // Total stroke length
      const value = Math.abs(states['sensor.kia_sportage_gt_ev_battery_level'].state);
      const dashOffset = dashArray * (1 - value / 100); 

    if (entity.state === 'home') {
      var bgActiveColor = '#000';
    } 
    else if (entity.state === 'home2') {
      var bgActiveColor = '#100';
    }
    
      return `

:smiley:

You can use it more simply like this…

  const colorMap = {
    'home': '#000',
    'home2': '#100',
  };

  let bgActiveColor = colorMap[entity.state] || '#4caf50'; // use default color if state is not in colorMap
  const state = states['senor.some_sensor'].state;
  let stateColor;
  if (state >= 75) {
    stateColor = '#FF5722'; // Highest priority
  } else if (state >= 45) {
    stateColor = '#FFEB3B';
  } else if (state >= 35) {
    stateColor = '#8BC34A';
  } else if (state >= 1) {
    stateColor = '#4CAF50';
  } else {
    stateColor = '#000000'; // Default color if no condition is met
  }
1 Like

or create a dedicated template sensor in HA, and use the state of that sensor entity.
that way you can easily use it everywhere you want to have that same color (eg in card-mod)

it’s by far the easiest way to do things like this, without blowing those configs out of proportion

example Is it possible to change header card icon based on entity state? - #10 by Mariusthvdb
check volgende_afval_kleur

1 Like

Thanks a lot both!

I now have this for my battery charging sensors:

custom_fields:
  RectP: |
    [[[ 
      const state = states['sensor.kia_sportage_gt_ev_battery_level'].state;
      let bgActiveColor;
        if (state >= 65) {
          bgActiveColor = '#00ae5b';
        } else if (state >= 25) {
          bgActiveColor = '#ff9532';
        } else if (state >= 0) {
          bgActiveColor = '#ff3e3e';
        } else {
          bgActiveColor = '#d9d9d9';
        }
      const fill = 'rgba(255,255,255,0.7)';
      const bgColor = '#d9d9d9';
      const width = 60;
      const height = 26;
      const dashArray = 2 * (width + height); // Total stroke length
      const value = Math.abs(states['sensor.kia_sportage_gt_ev_battery_level'].state);
      const dashOffset = dashArray * (1 - value / 100); 

      return `
      <svg viewBox="0 0 75 75">
        <rect x="8" y="8" width="${width}" height="${height}"
          rx="12" ry="12"
          stroke="${bgColor}" stroke-width="1" fill="${fill}" />
        <rect x="8" y="8" width="${width}" height="${height}"
          rx="12" ry="12"
          stroke="${bgActiveColor}" stroke-width="2" fill="none"
          stroke-dasharray="${dashArray}" stroke-dashoffset="${dashOffset}" />
        <text x="38" y="23" fill="rgba(62, 62, 62, 1.0);" 
          font-weight="normal" font-size="16" font-family="Sans-serif" 
          text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle">
          ${value}%
        </text>
      </svg>`;
    ]]]
  custom_fields:
    RectP:
      - position: absolute
      - top: 2px
      - right: 1px
      - width: 40%
      - height: auto

charging

Sounds easier to adapt in the cards.

You mean to create a template sensor that has the color settings in the template (amount % is color… )
and use that sensor in the card? but than i have to link that template sensor to the state of the sensor i use in the card.

            state-display {
              color: {{states('sensor.volgende_afval_kleur')}};
              text-transform: capitalize

have to put card_mod inside button_card in my case.

There is one “problem” with the active stroke, it is already full around 85%
I think that is because the start of the active border is not in the middle (but on the left) of the rect?

image

custom_fields:
  RectP: |
    [[[ 
      const state = states['sensor.afzuigkap_programma_voortgang'].state;
      let bgActiveColor;
        if (state >= 90) {
          bgActiveColor = '#00ae5b';
        } else if (state >= 50) {
          bgActiveColor = '#ffbe3e';
        } else if (state >= 25) {
          bgActiveColor = '#ff9532';
        } else if (state >= 0) {
          bgActiveColor = '#ff3e3e';
        } else {
          bgActiveColor = 'rgba(217,217,217,0.1)';
        }
      const value = Math.abs(states['sensor.afzuigkap_programma_voortgang'].state);
      const fill = 'rgba(255,255,255,0.7)';
      const bgColor = '#d9d9d9';
      const width = 60;
      const height = 26;
      const dashArray = 2 * (width + height);
      const dashOffset = dashArray * (1 - value / 100); 

      return `
      <svg viewBox="0 0 75 75">
        <rect x="8" y="8" width="${width}" height="${height}"
          rx="12" ry="12"
          stroke="${bgColor}" stroke-width="1" fill="${fill}" />
        <rect x="8" y="8" width="${width}" height="${height}"
          rx="12" ry="12"
          stroke="${bgActiveColor}" stroke-width="2" fill="none"
          stroke-dasharray="${dashArray}" stroke-dashoffset="${dashOffset}" />
        <text x="38" y="23" fill="rgba(62, 62, 62, 1.0);" 
          font-weight="normal" font-size="16" font-family="Sans-serif" 
          text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle">
          ${value}%
        </text>
      </svg>`;
    ]]]

no, not at all. you can use that same entity in the javascript .

seems to me you are way over your head here, creating difficult configs, while not understanding things.
simply c&p stuff we make for you wont help you in the long run

please educate yourself step by step, and make progress doing so.

playing with entities across the board in the various configurations is basic and required knowledge you should grasp first.

1 Like

Because you manipulate the border radius, the total stroke length is cut off…

const dashArray = 2 * ((width - 6) + (height - 5))
1 Like

This is partly true, I had an education in HTML, PHP and learned some GML(gamemaker) when i was 15 years.
I never did Javascript. I now made a lot of templates etc for HA now. I can say for my doing i run an “advanced” home assistant server now.
Starting with the help of the forum here and now I can do much more myself.
However, shit happens, and that made it very hard for me to learn total new things again.

So I am very great full for the help and things others can edit or explain to me in the community here. I learn to edit and change things and use this to make own new things again. I simply can not write new things from scratch again. But bit by bit i still make my HA the way i would like it :slight_smile: