Skip to main content

Dials

Dial actions are a combination of two parts of Stream Deck, the dial itself and a portion of the touch strip.

What is an Encoder?

The dial and portion of the touch strip that make up a dial action are collectively known as an "Encoder". Combined, they allow for your plugin to receive dial and touch events, as well as provide feedback on the touch strip in the form of layouts.

Screenshot of Stream Deck software highlighting an action slot

Layouts

Layouts are used to draw information about your actions on the touch display. Stream deck has a few built-in layouts, but you can also build your own custom layouts using JSON files included in your plugin folder. Layouts are composed of layout items that can be updated programmatically.

Built-in Layouts

There are several built-in layouts available when rendering information on the Stream Deck + touchscreen.

Preview of the built-in layout $X1. There is a title placeholder, and an icon placeholder
JSON file for pre-defined layout "$X1"
{
    "$schema": "https://schemas.elgato.com/streamdeck/plugins/layout.json",
    "id": "$X1",
    "items": [
        {
            "key": "title",
            "type": "text",
            "rect": [16, 10, 136, 24],
            "font": { "size": 16, "weight": 600 },
            "alignment": "left"
        },
        {
            "key": "icon",
            "type": "pixmap",
            "rect": [76, 40, 48, 48]
        }
    ]
}

Manifest

Built-in layouts can be used as an action's default layout by setting the Actions[].Encoder.layout property within the manifest. For example:

Manifest JSON file, with an action referencing a built-in layout
{
    "$schema": "https://schemas.elgato.com/streamdeck/plugins/manifest.json",
    "Actions": [
        {
            "Icon": "action-icon",
            "Name": "Action One",
            "Controllers": ["Encoder"],

            "Encoder": {
                "layout": "$B1"
            },
            "States": [
                {
                    "Image": "state-image"
                }
            ],
            "UUID": "come.elgato.test.one"
        }
    ],
    "Author": "Elgato",
    "Software": {
        "MinimumVersion": "6.6"
    }
    // ...
}

Programmatically

Built-in layouts can also be assigned to an instance of an action programmatically using the setFeedbackLayout function, for example:

Action class updating its layout to a built-in layout
import { action, SingletonAction, WillAppearEvent } from "@elgato/streamdeck";

@action({ UUID: "com.elgato.test.one" })
export class IncrementCounter extends SingletonAction {
	/**
	 * Occurs when the action will appear.
	 */
	override onWillAppear(ev: WillAppearEvent): Promise<void> {
		if (ev.action.isDial()) {
			return ev.action.setFeedbackLayout("$B1"); 
		}
	}
}

Custom Layouts

Custom layouts are composed of layout items provided in a JSON file located in the *.sdPlugin folder.

warning

Layouts have a canvas size of 200 × 100 px. If items fall outside of these bounds, Stream Deck will not render the layout.

Manifest

Custom layouts can be used as an action's default layout by setting the Actions[].Encoder.layout property within the manifest. For example:

Manifest JSON file, with an action referencing a custom layout file
{
    "$schema": "https://schemas.elgato.com/streamdeck/plugins/manifest.json",
    "Actions": [
        {
            "Icon": "action-icon",
            "Name": "Action One",
            "Controllers": ["Encoder"],

            "Encoder": {
                "layout": "custom-layout.json"
            },
            "States": [
                {
                    "Image": "state-image"
                }
            ],
            "UUID": "come.elgato.test.one"
        }
    ],
    "Author": "Elgato",
    "Software": {
        "MinimumVersion": "6.6"
    }
    // ...
}

Programmatically

Custom layouts can also be assigned to an instance of an action programmatically using the setFeedbackLayout function, for example:

Action class updating its layout to a custom layout file
import { action, SingletonAction, WillAppearEvent } from "@elgato/streamdeck";

@action({ UUID: "com.elgato.test.one" })
export class IncrementCounter extends SingletonAction {
	/**
	 * Occurs when the action will appear.
	 */
	override onWillAppear(ev: WillAppearEvent): Promise<void> {
		if (ev.action.isDial()) {
			return ev.action.setFeedbackLayout("custom-layout.json"); 
		}
	}
}

Debugging

You can debug your custom layouts using the CLI tool's validate command.

Terminal
streamdeck validate

For example, here is a layout in which the item would render outside the canvas.

Invalid custom layout
{
    "$schema": "https://schemas.elgato.com/streamdeck/plugins/layout.json",
    "id": "hello-world",
    "items": [
        {
            "key": "title",
            "type": "text",

            "rect": [100, 0, 136, 50], // x (100) + width (136) exceeds 200
            "font": { "size": 32, "weight": 600 },
            "alignment": "left"
        }
    ]
}

The CLI tool would provide the following output:

Layout validation output
8:13  error    items[0].rect[0] must not be outside of the canvas
8:13  error Width and height, relative to the x and y, must be within the 200x100 px canvas
warning

If a layout item is anticipated to render outside of the given bounds, Stream Deck will not render the layout and instead provide details in Stream Deck app logs.

Updating Layouts

You can update the values in a layout programmatically using the setFeedback function, by referencing layout items by their key. You can directly update the value of the item or set specific properties of the item. Properties not included in the payload will remain unchanged.

Action class updating a $B1 layout via value
import { action, DialUpEvent, SingletonAction } from "@elgato/streamdeck";

@action({ UUID: "com.elgato.layout-image-test.increment" })
export class IncrementCounter extends SingletonAction<CounterSettings> {
	/**
	 * Occurs when the user releases a dial.
	 */
	override onDialUp(ev: DialUpEvent<CounterSettings>): Promise<void> | void {

		ev.action.setFeedback({
			title: "Half way there",
		});
	}
}

/**
 * Settings for {@link IncrementCounter}.
 */
type CounterSettings = {
	count?: number;
	incrementBy?: number;
};
Action class updating a $B1 layout via properties
import { action, DialUpEvent, SingletonAction } from "@elgato/streamdeck";

@action({ UUID: "com.elgato.layout-image-test.increment" })
export class IncrementCounter extends SingletonAction<CounterSettings> {
	/**
	 * Occurs when the user releases a dial.
	 */
	override onDialUp(ev: DialUpEvent<CounterSettings>): Promise<void> | void {

		ev.action.setFeedback({
			indicator: {
				value: 50,
			},
		});
	}
}

/**
 * Settings for {@link IncrementCounter}.
 */
type CounterSettings = {
	count?: number;
	incrementBy?: number;
};
Stream Deck + touch display with updated layout values.

Reserved Layout Item Keys

Layouts utilize the key value of an item to identify said item, however there are a few reserved keys that can be overridden by the user.

  • title - As with key actions, users can set a custom title for dial/touchscreen actions, which will take precedence over the plugin provided title.
  • icon - As with key actions, users can set a custom icon for dial/touchscreen actions, which will take precedence over the plugin provided icon.

Trigger Descriptions

Trigger descriptions can help the user to understand what the encoder does in a particular dial action. This can be set in the manifest file using the Actions[].Encoder.TriggerDescriptions property.

Screenshot of Stream Deck software highlighting trigger descriptions
Manifest JSON file, with an action referencing a trigger description
{
    "Actions": [
        {
            "Icon": "action-icon",
            "Name": "Trigger Description Example",
            "Controllers": ["Encoder"],
            "Encoder": {
                "layout": "$A1",

                "TriggerDescription": {
                    "Push": "Play / Pause",
                    "Rotate": "Adjust Volume",
                    "Touch": "Play / Pause",
                    "LongTouch": "Skip Track"
                }
            }
        }
    ]
    // ...
}

Update Trigger Descriptions

You can programmatically update the trigger descriptions using the setTriggerDescription function.

Action class updating its trigger description
import { action, DialUpEvent, SingletonAction } from "@elgato/streamdeck";

@action({ UUID: "com.elgato.trigger-description-example.increment" })
export class IncrementCounter extends SingletonAction<CounterSettings> {
	/**
	 * Occurs when the user releases a dial.
	 */
	override onDialUp(ev: DialUpEvent<CounterSettings>): Promise<void> | void {

		ev.action.setTriggerDescription({
			push: "Increment counter",
			rotate: "Adjust increment",
			touch: "Increment counter",
			longTouch: "Reset counter",
		});
	}
}

/**
 * Settings for {@link IncrementCounter}.
 */
type CounterSettings = {
	count?: number;
	incrementBy?: number;
};

Events

In addition to the action events found on both keys and dials, dials also receive the following events in the form of overridable methods on the SingletonAction class.

onDialDown

Occurs when the user presses a dial (Stream Deck +). See also SingletonAction.onDialUp.

NB: For other action types see SingletonAction.onKeyDown.

function onDialDown?(ev: DialDownEvent): void | Promise<void>

Parameters

ev: DialDownEvent

Information about the event, including the source action and contextual payload information.

onDialRotate

Occurs when the user rotates a dial (Stream Deck +).

function onDialRotate?(ev: DialRotateEvent): void | Promise<void>

Parameters

ev: DialRotateEvent

Information about the event, including the source action and contextual payload information.

onDialUp

Occurs when the user releases a pressed dial (Stream Deck +). See also SingletonAction.onDialDown.

NB: For other action types see SingletonAction.onKeyUp.

function onDialUp?(ev: DialUpEvent): void | Promise<void>

Parameters

ev: DialUpEvent

Information about the event, including the source action and contextual payload information.

onTouchTap

Occurs when the user taps the touchscreen (Stream Deck +).

function onTouchTap?(ev: TouchTapEvent): void | Promise<void>

Parameters

ev: TouchTapEvent

Information about the event, including the source action and contextual payload information.

Commands

The following commands are available to dial actions.

tip

Some events are applicable to both dials and keys, such as onWillAppear. To invoke a dial-only command within these event handlers, you need to first assert the action is a dial using Action.isDial().

getSettings

Gets the settings associated this action instance.

function getSettings<U extends JsonObject>(): Promise<U>

setFeedback

Sets the feedback for the current layout associated with this action instance, allowing for the visual items to be updated. Layouts are a powerful way to provide dynamic information to users, and can be assigned in the manifest, or dynamically via Action.setFeedbackLayout.

The feedback payload defines which items within the layout will be updated, and are identified by their property name (defined as the key in the layout's definition). The values can either by a complete new definition, a string for layout item types of text and pixmap, or a number for layout item types of bar and gbar.

function setFeedback(feedback: FeedbackPayload): Promise<void>

Parameters

feedback: FeedbackPayload

Object containing information about the layout items to be updated.

setFeedbackLayout

Sets the layout associated with this action instance. The layout must be either a built-in layout identifier, or path to a local layout JSON file within the plugin's folder. Use in conjunction with Action.setFeedback to update the layout's current items' settings.

function setFeedbackLayout(layout: string): Promise<void>

Parameters

layout: string

Name of a pre-defined layout, or relative path to a custom one.

setImage

Sets the image to be display for this action instance within Stream Deck app.

NB: The image can only be set by the plugin when the the user has not specified a custom image.

function setImage(image?: string): Promise<void>

Parameters

image: string

Image to display; this can be either a path to a local file within the plugin's folder, a base64 encoded string with the mime type declared (e.g. PNG, JPEG, etc.), or an SVG string. When undefined, the image from the manifest will be used.

setSettings

Sets the settings associated with this action instance. Use in conjunction with Action.getSettings.

function setSettings<U extends JsonObject>(settings: U): Promise<void>

Parameters

settings: U

Settings to persist.

setTitle

Sets the title displayed for this action instance.

NB: The title can only be set by the plugin when the the user has not specified a custom title.

function setTitle(title: string): Promise<void>

Parameters

title: string

Title to display.

setTriggerDescription

Sets the trigger (interaction) descriptions associated with this action instance. Descriptions are shown within the Stream Deck application, and informs the user what will happen when they interact with the action, e.g. rotate, touch, etc. When descriptions is undefined, the descriptions will be reset to the values provided as part of the manifest.

NB: Applies to encoders (dials / touchscreens) found on Stream Deck + devices.

function setTriggerDescription(descriptions?: TriggerDescriptionOptions): Promise<void>

Parameters

descriptions: TriggerDescriptionOptions

Descriptions that detail the action's interaction.

showAlert

Temporarily shows an alert (i.e. warning), in the form of an exclamation mark in a yellow triangle, on this action instance. Used to provide visual feedback when an action failed.

function showAlert(): Promise<void>