Gauge

A collection of gauge, knob, thermostat, joystick, and display components for Dash.

Installation

Visit GitHub Repo

pip install dash-gauge

Introduction

The dash-gauge package provides a suite of interactive and visually appealing components to enhance your Plotly Dash dashboards. Built as wrappers around popular React libraries, this collection includes:

This page documents each component included in the suite.

# File: docs/dash_gauge/introduction_example.py

import dash
from dash import html, callback, Input, Output
import dash_gauge as dg
import dash_mantine_components as dmc

# app = dash.Dash(__name__) # Define app in your main docs entry point

component = dmc.Container([
    dmc.Title("Dash Gauge Component Suite Showcase", order=2, ta="center", mb="lg"),

    dmc.SimpleGrid(
        cols={"base": 1, "sm": 2, "lg": 3},
        spacing="lg",
        verticalSpacing="lg",
        children=[
            # 1. DashGauge Example
            dmc.Paper(
                p="md", shadow="sm", withBorder=True, children=[
                    dmc.Stack([
                        dmc.Text("DashGauge (Semicircle)", fw=500, ta="center"),
                        dmc.Center(
                            dg.DashGauge(
                                id="intro-gauge",
                                type="semicircle",
                                value=65,
                                minValue=0,
                                maxValue=100,
                                style={'width': '90%'} # Adjust width as needed
                            )
                        )
                    ])
                ]
            ),

            # 2. DashRotaryKnob Example
            dmc.Paper(
                p="md", shadow="sm", withBorder=True, children=[
                    dmc.Stack([
                        dmc.Text("DashRotaryKnob", fw=500, ta="center"),
                        dmc.Center(
                            dg.DashRotaryKnob(
                                id="intro-knob",
                                skinName="s12", # Choose a visually interesting skin
                                value=30,
                                min=0,
                                max=100,
                                style={"width": "100px", "height": "100px"} # Explicit size
                            )
                        ),
                        dmc.Text("Value: --", id="intro-knob-output", ta="center", size="sm", c="dimmed")
                    ])
                ]
            ),

            # 3. DashThermostat Example
            dmc.Paper(
                p="md", shadow="sm", withBorder=True, children=[
                    dmc.Stack([
                        dmc.Text("DashThermostat", fw=500, ta="center"),
                        dmc.Space(h=20),
                        dmc.Center(
                            dg.DashThermostat(
                                id="intro-thermostat",
                                value=21,
                                min=5,
                                max=35,
                                valueSuffix="°C",
                                style={'width': '200px', 'height': '300px'} # Control size
                            )
                        )
                    ])
                ]
            ),

            # 4. DashRCJoystick Example
            dmc.Paper(
                p="md", shadow="sm", withBorder=True, children=[
                    dmc.Stack([
                        dmc.Text("DashRCJoystick", fw=500, ta="center"),
                        dmc.Center(
                            dg.DashRCJoystick(
                                id='intro-joystick',
                                directionCountMode='Nine',
                                baseRadius=60, # Slightly smaller for grid
                                controllerRadius=30,
                            )
                        ),
                        dmc.Text("Direction: Center", id="intro-joystick-direction", ta="center", size="sm", c="dimmed"),
                        dmc.Text("Angle: N/A", id="intro-joystick-angle", ta="center", size="sm", c="dimmed"),
                        dmc.Text("Distance: 0.00", id="intro-joystick-distance", ta="center", size="sm", c="dimmed"),
                    ])
                ]
            ),
        ]
    )
], fluid=True, pt="xl", pb="xl")


# --- Callbacks ---

@callback(
    Output("intro-knob-output", "children"),
    Input("intro-knob", "value")
)
def update_intro_knob_output(value):
    if value is None:
        return "Value: --"
    return f"Value: {value:.1f}"

@callback(
    Output('intro-joystick-direction', 'children'),
    Output('intro-joystick-angle', 'children'),
    Output('intro-joystick-distance', 'children'),
    Input('intro-joystick', 'direction'),
    Input('intro-joystick', 'angle'),
    Input('intro-joystick', 'distance')
)
def update_intro_joystick_output(direction, angle, distance):
    angle_str = f"Angle: {angle:.1f}°" if angle is not None else "Angle: N/A"
    distance_str = f"Distance: {distance:.2f}" if distance is not None else "Distance: N/A"
    direction_str = f"Direction: {direction}" if direction is not None else "Direction: N/A"
    return direction_str, angle_str, distance_str

# Add this section if running this file standalone for testing
# if __name__ == "__main__":
#     app = dash.Dash(__name__)
#     app.layout = component
#     app.run_server(debug=True)

DashGauge

Displays a value on a customizable gauge. Supports different styles, color ranges, sub-arcs, custom labels, and pointers. Ideal for visualizing KPIs, sensor readings, or progress metrics.

# File: docs/dash_gauge/gauge_example.py

import dash
from dash import html, dcc, callback, Input, Output
import dash_gauge as dg
import dash_mantine_components as dmc

# Based on usage_gauge.py

component = dmc.Container([
    dmc.Title("DashGauge Examples", order=3, ta="center", mb="lg"),
    dmc.SimpleGrid(
        cols={"base": 1, "sm": 1, "lg": 3},
        spacing="lg",
        children=[
            dmc.Paper(p="md", shadow="sm", withBorder=True, children=dmc.Stack([
                dmc.Text("Basic Gauge", fw=500, ta="center"),
                dmc.Center(
                    dg.DashGauge(
                        id="basic-gauge-docs",
                        value=50,
                        style={'width': '90%'}
                    )
                )
            ])),
            dmc.Paper(p="md", shadow="sm", withBorder=True, children=dmc.Stack([
                dmc.Text("Temperature Gauge (Semicircle)", fw=500, ta="center"),
                dmc.Center(
                    dg.DashGauge(
                        id="temperature-gauge-docs",
                        type="semicircle",
                        value=22.5,
                        minValue=10,
                        maxValue=35,
                        arc={
                            "width": 0.2, "padding": 0.005, "cornerRadius": 1,
                            "subArcs": [
                                {"limit": 15, "color": "#EA4228", "showTick": True, "tooltip": {"text": "Too low!"}},
                                {"limit": 17, "color": "#F5CD19", "showTick": True, "tooltip": {"text": "Low"}},
                                {"limit": 28, "color": "#5BE12C", "showTick": True, "tooltip": {"text": "OK"}},
                                {"limit": 30, "color": "#F5CD19", "showTick": True, "tooltip": {"text": "High"}},
                                {"color": "#EA4228", "tooltip": {"text": "Too high!"}}
                            ]
                        },
                        pointer={"color": "#345243", "length": 0.80, "width": 15},
                        labels={"valueLabel": {"style": {"fontSize": "30px"}}}, # Simplified labels
                        style={'width': '90%'}
                    )
                )
            ])),
            dmc.Paper(p="md", shadow="sm", withBorder=True, children=dmc.Stack([
                dmc.Text("Bandwidth Gauge (Radial)", fw=500, ta="center"),
                dmc.Center(
                    dg.DashGauge(
                        id="bandwidth-gauge-docs",
                        type="radial", # Changed type for variety
                        value=900,
                        maxValue=3000,
                        arc={
                            "nbSubArcs": 150,
                            "colorArray": ["#5BE12C", "#F5CD19", "#EA4228"],
                            "width": 0.3, # Adjusted width for radial
                            "padding": 0.003
                        },
                         style={'width': '90%'}
                    )
                )
            ])),
        ]
    ),
    dmc.Space(h="xl"),
    dmc.Paper(p="md", shadow="sm", withBorder=True, children=dmc.Stack([
        dmc.Text("Interactive Gauge", fw=500, ta="center"),
        dmc.Text("Use the slider to update the gauge value:", size="sm", ta="center"),
        dmc.Slider(
            id="gauge-slider-docs",
            min=0, max=100, step=1, value=40,
            labelTransitionProps={
                "transition": "skew-down",
                "duration": 150,
                "timingFunction": "linear",
            },
        ),
        dmc.Center(
            dg.DashGauge(
                id="interactive-gauge-docs",
                type="radial",
                value=50, # Initial value linked to slider
                arc={
                    "colorArray": ["#5BE12C", "#EA4228"],
                    "subArcs": [{"limit": 10}, {"limit": 30}, {}, {}, {}],
                    "padding": 0.02,
                    "width": 0.3
                },
                pointer={"elastic": True, "animationDelay": 0},
                labels={
                    "tickLabels": {"type": "inner", "ticks": [{"value": i} for i in range(20, 101, 20)]}
                },
                 style={'width': '300px', 'marginTop': '20px'} # Control size
            )
        )
    ]))
], fluid=True)

@callback(
    Output("interactive-gauge-docs", "value"),
    Input("gauge-slider-docs", "value")
)
def update_gauge_docs(value):
    return value

DashGauge Props

PropTypeDefaultDescription
idstring-Component ID for Dash callbacks.
valuenumber33The value the gauge should indicate.
typestring'grafana'Style of the gauge. Choices: 'grafana', 'semicircle', 'radial'.
minValuenumber0Minimum value of the gauge scale.
maxValuenumber100Maximum value of the gauge scale.
classNamestringdash-gaugeCSS class name for the component.
styleobject{}Inline CSS styles for the component.
marginInPercentnumber or objectundefinedSets the margin for the chart inside the SVG. Can be a single number or {top, bottom, left, right}.
arcobject{}Configuration for the gauge arc (e.g., width, padding, cornerRadius, colorArray, subArcs, gradient). See usage_gauge.py for details.
pointerobject{}Configuration for the gauge pointer/needle (e.g., type, color, length, width, animate, elastic). See usage_gauge.py for details.
labelsobject{}Configuration for value and tick labels (e.g., valueLabel, tickLabels, formatTextValue, hideMinMax). See usage_gauge.py for details.
setPropsfunc-Dash-assigned callback function.

Note: For detailed examples of arc, pointer, and labels configurations, please refer to the usage_gauge.py file in the GitHub repository.


DashRotaryKnob

An interactive knob component, useful for selecting values within a range (e.g., volume, tuning). Comes with multiple visual skins from the react-rotary-knob-skin-pack.

# File: docs/dash_gauge/knob_example.py

import dash
from dash import html, dcc, callback, Input, Output, State
import dash_gauge as dg
import dash_mantine_components as dmc

# Based on usage_rotary_knob.py

component = dmc.Container([
    dmc.Title("DashRotaryKnob Example", order=3, ta="center", mb="lg"),
    dmc.Grid(
        gutter="xl",
        children=[
            dmc.GridCol(span={"md": 5, "sm": 12}, children=dmc.Stack(align="center", children=[
                dmc.Text("Interactive Knob", fw=500),
                dmc.Text(id="knob-value-display-docs", size="lg", mt="sm"),
                dg.DashRotaryKnob(
                    id="interactive-knob-docs",
                    skinName="s10",
                    value=50,
                    min=0,
                    max=100,
                    # format="{value}%", # Formatting might be better handled in display callback
                    style={"width": "150px", "height": "150px"} # Adjust size
                ),
            ])),
            dmc.GridCol(span={"md": 7, "sm": 12}, children=dmc.Stack([
                dmc.Text("Controls", fw=500),
                dmc.Slider(
                    id="knob-slider-docs",
                    label="Adjust with slider",
                    min=0, max=100, step=1, value=50,
                    marks=[{"value": i, "label": str(i)} for i in range(0, 101, 20)],
                    mb="lg"
                ),
                dmc.Select(
                    id="skin-selector-docs",
                    label="Change skin",
                    data=[{"label": f"Skin s{i}", "value": f"s{i}"} for i in range(1, 19)],
                    value="s10",
                    clearable=False,
                     mb="lg"
                ),

            ]))
        ]
    )
], fluid=True)

@callback(
    Output("knob-value-display-docs", "children"),
    Input("interactive-knob-docs", "value")
)
def update_knob_value_display_docs(value):
     if value is None:
        return "Current value: --"
     return f"Current value: {value:.1f}"

@callback(
    Output("interactive-knob-docs", "value"),
    Input("knob-slider-docs", "value"),
)
def update_knob_from_slider_docs(value):
    return value

@callback(
    Output("interactive-knob-docs", "skinName"),
    Input("skin-selector-docs", "value"),
)
def update_knob_skin_docs(skin_name):
    return skin_name

DashRotaryKnob Props

PropTypeDefaultDescription
idstring-Component ID for Dash callbacks.
valuenumber0The current value of the knob. Updated via interaction or callbacks.
minnumber0Minimum value of the knob.
maxnumber100Maximum value of the knob.
stepnumber1Increment/decrement step size.
skinNamestring's1'Selects the visual appearance (e.g., 's1', 's5', 's10', up to 's18'). See repository for examples.
preciseModebooleantrueIf true, requires Shift key + drag for fine adjustments.
unlockDistancenumber0Degrees the mouse must move vertically to "unlock" the knob for rotation.
classNamestring''CSS class name for the component.
styleobject{}Inline CSS styles for the component.
setPropsfunc-Dash-assigned callback function.

Note: Explore all 18 skins by changing the skinName prop! See usage_rotary_knob.py for an interactive example. Only skins 1 & 10-15 look good 🤷‍ "no idea why the other skins don't alin correctly".


DashThermostat

A component mimicking a thermostat interface for setting a target value, typically temperature.

# File: docs/dash_gauge/thermostat_example.py

import dash
from dash import html, dcc, callback, Input, Output, State
import dash_gauge as dg
import dash_mantine_components as dmc

# Based on usage_thermostat.py, but simplified for docs

# Define some example colors
cool_colors = ['#dae8eb', '#2c8e98']
heat_colors = ['#cfac48', '#cd5401']

component = dmc.Container([
    dmc.Title("DashThermostat Example", order=3, ta="center", mb="lg"),
    dmc.Grid(
        gutter="xl",
        children=[
            dmc.GridCol(span={"md": 6, "sm": 12}, children=dmc.Stack(align="center", children=[
                 dmc.Text("Thermostat Control", fw=500),
                 dmc.Space(h=20),
                 dg.DashThermostat(
                    id='thermostat-docs',
                    value=21,
                    min=5,
                    max=35,
                    valueSuffix='°C',
                    track={'colors': cool_colors}, # Start with cool colors
                    style={'width': '250px', 'height': '350px', 'marginBottom': '20px'},
                 )
            ])),
             dmc.GridCol(span={"md": 6, "sm": 12}, children=dmc.Stack([
                 dmc.Text("Controls", fw=500),
                 dmc.Text("Set Temperature:", size="sm"),
                 dmc.Slider(
                     id="thermostat-slider-docs",
                     min=5, max=35, step=0.5, value=21,
                     marks=[{"value": v, "label": f"{v}°"} for v in range(5, 36, 5)],
                     style={"maxWidth": 300},
                     mb="lg"
                 ),
                 dmc.Text("Current Setting:", size="sm"),
                 dmc.Title(id="thermostat-value-display-docs", order=4, ta="center"),
                 dmc.Space(h="lg"),
                 dmc.Text("Toggle Disabled:", size="sm"),
                 dmc.Switch(id="thermostat-disable-switch-docs", label="Disable Thermostat", checked=False),
                 dmc.Space(h="lg"),
                 dmc.Text("Change Track Color:", size="sm"),
                  dmc.SegmentedControl(
                    id="thermostat-color-switch-docs",
                    value="cool",
                    data=[
                        {"label": "Cool Mode", "value": "cool"},
                        {"label": "Heat Mode", "value": "heat"},
                    ],
                    fullWidth=True,
                    mb="md",
                ),
             ]))
        ]
    )
], fluid=True)

@callback(
    Output('thermostat-docs', 'value'),
    Input('thermostat-slider-docs', 'value')
)
def update_thermostat_from_slider(value):
    return value

@callback(
    Output('thermostat-value-display-docs', 'children'),
    Input('thermostat-docs', 'value')
)
def display_thermostat_value(value):
    if value is None:
        return "-- °C"
    return f"{value:.1f} °C"

@callback(
    Output('thermostat-docs', 'disabled'),
    Input('thermostat-disable-switch-docs', 'checked')
)
def toggle_thermostat_disabled(checked):
    return checked

@callback(
    Output('thermostat-docs', 'track'),
    Input('thermostat-color-switch-docs', 'value'),
    State('thermostat-docs', 'track') # Get current track state if needed
)
def update_thermostat_track_color(mode, current_track):
    # Ensure track is a dictionary before modifying
    track_config = current_track if isinstance(current_track, dict) else {}
    if mode == 'cool':
        track_config['colors'] = cool_colors
    elif mode == 'heat':
        track_config['colors'] = heat_colors
    # Add other track properties if they exist, e.g., thickness
    # track_config['thickness'] = current_track.get('thickness', 0.2) # Example
    return track_config

DashThermostat Props

PropTypeDefaultDescription
idstring-Component ID for Dash callbacks.
valuenumberRequiredThe current set value (e.g., temperature). Updated via interaction or callbacks.
minnumber0Minimum value of the thermostat scale.
maxnumber100Maximum value of the thermostat scale.
valueSuffixstring'°'Text to display after the value (e.g., '°C', '°F', '%).
disabledbooleanfalseIf true, disables user interaction with the thermostat.
handleobjectundefinedConfiguration object for the draggable handle (e.g., size, colors). See react-thermostat docs.
trackobjectundefinedConfiguration object for the background track (e.g., colors, thickness, markers). See react-thermostat docs.
classNamestring''CSS class name for the component.
styleobject{}Inline CSS styles for the component. Note: Component has min-width/height defaults.
setPropsfunc-Dash-assigned callback function.

Note: The usage_thermostat.py example demonstrates complex interaction with custom styling and mode switching. It may require CSS files placed in an assets folder.


DashRCJoystick

A virtual joystick component that reports direction, angle, and distance based on user interaction. Useful for controlling elements in simulations, games, or robotics dashboards.

# File: docs/dash_gauge/joystick_example.py

import dash
from dash import html, dcc, callback, Input, Output, State
import dash_gauge as dg
import dash_mantine_components as dmc

# Based on usage_rc_joystick.py

component = dmc.Container([
    dmc.Title("DashRCJoystick Example", order=3, ta="center", mb="lg"),
    dmc.Grid(
        gutter="xl",
        children=[
            # Left side: Joystick Component
            dmc.GridCol(span={"md": 5, "sm": 12}, children=dmc.Stack(align="center", children=[
                dmc.Text("Interactive Joystick", fw=500),
                dg.DashRCJoystick(
                    id='my-joystick-docs',
                    directionCountMode='Nine', # Default to Nine for demo
                    baseRadius=75,
                    controllerRadius=35,
                    style={'marginTop': '20px'} # Add some space
                ),
            ])),

            # Right side: Displaying Joystick State & Controls
            dmc.GridCol(span={"md": 7, "sm": 12}, children=dmc.Stack([
                dmc.Text("Joystick State", fw=500),
                dmc.Text(id='joystick-output-direction-docs', size="sm"),
                dmc.Text(id='joystick-output-angle-docs', size="sm"),
                dmc.Text(id='joystick-output-distance-docs', size="sm"),
                dmc.Divider(my="md"),
                dmc.RadioGroup(
                    [dmc.Radio(label, value=value) for label, value in
                     [('5 Directions', 'Five'), ('9 Directions', 'Nine')]],
                    id='direction-mode-selector-docs',
                    value='Nine', # Initial value matches component
                    label="Direction Mode",
                    size="sm",
                    mb="md",
                ),
                dmc.Text("Base Radius:", size="sm", fw=500),
                dmc.Slider(
                    id='base-radius-slider-docs', min=50, max=150, step=5, value=75,
                    marks=[{"value": i, "label": str(i)} for i in range(50, 151, 25)],
                    mb="md"
                ),
                dmc.Text("Controller Radius:", size="sm", fw=500),
                dmc.Slider(
                    id='controller-radius-slider-docs', min=20, max=70, step=5, value=35,
                    marks=[{"value": i, "label": str(i)} for i in range(20, 71, 10)],
                    mb="md"
                 ),
            ]))
        ])
], fluid=True)


# Callback to display joystick state changes
@callback(
    Output('joystick-output-direction-docs', 'children'),
    Output('joystick-output-angle-docs', 'children'),
    Output('joystick-output-distance-docs', 'children'),
    Input('my-joystick-docs', 'direction'),
    Input('my-joystick-docs', 'angle'),
    Input('my-joystick-docs', 'distance')
)
def update_joystick_output_docs(direction, angle, distance):
    angle_str = f"Angle: {angle:.1f}°" if angle is not None else "Angle: N/A (Center)"
    distance_str = f"Distance: {distance:.2f}" if distance is not None else "Distance: N/A"
    direction_str = f"Direction: {direction}" if direction is not None else "Direction: N/A"
    return direction_str, angle_str, distance_str

# Callback to update joystick configuration from controls
@callback(
    Output('my-joystick-docs', 'directionCountMode'),
    Output('my-joystick-docs', 'baseRadius'),
    Output('my-joystick-docs', 'controllerRadius'),
    Input('direction-mode-selector-docs', 'value'),
    Input('base-radius-slider-docs', 'value'),
    Input('controller-radius-slider-docs', 'value'),
)
def update_joystick_config_docs(direction_mode, base_radius, controller_radius):
    return direction_mode, base_radius, controller_radius

DashRCJoystick Props

PropTypeDefaultDescription
idstring-Component ID for Dash callbacks.
baseRadiusnumber75Radius of the joystick's static base circle.
controllerRadiusnumber35Radius of the movable controller knob.
directionCountModestring'Five'Determines the reported directions. Choices: 'Five' (Center, Top, Bottom, Left, Right), 'Nine' (includes diagonals).
insideModebooleanfalseIf true, the controller knob stays within the base radius.
throttlenumber0Throttle time in milliseconds for onChange events. 0 means no throttle.
classNamestring''CSS class name for the container.
styleobject{}Inline CSS styles for the container.
controllerClassNamestringundefinedAdditional CSS class for the controller knob.
Read-only Props(These props are updated by the component and read in callbacks)
anglenumberundefined[Readonly] Current angle of the joystick (degrees). undefined when centered.
directionstring'Center'[Readonly] Current direction string (e.g., 'Top', 'BottomLeft', 'Center'). Possible values depend on directionCountMode.
distancenumber0[Readonly] Current distance of the controller from the center (normalized 0-1 based on baseRadius).
setPropsfunc-Dash-assigned callback function.

Note: See usage_rc_joystick.py for an example controlling the joystick's appearance and reading its state.


Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: