It’s quite a collection of separate pieces of code But let me see if I can get all of them in here:
You need:
- Custom Button Card
- Custom Stack in Card
- Card Mod
The cards in the sidebar:
cards:
- type: custom:stack-in-card
mode: horizontal
style: |
ha-card {
background: none;
border: none;
box-shadow: none;
bottom: 0;
}
cards:
# MARCIANO
- type: custom:button-card
entity: person.marciano
triggers_update:
- sensor.marciano_last_changed
double_tap_action: !include ../popup/marciano.yaml
variables:
retain: sensor.marciano_last_changed
battery: sensor.s22u_battery_level
batt_s: sensor.s22u_battery_state
template:
- person_alt
# BERTA
- type: custom:button-card
entity: person.berta
triggers_update:
- sensor.berta_last_changed
double_tap_action: !include ../popup/berta.yaml
variables:
retain: sensor.berta_last_changed
battery: sensor.berta_phone_battery_level
batt_s: sensor.berta_phone_battery_state
template:
- person_alt
POPUP:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Marciano
card_mod:
style:
#popup header
.:
style: >
--popup-max-width: 400px;
content:
type: vertical-stack
cards:
- type: entities
card_mod:
class: content
entities:
- entity: person.marciano
secondary_info: last-changed
name: Marciano
- type: history-graph
card_mod:
style: |
ha-card > div {
padding: 0 2em 1em 1.6em !important;
}
entities:
- entity: person.marciano
name: Marciano
- type: glance
card_mod:
style: |
ha-card > div {
padding: 1em 1.5em 0.2em 1em !important;
box-sizing: content-box;
}
show_state: false
entities:
- entity: device_tracker.s22u
name: Router
icon: mdi:wifi
card_mod:
style: &state |
state-badge {
color: {{ is_state(config.entity, 'home') | iif('#3182b7', '#3c3f3f') }};
}
- entity: device_tracker.s22u
name: Bluetooth
icon: mdi:bluetooth
card_mod:
style: *state
- entity: device_tracker.s22u
name: Position
icon: cil:iphone-modern
card_mod:
style: *state
- type: custom:mod-card
card_mod:
style:
hui-horizontal-stack-card$: |
#root {
justify-content: space-evenly !important;
padding: var(--tablet-popup-button-padding);
}
card:
type: horizontal-stack
cards:
- type: custom:button-card
name: Play sound on phone
icon: mdi:volume-high
template: icon_name
tap_action:
action: call-service
service: notify.mobile_app_s22u
service_data:
title: Find my phone
message: Here I am!
data:
push:
sound:
name: findmy.wav
critical: 1
volume: 1
- type: map
default_zoom: 16
dark_mode: true
entities:
- device_tracker.s22u
card_mod:
style:
.: |
#root {
height: 25em;
padding-bottom: 0 !important;
}
ha-icon-button {
color: var(--primary-color);
zoom: 140%;
margin-left: -0.2em;
}
ha-card {
border-top: 2px solid #1a1a1a;
border-radius: 0;
transition: none;
margin-bottom: -4px !important;
height: 25em !important;
}
ha-map$: |
#map {
background-color: #191919 !important;
}
.leaflet-control-attribution {
display: none;
}
.leaflet-bar a {
background-color: rgba(115, 123, 124, 0.2) !important;
color: #9da0a2 !important;
backdrop-filter: blur(0.25em);
zoom: 140%;
}
a.leaflet-control-zoom-in {
border-bottom: 1px solid #181818 !important;
}
.leaflet-pane.leaflet-tile-pane {
filter: invert(0.95) grayscale(0.95) contrast(95%);
}
Templates:
person_alt.yaml:
There is a “triggers_update” in here which is overridden in the card. You could hardcode it in here instead.
---
person_alt:
template:
- dark-base
state_display: >
[[[
if (entity) {
return variables.state === 'home'
? variables.translate_home
: variables.state === 'not_home'
? variables.translate_not_home
: variables.state;
}
return variables.translate_unknown;
]]]
show_state: false
show_name: false
triggers_update: sensor.time
tap_action:
action: none
styles:
grid:
- grid-template-areas: |
"si"
"icon"
"bi"
- grid-template-columns: 1fr
- grid-template-rows: auto
- gap: 1.3%
- align-items: center
- will-change: transform
card:
- padding: 1em
- box-shadow: none
- background-color: none
- position: relative
name:
- z-index: 998
- position: absolute
- top: -5rem
- text-shadow: 0 4px 3px rgba(0,0,0,1)
- justify-self: center
- font-size: 1.5em
- font-family: "var(--secondary-font-family)"
- padding: 0 .3em 0 .3em
state:
- justify-self: start
- font-size: .8em
- align-self: center
- font-family: "var(--primary-font-family)"
- text-transform: uppercase
custom_fields:
icon:
- z-index: 0
- clip-path: circle()
- width: 125%
- pointer-events: none
- display: grid
- justify-self: center
- border: none
- border-radius: 50%
- border-color: >
[[[
return variables.state === 'home' || variables.state === 'Home'
? '#89b455'
: '#693633';
]]]
- margin-bottom: .5em
bi:
- justify-self: center
- font-size: 1rem
- font-family: Raleway, sans-serif
si:
- position: fixed
- top: -.1em
- right: -1rem
- font-size: 1rem
- clip-path: circle()
- padding: .3rem
- pointer-events: none
- border: none
- display: grid
- justify-self: center
- border-radius: 50%
- background-color: >
[[[
return variables.state === 'home' || variables.state === 'Home'
? '#89b455'
: '#693633';
]]]
custom_fields:
icon: >
[[[
return entity && variables.entity_picture
? `<img src="${variables.entity_picture}" width="100%">`
: null;
]]]
bi: >
[[[
let batt_s = states[variables.batt_s].state
if (entity) {
return batt_s === 'charging' || batt_s === 'Charging' || batt_s === 'full' || batt_s === 'Full'
? `⚡ ${states[variables.battery].state}%`
: batt_s === 'discharging' || batt_s === 'Not Charging'
? `🔋 ${states[variables.battery].state}%`
: `❓ ${states[variables.battery].state}%`;
}
return variables.translate_unknown;
]]]
si: >
[[[
if (entity) {
return variables.state === 'home' || variables.state === 'Home'
? `🏠`
: variables.state === 'not_home'
? "❌"
: variables.state === 'work'
? "🏢"
: variables.state;
}
return variables.translate_unknown;
]]]
dark_base.yaml (adjusted from matt’s base.yaml):
dark-base:
template:
- settings
variables:
state_on: >
[[[ return ['on', 'home', 'cool', 'fan_only', 'playing', 'unlocked'].indexOf(!entity || entity.state) !== -1; ]]]
state: >
[[[ return !entity || entity.state; ]]]
entity_id: >
[[[ return !entity || entity.entity_id; ]]]
entity_picture: >
[[[ return !entity || entity.attributes.entity_picture; ]]]
timeout: >
[[[ return !entity || Date.now() - Date.parse(entity.last_changed); ]]]
show_state: true
show_icon: false
state_display: >
[[[ if (variables.state === true) return variables.translate_unknown; ]]]
tap_action:
ui_sound_tablet: |
[[[
let screensaver = states[variables.entity_tablet] === undefined ||
states[variables.entity_tablet].state;
if (variables.state === 'off' && screensaver === 'off') {
hass.callService('media_player', 'play_media', {
entity_id: variables.entity_browser_mod,
media_content_id: '/local/sound/on.m4a',
media_content_type: 'music'
});
}
if (variables.state_on && screensaver === 'off') {
hass.callService('media_player', 'play_media', {
entity_id: variables.entity_browser_mod,
media_content_id: '/local/sound/off.m4a',
media_content_type: 'music'
});
}
]]]
card_bounce: |
[[[
// add animation
if (this.getElementsByTagName("style").length === 0) {
// phone condition
let mq = window.matchMedia('(max-width: 800px)').matches;
let style = document.createElement('style');
style.innerHTML = `
@keyframes card_bounce {
0% { transform: scale(1); }
10% { transform: scale(${ mq ? '0.92' : '0.94' }); }
25% { transform: scale(1); }
30% { transform: scale(${ mq ? '0.96' : '0.98' }); }
100% { transform: scale(1); }
}
`;
this.appendChild(style);
}
// duration
let duration = 800;
// animate
this.style.animation = `card_bounce ${duration}ms cubic-bezier(0.22, 1, 0.36, 1)`;
// reset
window.setTimeout(() => { this.style.animation = "none"; }, duration + 100)
]]]
action: toggle
haptic: medium
double_tap_action:
haptic: success
hold_action:
action: block
styles:
grid:
- grid-template-areas: |
"icon circle"
"n n"
"s s"
- grid-template-columns: .5fr auto
- grid-template-rows: auto
- gap: 0%
- align-items: start
- will-change: transform
name:
- justify-self: start
- line-height: 119%
state:
- justify-self: start
- line-height: 102%
card:
- border-radius: var(--button-card-border-radius)
- border-width: 0
- -webkit-tap-highlight-color: rgba(0,0,0,0)
- transition: none
- --mdc-ripple-color: >
[[[
return variables.state_on
? '#97989c'
: 'rgb(0, 0, 0)';
]]]
- color: >
[[[
return variables.state_on
? 'var(--primary-text-color)'
: 'var(--secondary-text-color)';
]]]
- background-color: >
[[[
return variables.state_on
? 'rgba(255, 255, 255, 0.85)'
: 'rgba(115, 115, 115, 0.25)';
]]]
settings.yaml (again adjusted from matt’s settings.yaml):
You might be able to go without this as the translation isn’t really necessary when you stay in English as I did…
settings:
variables:
entity_tablet: switch.galaxy_tab_a_screensaver
entity_browser_mod: media_player.LenTab
translate_unknown: Unknown
translate_idle: Idle
translate_home: Home
translate_not_home: Not Home
translate_available: Available
translate_no_updates: No Updates
translate_update_available: Update available
translate_updates_available: Updates available
translate_armed_home: Armed - Home
translate_armed_away: Armed - Away
translate_arming: Arming
translate_disarmed: Disarmed
translate_pending: Pending
translate_triggered: TRIGGERED