Custom Features for Home Assistant Cards - Buttons, Dropdowns, Selectors, Sliders, Spinboxes, and Toggles

Thank you! Its how I want now!

Wish these basic settings were in the core UI… odd they didnt put ‘auto’ or ‘off’ for the row height so the border conforms without editing YAML (or knowing you need to!)

side note on card-mod css… top-padding works as expected but bottom-padding doesnt. Example: for Top 0 removes padding completely, but Bottom 0 still puts ~10px on the bottom. Even negative numbers never make that bottom padding smaller. And making the Top 0, doesnt change the bottom either - thus the bottom is not based on the top. Really odd

Since the new ‘inline’ feature for HA 2025-03.1 the Selector-feature disappears for me when I put the volume slider as inline. This also happens in the editor.
Before adding an issue to Github would like to know if anyone else is experiencing the same?

That’s how inline tile card features work, it only shows the first one. It’s in the 2025.3 release notes.

Hello.

I am using this wonderful feature generator to create a room card:

But I would like the shutter button icon to match the state of the cover entity linked.

I managed thanks to the style to have the color changing, but I would like either:

  • to be able to use the default entity icon
  • to have the icon also changing from mdi:shutter to mdi:shutter-open depending the cover entity state defined into a template.

I tried numerous tests to have the button icon depending on the cover state, but was not able to mange it properly.

How and where can I do that ?

My code for information:

features:
  - type: custom:service-call
    entries:
      - type: button
        entity_id: plant.alocatia
        icon: mdi:flower
        styles: |-
          :host {
                --icon-color: grey;
                {% if is_state("plant.alocatia", "alert") %}
                --icon-color: orange;
                {% endif %}
        tap_action:
          action: fire-dom-event
          browser_mod:
            service: browser_mod.popup
            data:
              title: Plante Marsupilami
              content:
                type: custom:flower-card
                entity: plant.alocatia
                show_bars:
                  - moisture
                  - temperature
                  - illuminance
                  - conductivity
                battery_sensor: sensor.alocasia_zebrina_battery
                display_type: compact
      - type: button
        entity_id: device_tracker.echo_jeanne
        icon: mdi:play-pause
        styles: |-
          :host {
                --icon-color: grey;
                {% if is_state("media_player.echo_jeanne", "playing") %}
                --icon-color: blue;
                {% endif %}
        tap_action:
          action: fire-dom-event
          browser_mod:
            service: browser_mod.popup
            data:
              title: Echo salon
              content:
                type: custom:streamline-card
                template: pop-up-alexa
                variables:
                  media_player_entity_name: echo_jeanne
      - type: button
        entity_id: cover.volet_du_salon_apero
        icon: mdi:window-shutter
        styles: |-
          :host {
                --icon-color: grey;
                {% if is_state("cover.salon", "open") %}
                --icon-color: orange;
                {% endif %}
          }
        tap_action:
          action: fire-dom-event
          browser_mod:
            service: browser_mod.popup
            data:
              title: Volets du salon
              content:
                type: vertical-stack
                cards:
                  - type: custom:mushroom-cover-card
                    entity: cover.volet_du_salon_apero
                    name: Volet Apero
                    show_position_control: true
                    show_tilt_position_control: false
                    show_buttons_control: true
                  - type: custom:mushroom-cover-card
                    entity: cover.volet_du_salon_tv
                    name: Volet TV
                    show_position_control: true
                    show_tilt_position_control: false
                    show_buttons_control: true
      - type: button
        entity_id: group.lumieres_salon
        hold_action:
          action: toggle
          target:
            entity_id: group.lumieres_salon
          data: {}
        haptics: true
        tap_action:
          action: fire-dom-event
          browser_mod:
            service: browser_mod.popup
            data:
              title: Lumières salon
              content:
                type: custom:streamline-card
                template: pop-up-light-salon
                variables: {}
        icon: mdi:lightbulb
        color: accent
        autofill_entity_id: true
        styles: |-
          :host {
                --icon-color: grey;
                {% if is_state("light.0x84ba20fffe4b2581", "on") %}
                --icon-color: orange;
                {% endif %}
          }
    styles: ""
type: tile
features_position: bottom
vertical: false
entity: sensor.tuile_salon
color: accent
icon: ""
state_content:
  - Alexa
  - Marsu
grid_options:
  columns: 6
  rows: 2
icon_hold_action:
  action: perform-action
  perform_action: light.toggle
  target:
    entity_id: light.0x84ba20fffe4b2581
icon_tap_action:
  action: perform-action
  perform_action: ""

Thank you very much for this very nice feature generator

And thanks in advance for help !

[Edit]

This code ended up working !

      - type: button
        entity_id: cover.salon
        icon: >-
          {{ iif(is_state("cover.salon", "open"), "mdi:window-shutter-open",
          "mdi:window-shutter") }}
        styles: |-
          :host {
                --icon-color: grey;
                {% if is_state("cover.salon", "open") %}
                --icon-color: orange;
                {% endif %}
          }
1 Like

Ah indeed, OK.
I thought it would put the first feature as inline and any others below, my bad.

Is there a way to set a default label for the dropdown? the dropdown is empty before i choose one of the option.

and second question: can i configure the width of the dropdown itself? it seems it is the width of the longest dropdown-option from beginning.

thx for this addon and your work :+1:

You have to set the option fields for dropdowns/selectors to work at all. There is no default otherwise, although it will autofill if used with select/input_select entities. You can use the label field to make it display something other than option, but that isn’t a default.

You can explicitly set the size of the dropdown box in the parent dropdown (not option) styles.

.dropdown {
  width: 50px;
}

4.3.0 has been released!

You can now create custom toggles!

By default they look like the new default toggle feature, but are more customizable with multiple icons and user defined actions. You can also choose to style them as Material Design checkboxes and switches. The checkbox and switch colors follow theme colors rather than feature color, and work best (especially the Material Design 3 switch) with Material You theme. See the README for all of the CSS variables the Material Design toggle options use.

This release also adds action failure toasts and a custom dialog for confirmations. You can now also template the entire action data and target fields with a YAML string for better control of what data is sent when you fire an action.

3 Likes

Hi @Nerwyn . First of all thank you very much for your hard work. In my dashboard I have a tile card that has some buttons. When I press those buttons I call a script that only changes colors of the lights that are on. This works as expected.

Now I want to do the same with the brightness. I created a script that takes the brightness as a value and only changes the brightness for the lights that are on in that room. The scripts does what it has to do when I test it in the developer tools. This is the script:

fields:
  color:
    description: RGB kleurcode als lijst (bv. (255,0,0) voor rood)
    example: (255,0,0)
    required: true
sequence:
  - if:
      - condition: state
        entity_id: light.lichten_living
        state: "on"
    then:
      - target:
          entity_id: >
            {% set on_lights = expand('light.lichten_living') |
            selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list
            %} {{ on_lights | join(', ') if on_lights else none }}
        data:
          rgb_color: "{{ color }}"
        action: light.turn_on
    else:
      - target:
          entity_id: light.lichten_living
        data:
          rgb_color: "{{ color }}"
        action: light.turn_on
alias: verander kleur ingeschakelde lichten living
description: ""
mode: restart

The problem I have is that I have no idea how to call the script using a slider feature. Could you help me out with this? Thanks in advance.

Kind regards,
Silvio

See this issue. To pass a variable to a script, pass the value of the slider to the script using data.variables.

type: button
tap_action:
  action: perform-action
  perform_action: script.turn_on
  target:
    entity_id: script.script_args_test
  data:
    variables:
      speed: '{{ value }}'
autofill_entity_id: false

Thanks for your reply. This seems to work for a slider:

type: tile
entity: light.lichten_living
features_position: bottom
vertical: false
features:
  - type: custom:service-call
    service: script.verander_helderheid_living
    name: Helderheid
    entries:
      - type: slider
        field: brightness_pct
        range:
          - 0
          - 100
        step: 1
        tap_action:
          action: perform-action
          perform_action: script.verander_helderheid_ingeschakelde_lichten_living
          data:
            brightness_pct: "{{ value | int }}"
          target:
            entity_id: light.lichten_living
        entity_id: light.lichten_living
        haptics: true
        label: "{{ value }}{{ unit }}"
        unit_of_measurement: "%"
        value_attribute: brightness
        icon: mdi:brightness-4
        thumb: default
        styles: |
          :host {
            flex-basis: 200%;
            {% if is_state(config.entity, "on") %}
            --color: rgb({{ state_attr(config.entity, "rgb_color") }})
            {% endif %}
          }
          .tooltip {
            {% if is_state(config.entity, "off") %}
            display: none;
            {% endif %}
          }

I’m trying to set the background colour of the first button according to the status but unfortunately it doesn’t work. The value of the binary sensor is OFF and the background should be coloured green. What am I doing wrong?

features:
  - type: custom:service-call
    entries:
      - type: button
        entity_id: binary_sensor.eg_wohnzimmer_fenster_beschattung_status
        value_attribute: state
        label: "{{ value }}"
        icon: kuf:fts_blade_z_sun
        styles: |-
          .background {
            --color: {{ "green" if state_attr(config.entity, config.attribute) = 'off' else "blue"}};
          }
      - type: button
        icon: mdi:sun-angle
        label: "{{ state_attr(\"sun.sun\", \"elevation\") }}"
        entity_id: cover.eg_wohnzimmer_fenster_rollo
      - type: button
        label: "{{ state_attr(\"sun.sun\", \"azimuth\") }}"
        icon: mdi:sun-compass
        entity_id: cover.eg_wohnzimmer_fenster_rollo
      - type: button
        entity_id: sensor.wohnzimmer_tenmperatur
        label: "{{ value }}"
        value_attribute: state
        icon: mdi:home-thermometer
      - type: button
        entity_id: sensor.wetterstation_temperatur
        label: "{{ value }}"
        value_attribute: state
        icon: mdi:thermometer
  - type: cover-open-close
type: tile
entity: cover.eg_wohnzimmer_fenster_rollo
features_position: bottom
vertical: false
name: Wohnzimmer Fenster
grid_options:
  columns: 12
  rows: 3

Did not try, but you probably need == for comparison, not = (which is an assignment)

I noticed that my code style looks a bit different and uses is_state. The code below changes opacity of a button and makes it red. Due to opacity changes it look more or less saturated.

Not really a template expert and not sure where I got it from, but it works.

        styles: |-
          :host {
            --opacity: {% if is_state("switch.trance_power", "on") %}
            0.8
          {% else %}
            0.4
          {% endif %}
          ;
            --color: red;
          }
1 Like

have changed it to your suggestion, works now. Thanks

I tried to remove the title and the title icon which was also successful. Now I have the issue, that the whole cart is too high. I assume this has to do with the grid-options -> rows which I am not able to change to a smaller value than 2. Is there a way to make the grid same height than the card and/or to remove the height: 62px !important; to fit it directly to the card? Currently it has the empty (grey) space below the card, witch is not nice:

YAML-Code:

features:
  - type: custom:service-call
    entries:
      - type: selector
        entity_id: input_select.test
        options:
          - entity_id: input_select.test
            icon: mdi:clock-time-eleven-outline
            option: zeit
            tap_action:
              action: perform-action
              perform_action: input_select.select_option
              data:
                option: zeit
              target:
                entity_id: input_select.test
          - entity_id: input_select.test
            icon: mdi:water
            option: volumen
            tap_action:
              action: perform-action
              perform_action: input_select.select_option
              data:
                option: volumen
              target:
                entity_id: input_select.test
        autofill_entity_id: true
        haptics: true
type: tile
entity: input_select.test
features_position: bottom
vertical: false
hide_state: true
show_entity_picture: false
card_mod:
  style: |
    ha-card .content {
      display: none !important;
    }
    ha-card {
      padding-top: 10px !important;
      height: 62px !important;
    }
grid_options:
  columns: 12
  rows: 2

Try setting grid_options.rows to a non-numerical value like null or x. It causes the card to not conform to the grid height.

Thank you for your hint. Do you have an example how implement that?

By changing grid_options.rows in the config you shared.

grid_options:
  columns: 12
  rows: null

This is the solution! Thank you very much!

Hi,
I do have a drop down. If the state of the entity is set to any value I would expect that the drop down also pre-selects this entry. But it is always blank.

As you see the value is 2 so I also would like to see the entry 2 pre-selected. What am I doing wrong?

Here is my code:

features:
  - type: custom:service-call
    entries:
      - type: dropdown
        entity_id: input_select.pool_modus_select
        options:
          - entity_id: input_select.pool_modus_select
            option: 0 - Manuell
            tap_action:
              action: perform-action
              perform_action: input_select.select_option
              data:
                option: "0"
              target:
                entity_id: input_select.pool_modus_select
            value_attribute: friendly_name
            haptics: false
          - entity_id: input_select.pool_modus_select
            option: 1 - Auto
            tap_action:
              action: perform-action
              perform_action: input_select.select_option
              data:
                option: "1"
              target:
                entity_id: input_select.pool_modus_select
            value_attribute: friendly_name
          - entity_id: input_select.pool_modus_select
            option: 2 - Heizen
            tap_action:
              action: perform-action
              perform_action: input_select.select_option
              data:
                option: "2"
              target:
                entity_id: input_select.pool_modus_select
            value_attribute: friendly_name
type: tile
features_position: bottom
vertical: false
entity: input_select.pool_modus_select
name: Pool-Modus
show_entity_picture: false

Once that is working I would like to hide the state value itself - is this possible?