Skip to main content
The Home Assistant Plasmoid provides two types of interactive actions for controlling entities: click actions and scroll actions. These allow you to control your smart home directly from the widget.

Action Types

Default Actions (Click)

Triggered by clicking an entity tile. Used for discrete actions like toggling lights or activating scenes.

Scroll Actions

Triggered by scrolling on an active entity tile. Used for continuous adjustments like dimming lights or changing volume.
Scroll actions are only available when the entity is in an active state (on, open, or idle).

Action Configuration

Both action types share the same configuration structure:
{
  domain: string,      // Service domain (e.g., "light")
  service: string,     // Service name (e.g., "turn_on")
  target?: {           // Optional: defaults to entity itself
    entity_id: string
  },
  data_field?: string  // Required for scroll actions
}

Field Descriptions

FieldRequiredDefaultDescription
domainNoEntity’s domainHome Assistant domain (light, switch, media_player, etc.)
serviceYes-Service to call (toggle, turn_on, set_value, etc.)
targetNo{ entity_id: <entity_id> }Service target specification
data_fieldScroll only-Attribute name for scroll adjustment (brightness, volume_level, etc.)

Click Actions

Click actions are configured via the default_action field.

Implementation

From Entity.qml:
Loader {
    active: !!default_action
    sourceComponent: Component {
        Connections {
            readonly property string tip: `Click to ${format(default_action.service)}`
            target: control
            function onClicked() {
                ha.callService(default_action)
            }
        }
    }
}

Common Examples

Toggle Light

{
  "entity_id": "light.living_room",
  "default_action": {
    "service": "toggle"
  }
}

Turn On Switch

{
  "entity_id": "switch.fan",
  "default_action": {
    "service": "turn_on"
  }
}

Control Media Player

{
  "entity_id": "media_player.speaker",
  "default_action": {
    "service": "media_play_pause"
  }
}

Open Cover

{
  "entity_id": "cover.blinds",
  "default_action": {
    "service": "open_cover"
  }
}

Activate Scene

{
  "entity_id": "scene.movie_time",
  "default_action": {
    "service": "turn_on"
  }
}

Scroll Actions

Scroll actions enable continuous value adjustment through mouse wheel or touchpad scrolling.

Implementation

From Entity.qml:
Loader {
    active: model.active && !!scroll_action
    sourceComponent: Component {
        Item {
            readonly property string tip: `Scroll to adjust ${format(scroll_action.data_field)}`
            readonly property var scrollAttributeField: fields[scroll_action.domain + scroll_action.service + scroll_action.data_field]
            readonly property var max: scrollAttributeField?.number.max || 1
            readonly property var min: scrollAttributeField?.number.min || 0
            property real position: (attributes[scroll_action.data_field] - min) / (max - min)
            
            WheelHandler {               
                acceptedDevices: PointerDevice.TouchPad | PointerDevice.Mouse
                orientation: Qt.Vertical
                onWheel: e => {
                    const p = position + e.angleDelta.y / 360
                    position = p > 1 ? 1 : p < 0 ? 0 : p
                }
                onActiveChanged: !active && ha.callService(scroll_action, { 
                    [scroll_action.data_field]: position * (max - min) + min 
                })
            }
            
            Rectangle {
                radius: 3
                x: 1
                y: 1
                height: parent.height - 2 * y
                width: position * (parent.width - 2 * x)
                color: Kirigami.Theme.highlightColor
                opacity: 0.6
            }
        }
    }
}

How It Works

  1. Active Check: Scroll actions only work when model.active is true (entity is on/open/idle)
  2. Current Position: Reads current value from entity attributes
  3. Scroll Input: Mouse wheel or touchpad scroll adjusts position
  4. Visual Feedback: Highlight rectangle shows current level
  5. Service Call: When scrolling stops, sends new value to Home Assistant
Scroll actions require entities to be in an active state. Inactive entities (off, closed) will not respond to scroll.

Field Metadata

The plasmoid fetches service field definitions to determine min/max values:
function fetchFieldsInfo() {
    if (!items.length) return
    ha.getServices().then(s => {
        fields = items.reduce((a, i) => {
            if (i.scroll_action) {
                const field = i.scroll_action.data_field
                const key = i.scroll_action.domain + i.scroll_action.service + field
                const serviceFields = s[i.scroll_action.domain][i.scroll_action.service].fields
                a[key] = (serviceFields[field] || serviceFields.advanced_fields.fields[field])?.selector
            }
            return a
        },{})
    })
}
This provides:
  • Minimum value for the field
  • Maximum value for the field
  • Field type (number, percentage, etc.)

Common Examples

Dimmer (Brightness)

{
  "entity_id": "light.bedroom",
  "default_action": {
    "service": "toggle"
  },
  "scroll_action": {
    "service": "turn_on",
    "data_field": "brightness"
  }
}
Behavior:
  • Click: Toggle light on/off
  • Scroll (when on): Adjust brightness (0-255)
  • Visual: Progress bar shows brightness level

Volume Control

{
  "entity_id": "media_player.speaker",
  "attribute": "volume_level",
  "default_action": {
    "service": "media_play_pause"
  },
  "scroll_action": {
    "service": "volume_set",
    "data_field": "volume_level"
  }
}
Behavior:
  • Click: Play/pause media
  • Scroll (when playing): Adjust volume (0.0-1.0)
  • Display: Shows current volume level

Climate Temperature

{
  "entity_id": "climate.thermostat",
  "attribute": "temperature",
  "unit": "°C",
  "default_action": {
    "service": "turn_on"
  },
  "scroll_action": {
    "service": "set_temperature",
    "data_field": "temperature"
  }
}
Behavior:
  • Click: Turn on/off
  • Scroll (when on): Adjust target temperature
  • Display: Shows target temperature

Cover Position

{
  "entity_id": "cover.blinds",
  "attribute": "current_position",
  "unit": "%",
  "default_action": {
    "service": "toggle"
  },
  "scroll_action": {
    "service": "set_cover_position",
    "data_field": "position"
  }
}
Behavior:
  • Click: Open/close
  • Scroll (when open): Adjust position (0-100%)
  • Display: Shows current position

Fan Speed

{
  "entity_id": "fan.bedroom",
  "attribute": "percentage",
  "unit": "%",
  "default_action": {
    "service": "toggle"
  },
  "scroll_action": {
    "service": "set_percentage",
    "data_field": "percentage"
  }
}

Visual Feedback

Tooltips

Hovering over an entity shows available actions:
PlasmaComponents3.ToolTip {
    visible: control.hovered && text
    text: actions.map(c => c.item.tip).join("\n")
}
Example:
Click to toggle
Scroll to adjust brightness

Scroll Progress Indicator

Active scroll actions show a highlight overlay indicating the current level:
Rectangle {
    radius: 3
    width: position * (parent.width - 2)
    color: Kirigami.Theme.highlightColor
    opacity: 0.6
}
The highlight width represents the current value as a percentage of min-max range.

Active State Indication

Active entities (on/open/idle) are displayed with a pressed button state:
PlasmaComponents3.Button {
    down: model.active
}

Action Validation

Automatic Defaults

Missing configuration is automatically filled:
o[Symbol.for(name)] = !action?.service ? null : { 
    service: action.service,
    domain: action.domain || o.domain,           // Default to entity domain
    target: action.target || { entity_id: o.entity_id },  // Default to entity
    data_field: action.data_field
}

Domain Compatibility

When entity ID changes, actions are validated:
function updateAction(o, name) {
    if (!o[name]) return
    if (o.domain !== o[name].domain) return o[name] = null  // Disable incompatible action
    o[name].target.entity_id = o.entity_id    
}
If you configure a light entity with a “media_player” domain action, the action will be automatically disabled due to domain mismatch.

Scroll Sensitivity

Scroll sensitivity is fixed at 1/360th of the range per degree:
const p = position + e.angleDelta.y / 360
For a typical scroll wheel:
  • Each notch ≈ 15°
  • Each notch changes value by ≈ 4.2%
  • Full 0-100% range requires ≈ 24 notches

Service Call Timing

Service calls are only sent when scrolling stops:
onActiveChanged: !active && ha.callService(scroll_action, { 
    [scroll_action.data_field]: position * (max - min) + min 
})
This prevents flooding Home Assistant with rapid updates during scrolling.
Combine click and scroll actions for optimal control: click for quick on/off, scroll for fine adjustment when active.

Complete Configuration Example

A fully configured dimmable light with notifications:
{
  "entity_id": "light.bedroom",
  "name": "Bedroom Light",
  "icon": "mdi:ceiling-light",
  "attribute": "brightness",
  "unit": "%",
  "notify": false,
  "default_action": {
    "service": "toggle"
  },
  "scroll_action": {
    "service": "turn_on",
    "data_field": "brightness"
  }
}
Features:
  • Display: Shows brightness percentage
  • Click: Toggles light on/off
  • Scroll: Adjusts brightness (0-255, displayed as percentage)
  • Tooltip: “Click to toggle” / “Scroll to adjust brightness”
  • Visual: Progress bar showing brightness when on