I’ve recently discovered the power of custom:button-card
(https://github.com/custom-cards/button-card) and want to share some nice layouts I created. Be sure to read the documentation for the button-card at that link if you try to use any of these examples. I make extensive use of its templating feature.
There are a few things going on in that image:
- standard and wide button variations
- a container that only needs one color setting to theme the header and body
- multi-option button
- sensors that have color animation when active
Standard & Wide Buttons
The standard and wide button variations are fairly straightforward. I have these defined as templates:
button_card_templates:
standard:
color_type: card
size: 80%
hold_action:
action: more-info
styles:
card:
- padding: 0.2em
- '--mdc-ripple-color': yellow
- '--mdc-ripple-press-opacity': 0.5
icon:
- opacity: 0.5
name:
- font-size: 0.65em
- white-space: normal
state:
- font-size: 0.65em
- white-space: normal
label:
- font-size: 0.4em
- white-space: normal
wide:
template: standard
styles:
grid:
- position: relative
- grid-template-areas: '"i n"'
- grid-template-columns: 1fr 1fr
- grid-template-rows: 1fr
I use the standard template to set my common style. The wide template builds on the standard template and just makes the icon and name side by side instead of over/under.
To use them in my dashboard I just supply the desired template and any other relevant properties that aren’t defined by the template or that I want to override:
- entity: switch.patio_light
template: standard
name: Patio
icon: 'mdi:outdoor-lamp'
type: 'custom:button-card'
Container with Header
This layout was inspired by a control that I used to use for the same effect, banner-card
(https://github.com/nervetattoo/banner-card). I like the look of that, but I wanted more flexibility of the content. Fortunately it was quite easy to make a container with a button card using the custom_fields
config.
button_card_templates:
container:
color_type: label-card
color: dimgray
styles:
card:
- padding: 0
name:
- border-radius: 0.4em 0.4em 0 0
- padding: 0.1em
- width: 100%
- font-weight: bold
grid:
- grid-template-areas: '"i" "n" "buttons"'
- grid-template-columns: 1fr
- grid-template-rows: 1fr min-content min-content
custom_fields:
buttons:
- background-color: 'rgba(0,0,0,0.3)'
- margin: 0
- padding: 0.3em
This is a label card that contains a horizontal or vertical stack, which then contains whatever I want, such as buttons to control things. In the template above I defined a custom grid for the layout and set the styles. In the grid-template-areas
I have a grid area called buttons
that matches the buttons
custom field in custom_fields
. The custom_fields
is defined twice: once in the template styles, and once in my dashboard where I am defining the container. Below is the dashboard yaml for one of my containers in the example image.
type: 'custom:button-card'
template: container
color: '#EDE7B0'
name: Eating & Patio
custom_fields:
buttons:
card:
type: horizontal-stack
cards:
- entity: switch.ge_14291_in_wall_smart_switch_switch_2
name: Kitchen
template: standard
icon: 'mdi:wall-sconce-flat'
type: 'custom:button-card'
- entity: light.ge_14294_in_wall_smart_dimmer_level_10
name: Table
template: standard
icon: 'mdi:ceiling-light'
type: 'custom:button-card'
- entity: light.ge_14294_in_wall_smart_dimmer_level_7
name: Dining
template: standard
icon: 'mdi:ceiling-light'
type: 'custom:button-card'
- entity: switch.patio_light
template: standard
name: Patio
icon: 'mdi:outdoor-lamp'
type: 'custom:button-card'
Multi-option Button
The multi-option button is a bit more involved. It is essentially a button showing its own icon/name and 4 more buttons. In principal it works the same as the container, but it is styled differently and assumes I always want 4 options so that most of it is standard templates and reduces what I have to put in my dashboard. This also has custom javascript templates to detect value ranges when a particular option should be “on”, and it uses service calls to set the desired option value.
This uses several templates, so I will describe each one separately.
Option Button
This defines the basic look of an option button. It builds on the standard button, hides the icon, sets 1/1 aspect ratio to make it square, and sets a nice border radius.
button_card_templates:
option-button:
template: standard
show_icon: false
aspect_ratio: 1/1
styles:
card:
- border-radius: 20%
Dimmer Option, Blind Option, Fan Option
This builds on the option-button and defines the tap_action and state monitoring. You will notice that is is using the variables feature of the button-card to get some necessary values. Those are provided by the presets template that I will describe in a moment.
I am only showing the dimmer option here because they are all the same definition, but with different service type and service_data for the tap_action, and different attributes to examine in the javascript.
button_card_templates:
dimmer-option:
template: option-button
tap_action:
action: call-service
service: light.turn_on
service_data:
entity_id: entity
brightness: '[[[ return variables.set_value ]]]'
state:
- operator: default
styles:
card:
- background-color: '[[[ return variables.option_button_off_color ]]]'
- color: '[[[ return variables.option_text_off_color ]]]'
- operator: template
value: >-
[[[ return (entity.attributes.brightness||0) >= variables.range_start
&& (entity.attributes.brightness||0) <= variables.range_stop ]]]
styles:
card:
- background-color: '[[[ return variables.option_button_on_color ]]]'
- color: '[[[ return variables.option_text_on_color ]]]'
Presets Template
This is a big template. It defines the whole layout and all of the variables, with default values.
Special note on overflow: visible
: this is to allow the option button’s shadow to appear correctly.
button_card_templates:
presets:
template: standard
color_type: icon
tap_action:
action: none
styles:
card:
- background-color: 'rgba(0,0,0,0.3)'
icon:
- color: white
grid:
- grid-template-areas: '"i opt1 opt2 opt3 opt4" "n opt1 opt2 opt3 opt4"'
- grid-template-columns: 1fr 1fr 1fr 1fr 1fr
custom_fields:
opt1:
- margin: 0.1em
- overflow: visible
opt2:
- margin: 0.1em
- overflow: visible
opt3:
- margin: 0.1em
- overflow: visible
opt4:
- margin: 0.1em
- overflow: visible
variables:
option_template: dimmer-option
option_button_on_color: var(--paper-item-icon-active-color)
option_text_on_color: white
option_button_off_color: var(--paper-card-background-color)
option_text_off_color: white
option1_name: Low
option1_set_value: 51
option1_range_start: 1
option1_range_stop: 77
option2_name: Med
option2_set_value: 102
option2_range_start: 78
option2_range_stop: 170
option3_name: High
option3_set_value: 255
option3_range_start: 171
option3_range_stop: 255
option4_name: 'Off'
option4_set_value: 0
option4_range_start: 0
option4_range_stop: 0
custom_fields:
opt1:
card:
type: 'custom:button-card'
entity: '[[[ return variables.entity ]]]'
template: '[[[ return variables.option_template ]]]'
name: '[[[ return variables.option1_name ]]]'
variables:
set_value: '[[[ return variables.option1_set_value ]]]'
range_start: '[[[ return variables.option1_range_start ]]]'
range_stop: '[[[ return variables.option1_range_stop ]]]'
option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
opt2:
card:
type: 'custom:button-card'
entity: '[[[ return variables.entity ]]]'
template: '[[[ return variables.option_template ]]]'
name: '[[[ return variables.option2_name ]]]'
variables:
set_value: '[[[ return variables.option2_set_value ]]]'
range_start: '[[[ return variables.option2_range_start ]]]'
range_stop: '[[[ return variables.option2_range_stop ]]]'
option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
opt3:
card:
type: 'custom:button-card'
entity: '[[[ return variables.entity ]]]'
template: '[[[ return variables.option_template ]]]'
name: '[[[ return variables.option3_name ]]]'
variables:
set_value: '[[[ return variables.option3_set_value ]]]'
range_start: '[[[ return variables.option3_range_start ]]]'
range_stop: '[[[ return variables.option3_range_stop ]]]'
option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
opt4:
card:
type: 'custom:button-card'
entity: '[[[ return variables.entity ]]]'
template: '[[[ return variables.option_template ]]]'
name: '[[[ return variables.option4_name ]]]'
variables:
set_value: '[[[ return variables.option4_set_value ]]]'
range_start: '[[[ return variables.option4_range_start ]]]'
range_stop: '[[[ return variables.option4_range_stop ]]]'
option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
Using the multi-option button in the dashboard
For this, you can omit any variables that have defaults that match waht you want. In this example I have set a lot of them, but not all.
- entity: cover.master_bath_blinds
type: 'custom:button-card'
template: presets
name: Blinds
state:
- value: closed
color: var(--paper-card-background-color)
- value: open
color: var(--paper-item-icon-active-color)
variables:
entity: cover.master_bath_blinds
option_template: blind-option
option1_name: ANG
option1_set_value: 12
option1_range_start: 2
option1_range_stop: 35
option2_name: OPN
option2_set_value: 50
option2_range_start: 36
option2_range_stop: 99
option3_name: CLN
option3_set_value: 100
option3_range_start: 100
option3_range_stop: 100
option4_name: CLS
option4_set_value: 0
option4_range_start: 9999
option4_range_stop: 9999
Alerting Sensors
I can explain this in more detail later, but I need to wrap up for now.
The template, with animation:
button_card_templates:
alerter:
template: standard
show_last_changed: true
color_type: icon
extra_styles: |
[[[ return `
@keyframes pulse1 {
20% {
background-color: ${variables.color_initial};
}
}
@keyframes pulse2 {
20% {
background-color: ${variables.color_extended};
}
}
@keyframes color {
0% {
color: unset;
opacity: 0.5
}
99% {
color: unset;
opacity: 0.5
}
100% {
color: ${variables.color_extended};
}
}
`]]]
variables:
color_initial: var(--paper-item-icon-active-color)
color_extended: 'rgba(240,52,52, 0.9)'
color_seconds: 60
state:
- value: 'on'
id: value_on
styles:
card:
- animation: >-
[[[ return `pulse1 1s ${variables.color_seconds}, pulse2 1s
${variables.color_seconds}s infinite` ]]]
icon:
- color: '[[[ return variables.color_extended ]]]'
- opacity: 1
- animation: '[[[ return `color ${variables.color_seconds}s 1` ]]]'
name:
- font-weight: bold
Here is how to use it in the dashboard:
- entity: binary_sensor.garage_door
template: alerter
name: Garage
type: 'custom:button-card'
variables:
color_seconds: 120
Conclusion
I have dumped a lot of config here and fully expect there will be questions. I hope you find this useful
1 post - 1 participant