Here you go:
type: custom:button-card
styles:
card:
- padding: 8px
- border-radius: 20px
grid:
- display: grid
- grid-template-columns: auto 1fr auto
- grid-template-rows: auto auto auto
- grid-template-areas: |
"picture entity battery"
"picture state travel"
custom_fields:
picture:
- grid-area: picture
- justify-self: start
- align-self: center
entity:
- grid-area: entity
- justify-self: start
- align-self: end
- text-align: left
- margin-left: 15px
state:
- grid-area: state
- justify-self: start
- align-self: start
- text-align: left
- margin-left: 15px
battery:
- grid-area: battery
- justify-self: center
- align-self: center
- text-align: left
- margin-left: 15px
travel:
- grid-area: travel
- justify-self: center
- align-self: center
- text-align: left
- margin-left: 15px
custom_fields:
picture: |
[[[
let state = states['person.your_person_entity'].state;
let borderColor = "gray";
if (state === "home") {
borderColor = "green";
} else if (state === "not_home") {
borderColor = "red";
} else {
borderColor = "orange";
}
return `<div style="position: relative; margin: 0; padding: 0; border: 3px solid ${borderColor}; border-radius: 50%; width: 40px; height: 40px; display: flex; justify-content: center; align-items: center;">
<img src="${states['person.your_person_entity'].attributes.entity_picture}" style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; margin: 0; padding: 0;">
</div>`;
]]]
entity: |
[[[
return `<div style="font-size: 12px; font-weight: bold; margin: 0; padding: 0; text-transform: uppercase;">
${states['person.your_person_entity'].attributes.friendly_name}
</div>`;
]]]
state: |
[[[
let state = states['person.your_person_entity'].state;
if (state === "home") {
state = "Home";
} else if (state === "not_home") {
state = "Away";
}
return `<div style="font-size: 10px; color: var(--secondary-text-color); margin: 0; padding: 0;">
${state}
</div>`;
]]]
battery: |
[[[
let battery = states['sensor.your_battery_level_sensor'].state;
let charging = states['sensor.your_battery_state_sensor'].state;
let color = "green";
if (battery < 10) {
color = "red";
} else if (battery < 30) {
color = "orange";
} else if (battery < 50) {
color = "yellow";
} else {
color = "green";
}
return `<div style="position: relative; font-size: 14px; color: var(--secondary-text-color); margin: 0; padding: 0;">
<svg width="30" height="30" viewBox="0 0 36 36" class="circular-chart">
<path class="circle-bg"
stroke="#eee"
stroke-width="2"
fill="none"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831" />
<path class="circle"
stroke="${color}"
stroke-width="2"
stroke-dasharray="${battery}, 100"
fill="none"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831" />
${
charging === "Charging"
? `<text x="18" y="24" class="percentage" style="fill:yellow; font-size: 16px; text-anchor: middle; animation: blink 2s infinite;">
⚡
</text>`
: `<text x="18" y="17" class="percentage" style="fill:#fff; font-size: 10px; text-anchor: middle;">${battery}</text>
<text x="18" y="26" class="percentage" style="fill:#fff; font-size: 8px; text-anchor: middle;">%</text>`
}
</svg>
<style>
@keyframes blink {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}
</style>
</div>`;
]]]
travel: |
[[[
let travel_time = states['sensor.your_travel_time_sensor'].state;
let color = "green";
let max_time = 60;
let percentage = Math.min((travel_time / max_time) * 100, 100);
if (travel_time >= 40) {
color = "red";
} else if (travel_time >= 20) {
color = "yellow";
} else {
color = "green";
}
return `<div style="font-size: 14px; color: var(--secondary-text-color); margin: 0; padding: 0;">
<svg width="30" height="30" viewBox="0 0 36 36" class="circular-chart">
<path class="circle-bg"
stroke="#eee"
stroke-width="2"
fill="none"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831" />
<path class="circle"
stroke="${color}"
stroke-width="2"
stroke-dasharray="${percentage}, 100"
fill="none"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831" />
<text x="18" y="17" class="percentage" style="fill:#fff; font-size: 10px; text-anchor: middle;">${travel_time}</text>
<text x="18" y="25" class="percentage" style="fill:#fff; font-size: 6px; text-anchor: middle;">min</text>
</svg>
</div>`;
]]]
3 Likes
DrewXT
(Andrew)
November 2, 2024, 4:15am
477
apologies if I’m bringing this post back from the dead, but would you have the code for your peope cards?
I’m particularly interested in being able to change the ringer mode remotely, as my wife is notorious for misplacing her phone with it in silent mode
MarkR
November 4, 2024, 9:27am
478
I’ve had the same person card for the last few years. It works but I like to freshen up a bit. In button card, is it possible to have things like battery/distance clickable? I can with my current one, so clock distance and tells you the address a person is at
Cheers
Old but not dead yet.
And yes, you use case was my use case aswell.
I don’t know if there’s an easier way but mine works as intended:
Here’s the code for the button:
type: custom:mushroom-template-card
primary: Ringer Mode
secondary: "{{ states('sensor.YOURMOBILE_ringer_mode') }}"
icon: "{{ state_attr('sensor.YOURMOBILE_ringer_mode', 'icon') }}"
entity: sensor.dennis_pixel_ringer_mode
icon_color: |-
{% if is_state('sensor.YOURMOBILE_ringer_mode', 'normal') %}
green
{% elif is_state('sensor.YOURMOBILE_ringer_mode', 'vibrate') %}
blue
{% elif is_state('sensor.YOURMOBILE_ringer_mode', 'silent') %}
yellow
{% endif %}
hold_action:
action: call-service
service: script.toggle_ringer_mode
target: {}
tap_action:
action: none
double_tap_action:
action: none
layout: horizontal
fill_container: false
multiline_secondary: false
And here’s code for the script I toggle with button:
alias: "[YOU] Toggle Ringer Mode "
sequence:
- data:
message: command_ringer_mode
data:
command: >-
{% if is_state('sensor.YOURMOBILE_ringer_mode', 'normal') %}
vibrate {% elif is_state('sensor.YOURMOBILE_ringer_mode',
'vibrate') %} silent {% elif
is_state('sensor.YOURMOBILE_ringer_mode', 'silent') %} normal {%
endif %}
action: notify.mobile_app_YOURMOBILE
mode: single
icon: mdi:phone-ring
And here you find the full documentation:
1 Like
DrewXT
(Andrew)
November 13, 2024, 10:59pm
480
Thanks mate - would you be able to share your YAML for one of the entire “people” cards as well?
Haven’t updated in a while but it’s still working.There you go:
type: horizontal-stack
cards:
- type: custom:stack-in-card
cards:
- type: custom:mushroom-person-card
entity: person.ME
use_entity_picture: true
layout: vertical
hold_action:
action: navigate
navigation_path: ME
hide_name: true
hide_state: true
fill_container: true
card_mod:
style: |
ha-card {
--ha-card-border-width: 0;
}
- type: custom:mushroom-chips-card
chips:
- type: template
content: |-
{% if is_state('person.ME', 'home') %}
zuhause
{% elif is_state('person.ME', 'not_home') %}
unterwegs
{% else %}
{{ states('person.ME') }}
{% endif %}
card_mod:
style: |
ha-card {
--chip-box-shadow: 0px 0px;
--text-color: #a6a6a6;
--chip-font-size: 12px;
--chip-border-width: 0
}
alignment: center
- type: custom:stack-in-card
cards:
- type: custom:mushroom-person-card
entity: person.HER
use_entity_picture: true
layout: vertical
hold_action:
action: navigate
navigation_path: HER
hide_name: true
hide_state: true
fill_container: true
card_mod:
style: |
ha-card {
--ha-card-border-width: 0;
}
- type: custom:mushroom-chips-card
chips:
- type: template
content: |-
{% if is_state('person.HER', 'home') %}
zuhause
{% elif is_state('person.HER', 'not_home') %}
unterwegs
{% else %}
{{ states('person.HER') }}
{% endif %}
card_mod:
style: |
ha-card {
--chip-box-shadow: 0px 0px;
--text-color: #a6a6a6;
--chip-font-size: 12px;
--chip-border-width: 0
}
alignment: center
And this is the target for my personal card:
- theme: Google Theme
title: ME
path: ME
icon: ''
badges: []
cards:
- type: custom:mushroom-chips-card
chips:
- type: back
- type: custom:mushroom-template-card
secondary: >-
{{ state_attr('sensor.ME_geocoded_location', 'thoroughfare')
}} {{ state_attr('sensor.ME_geocoded_location',
'sub_thoroughfare') }}, {{
state_attr('sensor.ME_geocoded_location', 'locality')
}}
entity: sensor.ME_geocoded_location
primary: Wo bin ich?
icon: mdi:map-marker
layout: horizontal
multiline_secondary: false
tap_action:
action: more-info
hold_action:
action: navigate
navigation_path: /map
- type: custom:mushroom-title-card
subtitle: Bedienung
- type: gauge
entity: sensor.ME_battery_level
name: Akku
theme: Google Theme
severity:
green: 75
yellow: 25
red: 0
needle: true
- type: horizontal-stack
cards:
- type: custom:mushroom-entity-card
entity: binary_sensor.ME_is_charging
name: Ladestatus
icon_color: amber
- type: custom:mushroom-template-card
primary: Ringer Mode
secondary: '{{ states(''sensor.ME_ringer_mode'') }}'
icon: '{{ state_attr(''sensor.ME_ringer_mode'', ''icon'') }}'
entity: sensor.ME_ringer_mode
icon_color: |-
{% if is_state('sensor.ME_ringer_mode', 'normal') %}
green
{% elif is_state('sensor.ME_ringer_mode', 'vibrate') %}
blue
{% elif is_state('sensor.ME_ringer_mode', 'silent') %}
yellow
{% endif %}
hold_action:
action: call-service
service: script.toggle_ringer_mode
target: {}
tap_action:
action: none
double_tap_action:
action: none
layout: horizontal
fill_container: false
multiline_secondary: false
- type: custom:mushroom-entity-card
tap_action:
action: call-service
service: script.find_my_phone
service_data: {}
target: {}
icon: mdi:cellphone-arrow-down-variant
hide_icon: false
entity: script.find_my_phone
name: Wo ist mein Handy?
icon_color: green
layout: horizontal
secondary_info: none
1 Like
DrewXT
(Andrew)
November 18, 2024, 10:56pm
482
many thanks - gives me something to work towards
1 Like
DameekGamer
(Dameek Gamer)
November 19, 2024, 9:14pm
483
I’ve been working on mine, with modifying some that I found here and there.
Most of it works great, but when I start spotify, I have to do a page refresh before it will start the marquee and change the picture to the headphones.
type: custom:button-card
entity: person.<USERNAME>
device: <DEVICENAME>
variables:
phone_battery_level_sensor: "[[[ return states[\"sensor.<DEVICENAME>_battery_level\"].state]]]"
phone_battery_state_sensor: "[[[ return states[\"sensor.<DEVICENAME>_battery_state\"].state]]]"
phone_wifi_sensor: "[[[ return states[\"sensor.<DEVICENAME>_wifi_connection\"].state]]]"
proximity_sensor: "[[[ return states[\"sensor.<DEVICENAME>_geocoded_location\"].state]]]"
avatar_normal: /local/<USER>-Smile.png
avatar_headphones: /local/<USER>-Smile+headphones.png
media_player_spotify: media_player.spotify_<SPOTIFYACCOUNT>
aspect_ratio: 2/1
name: Person
show_entity_picture: false
show_name: false
hold_action:
action: none
state:
- value: home
styles:
card:
- background-color: "#202124"
custom_fields:
icon:
- border-color: "#77c66e"
- value: not_home
styles:
card:
- background-color: "#202124"
custom_fields:
icon:
- border-color: deepskyblue
- value: Pizzeria
styles:
card:
- background-color: "#202124"
custom_fields:
icon:
- border-color: "#B83838"
styles:
card:
- background-color: "#202124"
- border-radius: 5%
- padding: 2% 5% 5% 5%
- color: gray
- font-size: 12px
- text-shadow: 0px 0px 0px black
- text-transform: capitalize
- justify-self: center
- align-content: center
grid:
- grid-template-areas: "\"icon status\" \"icon battery\" \"icon wifi\" \"icon proximity\""
- grid-template-columns: 1.5fr 1fr
- grid-template-rows: 1fr 1fr 1fr 1fr
- align-content: center
name:
- font-size: 15px
- align-self: middle
- justify-self: start
custom_fields:
icon:
- clip-path: circle()
- width: 80%
- pointer-events: none
- display: grid
- border: 5px solid
- border-color: "#808080"
- border-radius: 500px
- margin: 0 0 0 0
- opacity: 1
- align-self: center
- justify-self: center
status:
- justify-self: start
- color: gray
proximity:
- align-self: middle
- justify-self: start
- color: gray
wifi:
- justify-self: start
- color: gray
- "--text-wifi-color-sensor": >-
[[[ if (variables.phone_wifi_sensor == '<not connected>') return
"#aaaaaa"; ]]]
battery:
- align-self: middle
- justify-self: start
- color: gray
- "--text-color-sensor": >-
[[[ if (variables.phone_battery_level_sensor < 35) return "#EF4F1A";
]]]
media:
- align-self: right
- position: absolute
- bottom: 4%
- right: 4%
- left: 4%
- color: >-
[[[if (states[variables.media_player_spotify].state == "playing")
return "#000000"; else return "#ffffff00"; ]]]
custom_fields:
icon: >
[[[
if (states[variables.media_player_spotify].state =='playing')
{
return entity === undefined ? null : `<img
src=${variables.avatar_headphones} width="100%">`; } else { return entity
=== undefined ? null : `<img
src="${states[entity.entity_id].attributes.entity_picture}" width="100%">`;
} ]]]
status: |
[[[
if (entity.state =='not_home') {
return `<ha-icon icon="mdi:home-export-outline"
style="width: 20px; height: 20px; color: '#888888';">
</ha-icon><span> On the way</span>`;
}
if (entity.state =='home') {
return `<ha-icon
icon="mdi:home"
style="width: 20px; height: 20px; color: 888888;">
</ha-icon><span> ${entity.state}</span>`;
} else {
if (entity.state =='[YOUR OTHER LOCATION]') {
return `<ha-icon icon="mdi:pizza"
style="width: 20px; height: 20px; color: '#888888';">
</ha-icon><span> ${entity.state}</span>`;
}
else{
return `<ha-icon
icon="mdi:map-marker-radius"
style="width: 20px; height: 20px; color: 888888;">
</ha-icon><span> ${entity.state}</span>`;
}
}
]]]
battery: |
[[[
if (variables.phone_battery_state_sensor =='charging') {
return `<ha-icon
icon="mdi:battery-charging-medium"
style="width: 20px; height: 20px; color: #888888;">
</ha-icon> <span><span style="color: var(--text-color-sensor);">${variables.phone_battery_level_sensor}% Battery</span></span>`;
} else {
return `<ha-icon
icon="mdi:battery-medium"
style="width: 20px; height: 20px; color: #888888;">
</ha-icon> <span><span style="color: var(--text-color-sensor);">${variables.phone_battery_level_sensor}% Battery</span></span>`;
}
]]]
wifi: |
[[[
if (variables.phone_wifi_sensor.state =='<not connected>') {
return `<ha-icon
icon="mdi:wifi"
style="width: 20px; height: 20px; color: var(--text-wifi-color-sensor);">
</ha-icon> <span><span style="color: var(--text-wifi-color-sensor);">Disconnected</span></span>`;
} else {
return `<ha-icon
icon="mdi:wifi"
style="width: 20px; height: 20px; color: #888888;">
</ha-icon> <span><span style="color: var(--text-color-sensor);">${variables.phone_wifi_sensor}</span></span>`;
}
]]]
media: |
[[[
if (states[variables.media_player_spotify].state =='playing') {
return `<marquee> <ha-icon
icon="mdi:music"
style="width: 20px; height: 20px;"></ha-icon
<span> ${states[variables.media_player_spotify].attributes.media_title}
- ${states[variables.media_player_spotify].attributes.media_artist} </marquee>`
} else {
}
]]]
DameekGamer
(Dameek Gamer)
November 19, 2024, 9:15pm
484
For some reason, when it changes the picture to the headphones one, it is a different size. Any suggestions?
probably a resolution thing, did you check the 2 pictures to be of exact same proportions?
as for the marquee
did you check the empty ‘else’ here? thats never a good thing.
you could try and set the triggers_update
entity list to include that player entity explicitly
btw, marquee tag is long deprecated and support may vary among browser. advice is to move to Javascript translateX() see translateX() - CSS: Cascading Style Sheets | MDN
1 Like
DameekGamer
(Dameek Gamer)
November 20, 2024, 2:56pm
486
@Mariusthvdb thanks for the info, I’ll take a look into that.