From 972cbf58d6a408258c114987f6fa40375930d969 Mon Sep 17 00:00:00 2001 From: AnasHost <41167157+Anashost@users.noreply.github.com> Date: Tue, 6 Oct 2026 15:57:34 +0200 Subject: [PATCH] Update print statement from 'Hello' to 'Goodbye' --- collections/batch6.md | 1429 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1429 insertions(+) diff --git a/collections/batch6.md b/collections/batch6.md index e69de29..8a3eb9a 100644 --- a/collections/batch6.md +++ b/collections/batch6.md @@ -0,0 +1,1429 @@ + +[![Revolut.Me][revolut_me_shield]][revolut_me] +[![PayPal.Me][paypal_me_shield]][paypal_me] +[![ko_fi][ko_fi_shield]][ko_fi_me] +[![buymecoffee][buy_me_coffee_shield]][buy_me_coffee_me] +[![patreon][patreon_shield]][patreon_me] + + + +
+ + + +
+ +# Home Assistant [Batch 6](https://youtu.be/RZncjsCWjTw) Collection. + +Other collections? watch these YouTube videos for more cards and instructions: +[Batch 1](https://youtu.be/5vYz37AqSO4) | [Batch 2](https://youtu.be/izx0JMrnhWE) | [Batch 3](https://youtu.be/SrFbC1ae35E) | [Batch 4](https://youtu.be/avAg9CR9TRc) | [Batch 5](https://youtu.be/5k6DfaymBZE) + +
+ +> [!NOTE] +> If you are using the **Sections** view type, you may need to set `rows` to around `1.5` for the card, +> otherwise the card may appear compressed. +> +> ```yaml +> grid_options: +> rows: 1.5 +> ``` + +
+ +# Cards: + +665270527-ae6cccdf-0a74-4f4f-b61f-e893fa04d808 + + +
+Presence sensor card + +```yaml +type: custom:button-card +entity: binary_sensor.aqara_presence_fp300_presence +name: Living Room +show_state: false +show_label: true +show_icon: false +variables: + distance: sensor.aqara_presence_fp300_target_distance + show_distance: true + range: number.aqara_presence_fp300_detection_range + show_range: true + max_supported_limit: 6 + zone_steps: 24 + track_button: button.aqara_presence_fp300_track_target_distance + show_track_button: true + temp: sensor.aqara_presence_fp300_temperature + humidity: sensor.aqara_presence_fp300_humidity + lux: sensor.aqara_presence_fp300_illuminance + show_environment: true + temp_low: 18 + temp_mid: 23 + temp_high: 27 + hum_low: 30 + hum_high: 60 + lux_min: 50 + lux_max: 400 + size_shape: 75px + size_card_height: 125px + font_primary: 15px + font_secondary: 12px + font_badge: 10px +styles: + card: + - --config-shape-size: '[[[ return variables.size_shape ]]]' + - --config-card-height: > + [[[ return variables.show_range !== false ? variables.size_card_height : + '99px'; ]]] + - --config-font-primary: '[[[ return variables.font_primary ]]]' + - --config-font-secondary: '[[[ return variables.font_secondary ]]]' + - --config-font-badge: '[[[ return variables.font_badge ]]]' + - height: var(--config-card-height) !important + - padding: 0px !important + - overflow: hidden + - position: relative + grid: + - padding: 12px 16px + - height: 100% + - box-sizing: border-box + - grid-template-areas: '"radar n" "radar l"' + - grid-template-columns: var(--config-shape-size) 1fr + - grid-template-rows: auto auto + - align-content: start + - gap: 0px 14px + - position: relative + - z-index: 2 + name: + - justify-self: start + - font-size: var(--config-font-primary) + - font-weight: 500 + - align-self: end + - margin-bottom: 2px + - position: relative + - color: var(--primary-text-color) + label: + - justify-self: start + - font-size: var(--config-font-secondary) + - opacity: 0.7 + - align-self: start + - margin-top: 2px + - position: relative + - color: var(--secondary-text-color) + custom_fields: + radar: + - grid-area: radar + - justify-self: start + - width: var(--config-shape-size) + - height: var(--config-shape-size) + - border-radius: 50% + - border: 1px solid rgba(128, 128, 128, 0.15) + - background: rgba(128, 128, 128, 0.05) + - position: relative + - overflow: hidden + - box-shadow: inset 0 2px 8px rgba(0,0,0,0.1) + badge1: + - position: absolute + - top: 12px + - right: | + [[[ + let btn_valid = variables.show_track_button !== false && variables.track_button && states[variables.track_button] && states[variables.track_button].state !== 'unknown' && states[variables.track_button].state !== 'unavailable'; + return btn_valid ? '46px' : '12px'; + ]]] + - transition: right 0.3s ease-out + - padding: 4px 10px + - font-size: var(--config-font-badge) + - letter-spacing: 0.5px + - white-space: nowrap + - font-weight: 600 + - text-transform: uppercase + - z-index: 5 + badge2: + - position: absolute + - top: 45px + - right: 12px + - padding: 4px 10px + - font-size: var(--config-font-badge) + - letter-spacing: 0.5px + - white-space: nowrap + - opacity: 0.9 + - font-weight: 500 + - z-index: 5 + track_button: + - position: absolute + - top: 11px + - right: 12px + - z-index: 10 + - display: | + [[[ + let btn_valid = variables.show_track_button !== false && variables.track_button && states[variables.track_button] && states[variables.track_button].state !== 'unknown' && states[variables.track_button].state !== 'unavailable'; + return btn_valid ? 'block' : 'none'; + ]]] + zone_map: + - position: absolute + - bottom: 0 + - left: 0 + - width: 100% + - height: 42px + - z-index: 1 +tap_action: + action: more-info +label: | + [[[ + if (!entity) return 'Entity Setup Required'; + + let range_valid = variables.show_range !== false && variables.range && states[variables.range] && states[variables.range].state !== 'unknown' && states[variables.range].state !== 'unavailable'; + if (!range_valid) return '\u00A0'; + + let max_l = parseFloat(variables.max_supported_limit) || 6.0; + let bm = parseInt(states[variables.range].state); + let highest_zone = -1; + if (!isNaN(bm)) { + for(let i=23; i>=0; i--) { if((bm & (1<= 0 ? (highest_zone + 1) * 0.25 : max_l; + return `Zone Limit: ${limit.toFixed(1)}m`; + ]]] +custom_fields: + badge1: ' ' + badge2: ' ' + track_button: + card: + type: custom:button-card + entity: '[[[ return variables.track_button ]]]' + icon: mdi:crosshairs-gps + show_name: false + show_state: false + styles: + card: + - width: 26px + - height: 26px + - border-radius: 50% + - background: rgba(128, 128, 128, 0.1) + - border: 1px solid rgba(128, 128, 128, 0.2) + - box-shadow: 0 2px 4px rgba(0,0,0,0.1) + - display: flex + icon: + - width: 16px + - color: var(--primary-text-color) + tap_action: + action: call-service + service: button.press + service_data: + entity_id: '[[[ return variables.track_button ]]]' + radar: | + [[[ + let is_on = entity && entity.state === 'on'; + + let dist_valid = variables.show_distance !== false && variables.distance && states[variables.distance] && states[variables.distance].state !== 'unknown' && states[variables.distance].state !== 'unavailable'; + let safe_dist = dist_valid ? parseFloat(states[variables.distance].state) : 0; + + let range_valid = variables.show_range !== false && variables.range && states[variables.range] && states[variables.range].state !== 'unknown' && states[variables.range].state !== 'unavailable'; + let bm = range_valid ? parseInt(states[variables.range].state) : 0; + + let max_r = parseFloat(variables.max_supported_limit) || 6.0; + let highest_zone = -1; + if (range_valid && !isNaN(bm)) { + for(let i=23; i>=0; i--) { if((bm & (1<= 0 ? (highest_zone + 1) * 0.25 : max_r) : max_r; + + if (safe_dist > max_r) safe_dist = max_r; + + let raw_zone = Math.floor(safe_dist / 0.25); + let is_zone_valid = range_valid ? ((bm & (1 << raw_zone)) !== 0) : true; + + let max_svg = 47.5; + let range_pct = (range_val / max_r) * max_svg; + let dist_pct = dist_valid ? ((safe_dist / max_r) * max_svg) : 0; + + let c_rgb = is_on ? '0, 229, 255' : '158, 158, 158'; + let t_rgb = is_zone_valid ? c_rgb : '255, 82, 82'; + let stroke_color = 'rgba(128,128,128,0.2)'; + + return ` + + + + + + + + + + ${is_on && dist_valid ? ` + + + ` : ''} + + + + ${is_on ? ` +
+
+
+ ` : ''} + `; + ]]] + zone_map: | + [[[ + let range_valid = variables.show_range !== false && variables.range && states[variables.range] && states[variables.range].state !== 'unknown' && states[variables.range].state !== 'unavailable'; + if (!range_valid) return ''; + + let is_on = entity && entity.state === 'on'; + + let dist_valid = variables.show_distance !== false && variables.distance && states[variables.distance] && states[variables.distance].state !== 'unknown' && states[variables.distance].state !== 'unavailable'; + let safe_dist = dist_valid ? parseFloat(states[variables.distance].state) : 0; + + let bm = parseInt(states[variables.range].state); + if(isNaN(bm)) bm = 0; + + let max_r = parseFloat(variables.max_supported_limit) || 6.0; + let visual_steps = parseInt(variables.zone_steps) || 12; + + safe_dist = Math.max(0, Math.min(safe_dist, max_r - 0.001)); + let step_size = max_r / visual_steps; + let tracked_visual_step = Math.floor(safe_dist / step_size); + + let total_raw_zones = Math.ceil(max_r / 0.25); + let raw_per_step = total_raw_zones / visual_steps; + let visual_array = Array(visual_steps).fill(false); + + for(let i=0; i= 0 && v_idx < visual_steps) visual_array[v_idx] = true; + } + } + + let zone_bars = `
`; + + for(let i=0; i
`; + } + zone_bars += ``; + + let l1 = (max_r * 0.25).toFixed(1) + 'm'; + let l2 = (max_r * 0.50).toFixed(1) + 'm'; + let l3 = (max_r * 0.75).toFixed(1) + 'm'; + let l4 = max_r.toFixed(0) + 'm'; + + let labels = `
+ 0m${l1}${l2}${l3}${l4} +
`; + + return `
${labels}${zone_bars}
`; + ]]] +extra_styles: | + [[[ + let is_on = entity && entity.state === 'on'; + + let dist_valid = variables.show_distance !== false && variables.distance && states[variables.distance] && states[variables.distance].state !== 'unknown' && states[variables.distance].state !== 'unavailable' && !isNaN(parseFloat(states[variables.distance].state)); + let safe_dist = dist_valid ? parseFloat(states[variables.distance].state) : 0; + if (safe_dist > variables.max_supported_limit) safe_dist = variables.max_supported_limit; + + let range_valid = variables.show_range !== false && variables.range && states[variables.range] && states[variables.range].state !== 'unknown' && states[variables.range].state !== 'unavailable' && !isNaN(parseInt(states[variables.range].state)); + let bm = range_valid ? parseInt(states[variables.range].state) : 0; + + let raw_zone = Math.floor(safe_dist / 0.25); + let is_zone_valid = range_valid ? ((bm & (1 << raw_zone)) !== 0) : true; + + let status_text = 'CLEAR'; + if (!entity) { + status_text = 'SETUP REQ'; + } else if (is_on) { + if (dist_valid) { + status_text = `PRESENCE • ${safe_dist.toFixed(1)}m`; + } else { + status_text = 'PRESENCE'; + } + } + + let color = is_on ? (is_zone_valid ? '0, 229, 255' : '255, 82, 82') : '158, 158, 158'; + + let env_parts = []; + let c_temp = '128, 128, 128'; + let c_hum = '128, 128, 128'; + let c_lux = '128, 128, 128'; + + if (variables.show_environment !== false && variables.temp && states[variables.temp]) { + let st = states[variables.temp].state; + if (st !== 'unknown' && st !== 'unavailable') { + let v = parseFloat(st); + if (!isNaN(v)) { + env_parts.push(`${v.toFixed(1)}°C`); + if (v < variables.temp_low) c_temp = '66, 165, 245'; + else if (v < variables.temp_mid) c_temp = '255, 235, 59'; + else if (v < variables.temp_high) c_temp = '255, 167, 38'; + else c_temp = '239, 83, 80'; + } + } + } + + if (variables.show_environment !== false && variables.humidity && states[variables.humidity]) { + let st = states[variables.humidity].state; + if (st !== 'unknown' && st !== 'unavailable') { + let v = parseFloat(st); + if (!isNaN(v)) { + env_parts.push(`${v.toFixed(0)}%`); + if (v < variables.hum_low) c_hum = '255, 167, 38'; + else if (v <= variables.hum_high) c_hum = '66, 165, 245'; + else c_hum = '255, 167, 38'; + } + } + } + + if (variables.show_environment !== false && variables.lux && states[variables.lux]) { + let st = states[variables.lux].state; + if (st !== 'unknown' && st !== 'unavailable') { + let v = parseFloat(st); + if (!isNaN(v)) { + env_parts.push(`${v.toFixed(0)}lx`); + c_lux = v < variables.lux_min ? '120, 144, 156' : (v > variables.lux_max ? '255, 235, 59' : '212, 225, 87'); + } + } + } + + let b2_text = env_parts.join(' • '); + let display_b2 = env_parts.length > 0 ? 'block' : 'none'; + let bg_gradient = `linear-gradient(90deg, rgba(${c_temp}, 0.15) 0%, rgba(${c_hum}, 0.15) 50%, rgba(${c_lux}, 0.2) 100%)`; + + return ` + #card { + --appliance-color: ${color}; + } + + #badge1 { + display: block; + background: rgba(var(--appliance-color), 0.07); + color: var(--primary-text-color); + border-top: 1px solid var(--divider-color, rgba(128,128,128,0.2)); + border-bottom: 1px solid var(--divider-color, rgba(128,128,128,0.2)); + border-left: 2.5px solid rgb(var(--appliance-color)); + border-radius: 6px !important; + } + #badge1::before { content: "${status_text}"; } + + #badge2 { + display: ${display_b2}; + background: ${bg_gradient}; + color: var(--primary-text-color); + border-top: 1px solid var(--divider-color, rgba(128,128,128,0.2)); + border-bottom: 1px solid var(--divider-color, rgba(128,128,128,0.2)); + border-left: 2.5px solid rgb(${c_temp}); + border-right: 2.5px solid rgb(${c_lux}); + border-radius: 6px !important; + } + #badge2::before { content: "${b2_text}"; } + + @keyframes radar-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + `; + ]]] + +``` +
+ +
+ +665270583-e99d9c97-0201-489e-99b3-9506c5fa2cb7 + +
+Smoke detector card + +```yaml +type: custom:button-card +entity: binary_sensor.aqara_smoke_detector_smoke +name: Smoke Detector +show_state: false +show_label: true +variables: + sensor_density: sensor.aqara_smoke_detector_smoke_density + sensor_battery: sensor.aqara_smoke_detector_battery + show_bar: false + theme_idle_colored: false + heartbeat_color: '#4caf50' + heartbeat_interval: 3s + batt_red: 20 + batt_orange: 40 + batt_yellow: 70 + dens_yellow: 0.1 + dens_orange: 0.3 + dens_red: 0.5 + size_icon: 45px + size_shape: 65px + size_card_height: 95px + font_primary: 15px + font_secondary: 12px + font_badge: 10px +styles: + card: + - --config-icon-size: '[[[ return variables.size_icon ]]]' + - --config-shape-size: '[[[ return variables.size_shape ]]]' + - --config-card-height: '[[[ return variables.size_card_height ]]]' + - --config-font-primary: '[[[ return variables.font_primary ]]]' + - --config-font-secondary: '[[[ return variables.font_secondary ]]]' + - --config-font-badge: '[[[ return variables.font_badge ]]]' + - height: var(--config-card-height) !important + - padding: 0px !important + - overflow: hidden + - position: relative + - transition: background 0.5s ease + grid: + - padding: 12px 16px + - height: 100% + - box-sizing: border-box + - grid-template-areas: '"i n" "i l"' + - grid-template-columns: var(--config-shape-size) 1fr + - grid-template-rows: auto auto + - align-content: center + - gap: 0px 12px + - position: relative + - z-index: 2 + icon: + - width: var(--config-icon-size) + - height: var(--config-icon-size) + - color: var(--primary-text-color) + - z-index: 3 + - animation: var(--anim-icon-shake) + - transform-origin: center center + - will-change: transform + img_cell: + - width: var(--config-shape-size) + - height: var(--config-shape-size) + - border-radius: 50% + - border: 1px solid var(--divider-color, rgba(128,128,128,0.2)) !important + - background: rgba(var(--appliance-color), 0.1) !important + - position: relative + - overflow: visible !important + - justify-self: start + - z-index: 2 + name: + - justify-self: start + - font-size: var(--config-font-primary) + - font-weight: 500 + - align-self: end + - margin-bottom: 2px + - position: relative + - z-index: 3 + label: + - justify-self: start + - font-size: var(--config-font-secondary) + - opacity: 0.7 + - align-self: start + - margin-top: 2px + - position: relative + - z-index: 3 + custom_fields: + bg_smoke: + - position: absolute + - inset: 0 + - z-index: 0 + - pointer-events: none + - display: var(--display-smoke) + heartbeat: + - position: absolute + - top: 10px + - left: 10px + - width: 6px + - height: 6px + - border-radius: 50% + - background: var(--hb-color) + - box-shadow: 0 0 6px var(--hb-color) + - display: var(--display-heartbeat) + - animation: hardware-blink var(--hb-interval) infinite + - z-index: 5 + badge1: + - position: absolute + - top: 10px + - right: 10px + - background: rgba(var(--appliance-color), 0.15) + - color: var(--primary-text-color) + - border-top: 1px solid rgba(128,128,128, 0.2) + - border-bottom: 1px solid rgba(128,128,128, 0.2) + - border-left: 2.5px solid rgb(var(--appliance-color)) + - padding: 2px 10px + - border-radius: 6px + - font-size: var(--config-font-badge) + - font-weight: 600 + - text-transform: uppercase + - letter-spacing: 0.5px + - white-space: nowrap + - z-index: 5 + badge2: + - position: absolute + - top: 38px + - right: 10px + - color: var(--primary-text-color) + - border-top: 1px solid rgba(128,128,128, 0.2) + - border-bottom: 1px solid rgba(128,128,128, 0.2) + - padding: 4px 8px + - font-size: 10px + - letter-spacing: 0.5px + - white-space: nowrap + - opacity: 0.9 + - text-transform: uppercase + - font-weight: 500 + - border-radius: 6px + - display: var(--display-badge2) + - z-index: 5 + bar: + - position: absolute + - bottom: 0 + - left: 0 + - height: 3.5px + - width: var(--appliance-level) + - background: rgb(var(--appliance-color)) + - box-shadow: 0 0 8px rgb(var(--appliance-color)) + - transition: width 0.5s ease + - display: var(--display-bar) + - z-index: 5 +tap_action: + action: more-info +label: | + [[[ + let ent_smoke = entity ? entity.entity_id : null; + if (!ent_smoke || !states[ent_smoke]) return 'Entity Setup Required'; + return states[ent_smoke].state === 'on' ? 'Smoke Detected' : 'Monitoring'; + ]]] +icon: mdi:smoke-detector +custom_fields: + badge1: ' ' + badge2: ' ' + bar: ' ' + heartbeat: ' ' + bg_smoke: | + [[[ + return ` +
+
+
+
+ `; + ]]] +extra_styles: | + [[[ + let ent_smoke = entity ? entity.entity_id : null; + let ent_bat = variables.sensor_battery; + let ent_den = variables.sensor_density; + + let is_smoke = ent_smoke && states[ent_smoke] && states[ent_smoke].state === 'on'; + let raw_bat = states[ent_bat] ? parseFloat(states[ent_bat].state) : NaN; + let raw_den = states[ent_den] ? parseFloat(states[ent_den].state) : NaN; + + let theme_colored = variables.theme_idle_colored !== undefined ? variables.theme_idle_colored : false; + let status = 'CLEAR'; + let color = theme_colored ? '0, 229, 255' : '158, 158, 158'; + + let anim_shake = 'none'; + let anim_strobe = 'none'; + let display_smoke = 'none'; + let display_heartbeat = 'block'; + + if (is_smoke) { + status = 'SMOKE ALARM'; + color = '244, 67, 54'; + anim_shake = 'buzzer-shake 0.1s linear infinite'; + anim_strobe = 'strobe-fade 0.8s ease-in-out infinite'; + display_smoke = 'block'; + display_heartbeat = 'none'; + } + + let progress = isNaN(raw_bat) ? 100 : Math.max(0, Math.min(100, raw_bat)); + let display_bar = (variables.show_bar !== false && !isNaN(raw_bat)) ? 'block' : 'none'; + + let c_bat = '76, 175, 80'; + if (!isNaN(raw_bat)) { + if (raw_bat <= (variables.batt_red || 20)) { c_bat = '244, 67, 54'; } + else if (raw_bat <= (variables.batt_orange || 40)) { c_bat = '255, 152, 0'; } + else if (raw_bat <= (variables.batt_yellow || 70)) { c_bat = '255, 235, 59'; } + } + + let c_den = '76, 175, 80'; + if (!isNaN(raw_den)) { + if (raw_den >= (variables.dens_red || 0.5)) { c_den = '244, 67, 54'; } + else if (raw_den >= (variables.dens_orange || 0.3)) { c_den = '255, 152, 0'; } + else if (raw_den >= (variables.dens_yellow || 0.1)) { c_den = '255, 235, 59'; } + } + + let b2_arr = []; + let b2_text = ''; + if (!isNaN(raw_bat)) b2_arr.push(`Bat ${Math.round(raw_bat)}%`); + if (!isNaN(raw_den)) b2_arr.push(`Den ${raw_den}`); + + let display_badge2 = b2_arr.length > 0 ? 'block' : 'none'; + if (b2_arr.length > 0) { + b2_text = b2_arr.join(' • '); + } + + let bg_badge2 = 'rgba(128,128,128,0.05)'; + let b2_left = '1px solid rgba(128,128,128,0.2)'; + let b2_right = '1px solid rgba(128,128,128,0.2)'; + + if (!isNaN(raw_bat) && !isNaN(raw_den)) { + bg_badge2 = `linear-gradient(90deg, rgba(${c_bat}, 0.15) 30%, rgba(${c_den}, 0.2) 75%)`; + b2_left = `2.5px solid rgb(${c_bat})`; + b2_right = `2.5px solid rgb(${c_den})`; + } else if (!isNaN(raw_bat)) { + bg_badge2 = `rgba(${c_bat}, 0.15)`; + b2_left = `2.5px solid rgb(${c_bat})`; + } else if (!isNaN(raw_den)) { + bg_badge2 = `rgba(${c_den}, 0.15)`; + b2_right = `2.5px solid rgb(${c_den})`; + } + + return ` + #card { + --appliance-color: ${color}; + --appliance-level: ${progress}%; + --anim-icon-shake: ${anim_shake}; + --anim-cell-strobe: ${anim_strobe}; + --display-smoke: ${display_smoke}; + --display-bar: ${display_bar}; + --display-heartbeat: ${display_heartbeat}; + --display-badge2: ${display_badge2}; + --hb-color: ${variables.heartbeat_color || '#4caf50'}; + --hb-interval: ${variables.heartbeat_interval || '5s'}; + } + + #badge1::before { content: "${status}"; } + + #badge2 { + background: ${bg_badge2}; + border-left: ${b2_left}; + border-right: ${b2_right}; + } + + #badge2::before { content: "${b2_text}"; } + + #img-cell::before { + content: ''; + position: absolute; + inset: 0; + border-radius: 50%; + background-color: rgba(var(--appliance-color), 0.5); + box-shadow: 0 0 20px rgba(var(--appliance-color), 0.6); + opacity: 0; + animation: var(--anim-cell-strobe); + pointer-events: none; + will-change: opacity; + } + + .smoke-plume { + position: absolute; + bottom: -40px; + background: radial-gradient(circle at center, color-mix(in srgb, var(--primary-text-color) 40%, transparent) 0%, transparent 65%); + border-radius: 50%; + opacity: 0; + will-change: transform, opacity; + } + + .plume-1 { animation: drift-1 4s ease-in infinite; } + .plume-2 { animation: drift-2 4.5s ease-in infinite; } + .plume-3 { animation: drift-3 5s ease-in infinite; } + .plume-4 { animation: drift-1 5.5s ease-in infinite; } + + @keyframes buzzer-shake { + 0%, 100% { transform: translate3d(0, 0, 0); } + 25% { transform: translate3d(-1px, 0.5px, 0) rotate(-1.5deg); } + 75% { transform: translate3d(1px, -0.5px, 0) rotate(1.5deg); } + } + + @keyframes strobe-fade { + 0%, 100% { opacity: 0; } + 50% { opacity: 1; } + } + + @keyframes hardware-blink { + 0%, 8%, 100% { opacity: 0; } + 4% { opacity: 1; } + } + + @keyframes drift-1 { + 0% { transform: translate3d(0, 10px, 0) scale(0.5); opacity: 0; } + 30% { opacity: 0.7; } + 100% { transform: translate3d(-15px, -110px, 0) scale(2.8); opacity: 0; } + } + + @keyframes drift-2 { + 0% { transform: translate3d(0, 10px, 0) scale(0.5); opacity: 0; } + 30% { opacity: 0.6; } + 100% { transform: translate3d(20px, -100px, 0) scale(3.2); opacity: 0; } + } + + @keyframes drift-3 { + 0% { transform: translate3d(0, 10px, 0) scale(0.5); opacity: 0; } + 30% { opacity: 0.8; } + 100% { transform: translate3d(-5px, -120px, 0) scale(3.0); opacity: 0; } + } + `; + ]]] + +``` +
+ +
+ +665270603-0e21a7c6-cfbb-47fd-8f92-ea5fa3a7038f + +
+Liquid card (Water) + +```yaml +type: custom:button-card +entity: sensor.water_tank_level +name: Water Tank +show_icon: true +show_name: true +show_state: true +icon: mdi:water +variables: + card_h: 150 + circle_size: 100 +styles: + card: + - height: '[[[ return variables.card_h + ''px'' ]]]' + - position: relative + - overflow: hidden + - background: transparent + - box-shadow: var(--ha-card-box-shadow, none) + - border-radius: var(--ha-card-border-radius, 12px) + - border: | + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + let rgb = level <= 20 ? "150, 29, 29" : "29, 130, 150"; + return `1px solid rgba(${rgb}, 0.3)`; + ]]] + grid: + - grid-template-areas: '"i" "s" "n"' + - grid-template-columns: 1fr + - grid-template-rows: min-content min-content min-content + - height: 100% + - align-content: center + - justify-content: center + - gap: '[[[ return (variables.circle_size * 0.02) + ''px'' ]]]' + icon: + - color: white + - width: '[[[ return (variables.circle_size * 0.35) + ''px'' ]]]' + - justify-self: center + - filter: drop-shadow(0px 1px 3px rgba(0,0,0,0.8)) + - position: relative + - z-index: 3 + state: + - color: white + - font-size: '[[[ return (variables.circle_size * 0.15) + ''px'' ]]]' + - font-weight: bold + - justify-self: center + - text-shadow: 0px 1px 3px rgba(0,0,0,0.8) + - position: relative + - z-index: 3 + name: + - color: white + - font-size: '[[[ return (variables.circle_size * 0.10) + ''px'' ]]]' + - justify-self: center + - text-shadow: 0px 1px 3px rgba(0,0,0,0.8) + - position: relative + - z-index: 3 + custom_fields: + glass_circle: + - position: absolute + - top: 50% + - left: 50% + - transform: translate(-50%, -50%) + - width: '[[[ return variables.circle_size + ''px'' ]]]' + - height: '[[[ return variables.circle_size + ''px'' ]]]' + - border-radius: 50% + - background: rgba(0, 0, 0, 0.25) + - backdrop-filter: blur(6px) + - -webkit-backdrop-filter: blur(6px) + - border: 1px solid rgba(255, 255, 255, 0.15) + - box-shadow: 0 4px 15px rgba(0,0,0,0.3) + - z-index: 2 + back_wave: + - position: absolute + - inset: 0 + - z-index: 1 + - pointer-events: none + - display: |- + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + return level <= 0 ? "none" : "block"; + ]]] + front_wave: + - position: absolute + - inset: 0 + - z-index: 1 + - pointer-events: none + - display: |- + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + return level <= 0 ? "none" : "block"; + ]]] +custom_fields: + glass_circle: | + [[[ return ``; ]]] + back_wave: | + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + let rgb = level <= 20 ? "150, 29, 29" : "29, 130, 150"; + let color = `rgba(${rgb}, 0.6)`; + + /* Draw SVG path */ + let path = "M0 7.5 Q30 0 60 7.5 T120 7.5 L120 15 L0 15 Z"; + let svg = ``; + + /* Repeat the SVG 10 times */ + let wave_row = svg.repeat(10); + + return ` +
+
+ ${wave_row} +
+
+
+ `; + ]]] + front_wave: | + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + let rgb = level <= 20 ? "150, 29, 29" : "29, 130, 150"; + let color = `rgba(${rgb}, 1)`; + + /* Draw SVG path */ + let path = "M0 7.5 Q30 0 60 7.5 T120 7.5 L120 15 L0 15 Z"; + let svg = ``; + + /* Repeat the SVG 10 times */ + let wave_row = svg.repeat(10); + + return ` +
+
+ ${wave_row} +
+
+
+ `; + ]]] +extra_styles: | + @keyframes scroll-left { + 0% { transform: translateX(0); } + 100% { transform: translateX(-120px); } + } + @keyframes scroll-right { + 0% { transform: translateX(-120px); } + 100% { transform: translateX(0); } + } + +``` +
+ +
+Liquid card (Fuel) + +```yaml +type: custom:button-card +entity: sensor.fuel_tank_level +name: Fuel Tank +show_icon: true +show_name: true +show_state: true +icon: mdi:barrel +variables: + card_h: 150 + circle_size: 100 +styles: + card: + - height: '[[[ return variables.card_h + ''px'' ]]]' + - position: relative + - overflow: hidden + - background: transparent + - box-shadow: var(--ha-card-box-shadow, none) + - border-radius: var(--ha-card-border-radius, 12px) + - border: | + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + let rgb = level <= 20 ? "211, 47, 47" : "245, 124, 0"; + return `1px solid rgba(${rgb}, 0.3)`; + ]]] + grid: + - grid-template-areas: '"i" "s" "n"' + - grid-template-columns: 1fr + - grid-template-rows: min-content min-content min-content + - height: 100% + - align-content: center + - justify-content: center + - gap: '[[[ return (variables.circle_size * 0.02) + ''px'' ]]]' + icon: + - color: white + - width: '[[[ return (variables.circle_size * 0.35) + ''px'' ]]]' + - justify-self: center + - filter: drop-shadow(0px 1px 3px rgba(0,0,0,0.8)) + - position: relative + - z-index: 3 + state: + - color: white + - font-size: '[[[ return (variables.circle_size * 0.15) + ''px'' ]]]' + - font-weight: bold + - justify-self: center + - text-shadow: 0px 1px 3px rgba(0,0,0,0.8) + - position: relative + - z-index: 3 + name: + - color: white + - font-size: '[[[ return (variables.circle_size * 0.10) + ''px'' ]]]' + - justify-self: center + - text-shadow: 0px 1px 3px rgba(0,0,0,0.8) + - position: relative + - z-index: 3 + custom_fields: + glass_circle: + - position: absolute + - top: 50% + - left: 50% + - transform: translate(-50%, -50%) + - width: '[[[ return variables.circle_size + ''px'' ]]]' + - height: '[[[ return variables.circle_size + ''px'' ]]]' + - border-radius: 50% + - background: rgba(0, 0, 0, 0.25) + - backdrop-filter: blur(6px) + - -webkit-backdrop-filter: blur(6px) + - border: 1px solid rgba(255, 255, 255, 0.15) + - box-shadow: 0 4px 15px rgba(0,0,0,0.3) + - z-index: 2 + back_wave: + - position: absolute + - inset: 0 + - z-index: 1 + - pointer-events: none + - display: >- + [[[ return ((entity ? parseFloat(entity.state) || 0 : 0) <= 0) ? + "none" : "block"; ]]] + front_wave: + - position: absolute + - inset: 0 + - z-index: 1 + - pointer-events: none + - display: >- + [[[ return ((entity ? parseFloat(entity.state) || 0 : 0) <= 0) ? + "none" : "block"; ]]] +custom_fields: + glass_circle: | + [[[ return ``; ]]] + back_wave: | + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + let rgb = level <= 20 ? "211, 47, 47" : "245, 124, 0"; + let color = `rgba(${rgb}, 0.6)`; + + /* Draw SVG path */ + let path = "M0 7.5 Q30 0 60 7.5 T120 7.5 L120 15 L0 15 Z"; + let svg = ``; + + /* Repeat the SVG 10 times */ + let wave_row = svg.repeat(10); + + return ` +
+
+ ${wave_row} +
+
+
+ `; + ]]] + front_wave: | + [[[ + let level = entity ? parseFloat(entity.state) || 0 : 0; + let rgb = level <= 20 ? "211, 47, 47" : "245, 124, 0"; + let color = `rgba(${rgb}, 1)`; + + /* Draw SVG path */ + let path = "M0 7.5 Q30 0 60 7.5 T120 7.5 L120 15 L0 15 Z"; + let svg = ``; + + /* Repeat the SVG 10 times */ + let wave_row = svg.repeat(10); + + return ` +
+
+ ${wave_row} +
+
+
+ `; + ]]] +extra_styles: | + @keyframes scroll-left { + 0% { transform: translateX(0); } + 100% { transform: translateX(-120px); } + } + @keyframes scroll-right { + 0% { transform: translateX(-120px); } + 100% { transform: translateX(0); } + } + +``` +
+ +
+Liquid card (Battery/percentage) + +```yaml +type: custom:button-card +entity: sensor.anasbox_battery_level +name: Battery +show_icon: true +show_name: true +show_state: true +variables: + card_h: 150 + circle_size: 110 + threshold_red: 20 + threshold_orange: 50 + threshold_green: 100 + charger_entity: binary_sensor.anasbox_is_charging +icon: | + [[[ + if (entity && entity.attributes && entity.attributes.icon) return entity.attributes.icon; + let level = entity && entity.state && !isNaN(entity.state) ? parseFloat(entity.state) : 0; + let charger = variables.charger_entity && states[variables.charger_entity] ? states[variables.charger_entity] : null; + let is_charging = charger ? ['on', 'charging', 'plugged'].includes(charger.state.toLowerCase()) : false; + let rounded = Math.round(level / 10) * 10; + if (is_charging) { + if (rounded === 0) return "mdi:battery-charging-outline"; + return `mdi:battery-charging-${rounded}`; + } + if (rounded === 100) return "mdi:battery"; + if (rounded === 0) return "mdi:battery-outline"; + return `mdi:battery-${rounded}`; + ]]] +styles: + card: + - height: '[[[ return variables.card_h + ''px'' ]]]' + - position: relative + - overflow: hidden + - background: transparent + - box-shadow: var(--ha-card-box-shadow, none) + - border-radius: var(--ha-card-border-radius, 12px) + - border: | + [[[ + let level = entity && entity.state && !isNaN(entity.state) ? parseFloat(entity.state) : 0; + let is_charging = variables.charger_entity && states[variables.charger_entity] ? ['on', 'charging', 'plugged'].includes(states[variables.charger_entity].state.toLowerCase()) : false; + let rgb = "0, 255, 100"; + if (is_charging) rgb = "0, 255, 255"; + else if (level <= variables.threshold_red) rgb = "244, 67, 54"; + else if (level <= variables.threshold_orange) rgb = "255, 152, 0"; + return `1px solid rgba(${rgb}, 0.3)`; + ]]] + grid: + - grid-template-areas: '"i" "s" "n"' + - grid-template-columns: 1fr + - grid-template-rows: min-content min-content min-content + - height: 100% + - align-content: center + - justify-content: center + - gap: '[[[ return (variables.circle_size * 0.02) + ''px'' ]]]' + icon: + - color: white + - width: '[[[ return (variables.circle_size * 0.35) + ''px'' ]]]' + - justify-self: center + - filter: drop-shadow(0px 1px 3px rgba(0,0,0,0.8)) + - position: relative + - z-index: 3 + state: + - color: white + - font-size: '[[[ return (variables.circle_size * 0.15) + ''px'' ]]]' + - font-weight: bold + - justify-self: center + - text-shadow: 0px 1px 3px rgba(0,0,0,0.8) + - position: relative + - z-index: 3 + name: + - color: white + - font-size: '[[[ return (variables.circle_size * 0.10) + ''px'' ]]]' + - justify-self: center + - text-shadow: 0px 1px 3px rgba(0,0,0,0.8) + - position: relative + - z-index: 3 + custom_fields: + glass_circle: + - position: absolute + - top: 50% + - left: 50% + - transform: translate(-50%, -50%) + - width: '[[[ return variables.circle_size + ''px'' ]]]' + - height: '[[[ return variables.circle_size + ''px'' ]]]' + - border-radius: 50% + - background: rgba(0, 0, 0, 0.25) + - backdrop-filter: blur(6px) + - -webkit-backdrop-filter: blur(6px) + - border: 1px solid rgba(255, 255, 255, 0.15) + - box-shadow: 0 4px 15px rgba(0,0,0,0.3) + - z-index: 2 + back_wave: + - position: absolute + - inset: 0 + - z-index: 1 + - pointer-events: none + front_wave: + - position: absolute + - inset: 0 + - z-index: 1 + - pointer-events: none +custom_fields: + glass_circle: | + [[[ return ``; ]]] + back_wave: | + [[[ + let level = entity && entity.state && !isNaN(entity.state) ? parseFloat(entity.state) : 0; + let display_level = Math.max(level, 5); + let is_charging = variables.charger_entity && states[variables.charger_entity] ? ['on', 'charging', 'plugged'].includes(states[variables.charger_entity].state.toLowerCase()) : false; + let rgb = "46, 204, 113"; + if (is_charging) rgb = "52, 152, 219"; + else if (level <= variables.threshold_red) rgb = "231, 76, 60"; + else if (level <= variables.threshold_orange) rgb = "243, 156, 18"; + let color = `rgba(${rgb}, 0.6)`; + let speed = is_charging ? "2s" : "4s"; + let path = "M0 7.5 Q30 0 60 7.5 T120 7.5 L120 15 L0 15 Z"; + let svg = ``; + let wave_row = svg.repeat(10); + return ` +
+
+ ${wave_row} +
+
+
+ `; + ]]] + front_wave: | + [[[ + let level = entity && entity.state && !isNaN(entity.state) ? parseFloat(entity.state) : 0; + let display_level = Math.max(level, 5); + let is_charging = variables.charger_entity && states[variables.charger_entity] ? ['on', 'charging', 'plugged'].includes(states[variables.charger_entity].state.toLowerCase()) : false; + let rgb = "46, 204, 113"; + if (is_charging) rgb = "52, 152, 219"; + else if (level <= variables.threshold_red) rgb = "231, 76, 60"; + else if (level <= variables.threshold_orange) rgb = "243, 156, 18"; + let color = `rgba(${rgb}, 1)`; + let speed = is_charging ? "1.5s" : "3s"; + let path = "M0 7.5 Q30 0 60 7.5 T120 7.5 L120 15 L0 15 Z"; + let svg = ``; + let wave_row = svg.repeat(10); + return ` +
+
+ ${wave_row} +
+
+
+ `; + ]]] +extra_styles: | + @keyframes scroll-left { + 0% { transform: translateX(0); } + 100% { transform: translateX(-120px); } + } + @keyframes scroll-right { + 0% { transform: translateX(-120px); } + 100% { transform: translateX(0); } + } + +``` +
+ +
+ +665270619-e1f31ec9-da72-4c9f-bdfc-ed20abf2d10c + +
+Mushroom light card with color temps quick toggles + +
+ +>* after pasting this card, use the Find & Replace ALL feature in the card editor (CTRL+F) and Replace `light.CHANGE_ME` with your light entity, to change it everywhere at once. + +```yaml +type: custom:vertical-stack-in-card +cards: + - type: custom:mushroom-light-card + entity: light.CHANGE_ME + name: Light Card Name + icon: mdi:led-strip-variant + show_brightness_control: true + show_color_control: true + show_color_temp_control: true + use_light_color: true + card_mod: + style: + mushroom-light-brightness-control$: + mushroom-slider$: | + .slider { + background: rgba(255, 255, 255, 0.05) !important; + } + .slider-track-active { + box-shadow: inset 0 2px 4px rgba(0,0,0,0.15) !important; + } + .: | + ha-card { + background: none !important; + border: none !important; + box-shadow: none !important; + + padding-top: 10px !important; + padding-bottom: 10px !important; + + --control-height: 38px; + --control-border-radius: 19px; + } + mushroom-state-info { + max-width: calc(100% - 140px) !important; + } + - type: custom:mushroom-chips-card + alignment: end + card_mod: + style: | + ha-card { + position: absolute; + top: 10px; + right: 10px; + background: none !important; + border: none !important; + box-shadow: none !important; + + width: max-content; + pointer-events: none; + z-index: 10; + + --chip-background: rgba(255, 255, 255, 0.05); + --chip-box-shadow: none; + --chip-border-width: 0px; + --chip-spacing: 6px; + --chip-padding: 0 10px; + --chip-height: 38px; + --chip-icon-size: 20px; + } + mushroom-template-chip { + pointer-events: auto; + } + chips: + - type: template + entity: light.CHANGE_ME + icon: mdi:weather-sunset + icon_color: >- + {% set temp = state_attr(entity, 'color_temp_kelvin') %} + + {% set mode = state_attr(entity, 'color_mode') %} + + {{ 'orange' if is_state(entity, 'on') and mode == 'color_temp' and + temp != None and temp <= 3200 else 'disabled' }} + tap_action: + action: call-service + service: light.turn_on + target: + entity_id: light.CHANGE_ME + data: + color_temp_kelvin: 2702 + - type: template + entity: light.CHANGE_ME + icon: mdi:white-balance-sunny + icon_color: >- + {% set temp = state_attr(entity, 'color_temp_kelvin') %} + + {% set mode = state_attr(entity, 'color_mode') %} + + {{ 'amber' if is_state(entity, 'on') and mode == 'color_temp' and temp + != None and 3200 < temp < 5000 else 'disabled' }} + tap_action: + action: call-service + service: light.turn_on + target: + entity_id: light.CHANGE_ME + data: + color_temp_kelvin: 4000 + - type: template + entity: light.CHANGE_ME + icon: mdi:snowflake + icon_color: >- + {% set temp = state_attr(entity, 'color_temp_kelvin') %} + + {% set mode = state_attr(entity, 'color_mode') %} + + {{ 'light-blue' if is_state(entity, 'on') and mode == 'color_temp' and + temp != None and temp >= 5000 else 'disabled' }} + tap_action: + action: call-service + service: light.turn_on + target: + entity_id: light.CHANGE_ME + data: + color_temp_kelvin: 6535 +card_mod: + style: | + ha-card { + position: relative; + } + +``` +
+ +--- + +[paypal_me_shield]: https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white + +[paypal_me]: https://paypal.me/anasboxsupport + +[revolut_me_shield]: +https://img.shields.io/badge/revolut-FFFFFF?style=for-the-badge&logo=revolut&logoColor=black + +[revolut_me]: https://revolut.me/anas4e + +[ko_fi_shield]: https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white + +[ko_fi_me]: https://ko-fi.com/anasbox + +[buy_me_coffee_shield]: +https://img.shields.io/badge/Buy%20Me%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black + +[buy_me_coffee_me]: https://www.buymeacoffee.com/anasbox + +[patreon_shield]: +https://img.shields.io/badge/patreon-404040?style=for-the-badge&logo=patreon&logoColor=white + +[patreon_me]: https://patreon.com/AnasBox