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.
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
| Field | Required | Default | Description |
|---|
domain | No | Entity’s domain | Home Assistant domain (light, switch, media_player, etc.) |
service | Yes | - | Service to call (toggle, turn_on, set_value, etc.) |
target | No | { entity_id: <entity_id> } | Service target specification |
data_field | Scroll 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"
}
}
{
"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 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
- Active Check: Scroll actions only work when
model.active is true (entity is on/open/idle)
- Current Position: Reads current value from entity attributes
- Scroll Input: Mouse wheel or touchpad scroll adjusts position
- Visual Feedback: Highlight rectangle shows current level
- 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.
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
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
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 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