Custom Features for Home Assistant Cards

repository·main·Indexed 19 days ago

https://github.com/nerwyn/custom-card-features

A suite of highly customizable UI elements for Home Assistant, including buttons, sliders, dropdowns, inputs, selectors, spinboxes, and toggles. These elements can be added as features to existing cards (such as the Tile card) or used within a standalone Custom Features Card. It supports Material Design 3, Nunjucks templating for dynamic labels and styles, and advanced interactions like double tap, hold, and swipe actions.

Tokens
20.2K
Snippets
47
Records
73
Agent score
61%

What's inside custom-card-features

  1. Overview of Custom Features for Home Assistant Cards

    main

    Custom Features for Home Assistant Cards allows you to call any Home Assistant action via card features. It provides highly customizable UI elements including buttons, dropdowns, inputs, selectors, sliders, spinboxes, and toggles.

    Key capabilities include:

    • Customizable UI: Add icons, labels, and custom CSS to features.
    • Advanced Button Interactions: Supports tap, double tap, hold actions, and momentary button modes.
    • Material Design 3: Includes MD3 variants that follow theme palette colors (works best with Material You themes).
    • Custom Features Card: A standalone card that acts as a vertical stack for custom feature rows, useful for creating feature-only interfaces.
  2. Use momentary button actions for dynamic URLs or logic

    main

    The button feature supports a momentary interaction pattern. By using momentary_start_action, momentary_repeat_action, and momentary_end_action, you can trigger different behaviors based on how long a user holds the button. For example, you can use the hold_secs variable in a url action to open a specific URL based on the duration of the press.

    - type: button
      entity_id: climate.downstairs_thermostat
      label: XKCD
      value_from_hass_delay: 5000
      momentary_end_action:
        action: url
        url_path: https://xkcd.com/{{ (1000 * hold_secs) | int }}
      value_attribute: state
  3. Configure Momentary Button Mode

    main

    Momentary mode is an alternative to standard tap/hold/double-tap interactions. When enabled, it disables all other interaction types for that button.

    • Momentary Start Action: Fired when the button is first pressed down.
    • Momentary End Action: Fired when the button is released.
    • Momentary Repeat Action: Fired when the button is held for a set duration.

    For momentary repeat and end actions, you can include the number of seconds the button has been held by using the hold_secs variable in a template.

  4. Supported Interaction Types and Timing

    main

    Custom features support three primary interaction types, though availability varies by feature type:

    • Tap: Supported by all features (Buttons, Selectors, Sliders, Toggles, etc.).
    • Double Tap: Supported by Buttons, Selector options, and Spinbox buttons. Note that defining a non-none double tap action introduces a 200ms delay to single tap actions.
    • Hold: Supported by Buttons, Selector options, and Spinbox buttons.

    Adjustable Timings

    You can customize the trigger thresholds for complex interactions:

    • Hold Time: The duration a button must be held before the action triggers (default: 500ms).
    • Double Tap Window: The time window to register a double tap before it is treated as a single tap (default: 200ms).
      • Warning: If you increase the Double tap window, ensure you increase Hold time by at least 100ms to prevent conflicts.
    • Repeat Delay: The delay between repetitions when a hold action is set to repeat (default: 100ms).
  5. Use the Custom Features Card as a standalone container

    main
    If you do not want to attach features to an existing parent card (like a Tile card), use the Custom Features Card. This card acts as a vertical stack for custom feature rows. You can increase the feature height or set the card to transparent to make the features appear as standalone UI elements.
  6. Configure General Feature Options and Templates

    main

    Every feature can be linked to an entity to track its internal state.

    Value Tracking:

    • Entity ID: If set, the feature tracks the entity's state or a specific attribute.
    • Value Template: If no entity is set, use the value template field to define the state (e.g., {{ value | float }}).
    • Templates: Use {{ value | float }} in styles and actions to access the current state.

    Special Attribute Logic:

    • brightness: Automatically converted from 0-255 to 0-100.
    • media_position: Updated twice a second using media_position_updated_at and media_duration when state is playing.
    • elapsed: Used for timer entities. Calculates elapsed time using duration, remaining, and finishes_at (or media_position logic) to provide accurate real-time updates.

    Haptics: Can be enabled/disabled at the individual feature level.

  7. Use Nunjucks templating in custom features

    main

    Almost all fields in custom features support Nunjucks templating (a JavaScript engine similar to Home Assistant's Jinja2). You can use templates to dynamically set labels, icons, units, and CSS styles.

    Available Variables

    • value: The current value of the feature.
    • unit: The current unit of the feature.
    • hold_secs: Used during momentary repeat or end actions.
    • checked: (For toggles) Boolean indicating if the toggle is on or off.
    • option: (For dropdowns and selectors) References the specific option being rendered.
    • config: References the feature's configuration. Use config.entity or config.attribute to access the entity ID or attribute with rendered templates. Other templated config fields can be accessed using the render function, e.g., {{ render(config.some_field) }}.
    • stateObj: Provides access to the parent card's information (entity ID, state, attributes, etc.). The structure follows the Home Assistant HassEntity type.
  8. Configure complex feature sets using service-call entries

    main

    The custom:service-call feature type allows you to group multiple interactive elements (entries) together. Each entry can be a different feature type (like button or slider) and can be configured to perform Home Assistant actions via tap_action, double_tap_action, hold_action, or momentary actions (momentary_start_action, momentary_end_action).

    Key capabilities include:

    • Dynamic Labels: Use Jinja2 templates in the label field to display entity states or attributes (e.g., label: '{{ states(config.entity) }}').
    • Custom Styling: Use the styles field to apply CSS to the :host element or specific sub-elements like .tooltip, .icon, or .label. You can use CSS variables like --color, --background, and --background-opacity to theme your features.
    • Template-driven Actions: Pass template values into action data, such as brightness_pct: '{{ value | int }}' for a slider.
    • Momentary Actions: Use momentary_start_action and momentary_end_action for controls like curtains or garage doors that require a press-and-hold behavior.
    features:
      - type: custom:service-call
        entries:
          - type: button
            entity_id: light.sunroom_ceiling
            tap_action:
              action: perform-action
              perform_action: light.turn_on
              data:
                entity_id: light.sunroom_ceiling
                color_name: red
          - type: slider
            entity_id: light.sunroom_ceiling
            value_attribute: brightness
            range:
              - 0
              - 100
            tap_action:
              action: perform-action
              perform_action: light.turn_on
              data:
                brightness_pct: '{{ value | int }}'
  9. How to use Custom Features in Home Assistant

    main

    To use this project:

    1. Install via HACS.
    2. In a dashboard, create a Tile Card (or any card supporting card features).
    3. Click Add feature and select Custom features row.

    Custom Features Row: All custom features must be encapsulated within a Custom features row. This container allows you to:

    • Add multiple features to a single row.
    • Apply overall CSS styles to the row.
    • Control feature widths using the flex-basis CSS property.

    Adding Features: Inside a row, use the add custom feature button to add individual features. Features can be reordered, copied, edited, or deleted.

    Row Styling: CSS styles for the row must be encapsulated in a selector, such as :host:

    :host {
      --mdc-icon-size: 32px;
    }

    Autofill: By default, features autofill with the parent entity's information (state, icon, unit of measurement). Disable this via the Autofill toggle if you need to manually define an entity or value.

  10. Configure Spinboxes for number increments

    main

    Spinboxes create Home Assistant-style number boxes with increment and decrement buttons.

    Behavior:

    • Users can increment/decrement the internal value using buttons.
    • Debounce time: The user-defined tap action fires only after the buttons are no longer pressed for a specified duration (default: 1000ms).
    • Update after action delay: Controls how long the spinbox waits before updating its internal value from Home Assistant (similar to sliders).
    • Repeat on hold: You can set the hold action to repeat in the Center tab to allow continuous incrementing/decrementing while holding the button.

    Best Practices: To prevent excessive Home Assistant calls, use an action that sets a value (e.g., number/input_number.set_value or climate.set_temperature) and use the value template variable to pass the current internal value to the action call. This allows the user to reach the desired value before a single update is sent.

    Customizing Buttons: You can override default behavior by changing the tab bar to Increment or Decrement. This converts the feature into a standard button feature and disables the default increment/decrement/debounce logic.

    # Conceptual usage for an action
    service: input_number.set_value
    target:
      entity_id: input_number.target_temp
    data:
      value: "{{ value }}"
  11. Apply CSS styles to custom features

    main

    Both the custom features row and individual features support custom CSS.

    Important: You must wrap your styles within a :host selector. You cannot set styles outside of a selector.

    :host {
      flex-basis: 200%;
      --color: red;
      --icon-color: blue;
    }

    Common CSS Classes

    Use these classes to target specific sub-elements within a feature:

    Class NameElement
    .rowThe custom features row containing all features
    .containerA container within the feature for organization
    .backgroundThe background of the feature
    .iconThe feature's icon
    .labelThe feature's label
    .thumbThe slider thumb element
    .activeThe slider active area trailing the thumb
    .tooltipThe slider tooltip

    General Style Properties

    These internal CSS attributes can be used within :host or specific classes:

    NameDescription
    flex-basisPercentage of the row the feature populates (default 100%)
    --feature-colorColor inherited from the card (e.g., tile icon color)
    --feature-heightHeight of the features (default 40px or 42px depending on HA version)
    --feature-border-radiusBorder radius (default 12px)
    --feature-button-spacingGap between custom features (default 12px)
    --colorColor of the custom feature
    --opacityOpacity of the custom feature (default 0.2)
    --icon-colorColor of the icon
    --label-colorColor of the string label
    --icon-filterFilter for the icon color
    --label-filterFilter for the label color
    --backgroundColor for the feature background
    --background-opacityOpacity of the feature background (default 0.2)
    :host {
      flex-basis: 200%;
    
      --color: red;
      --icon-color: blue;
    }
    
    .background {
      background: blue;
    }
    .icon {
      --mdc-icon-size: 32px;
    }
    .label {
      color: red;
    }
    .tooltip {
      --tooltip-label: '{{ (value / 60) | int }}:{{ 0 if (value - 60*((value / 60) | int)) < 10 else "" }}{{ (value - 60*((value / 60) | int) | int }}';
    }
  12. Use templates in Action Data and Target

    main

    The entire action, data, and target fields support YAML templating. This allows you to dynamically change service calls or parameters based on the feature's state.

    When using sliders or spinboxes, you must use the value variable within a template to access the current feature value in the action.

    action: light.turn_{{ iif(checked, 'on', 'off') }}
    data: |
      {% if checked %}
      brightness_pct: 100
      {% endif %}