TimeClock demos mirroring the MUI docs: basic usage, controlled vs uncontrolled values, disabled/readOnly, view configuration and 12h/24h format.

Time Clock

TimeClock demos mirroring the MUI docs: basic usage, controlled vs uncontrolled values, disabled/readOnly, view configuration and 12h/24h format.


Overview

TimeClock demos mirroring the MUI docs: basic usage, controlled vs uncontrolled values, disabled/readOnly, view configuration and 12h/24h format.

TimeClock is an inline clock-face time selector — no text input, popper, or modal; the user drags the hand or clicks the numbers to pick hours, minutes, and optionally seconds. It is a Community (free) component and the library's first Date & Time Pickers component (wrapping @mui/x-date-pickers 8.24.0 with the dayjs adapter), NOT a chart.

String <-> dayjs boundary: dayjs objects can't cross the Dash boundary, so values are exchanged as strings — full wall-time ISO ("2022-04-17T15:30:00") or time-only ("15:30" / "15:30:45"). Strings are parsed to dayjs on the way in; on the way out the value is formatted as local wall-time YYYY-MM-DDTHH:mm:ss (not toISOString(), to avoid a UTC shift).

Usage

from dash_mui_charts import TimeClock

TimeClock(
    id="clock",
    value="15:30:00",                       # controlled, in/out (wall-time ISO out)
    defaultValue="15:30:00",                # uncontrolled initial (use instead of value)
    views=["hours", "minutes", "seconds"],  # default ["hours", "minutes"]
    view="hours",                           # controlled view, in/out
    ampm=False,                             # force 12h/24h (omit = locale default)
    minutesStep=5,
    minTime="09:00", maxTime="18:00",
    disabled=False, readOnly=False,
    showViewSwitcher=True,
)

Outputs

value (wall-time ISO), view, and timeData: {"hours", "minutes", "seconds", "formatted" ("HH:mm:ss"), "event_timestamp"}.

@callback(Output("out", "children"), Input("clock", "timeData"))
def show(td):
    return td["formatted"] if td else "-"

Notes

boundary): shouldDisableTime, referenceDate, slots/slotProps. skipDisabled is intentionally not exposed — it belongs to the digital clock variants, not the analog TimeClock.

hand .MuiClockPointer-root + .MuiClockPointer-thumb + centre .MuiClock-pin, digits .MuiClockNumber-root / -selected, meridiem .MuiClock-amButton / -pmButton.

Related pages

views, 12h/24h)

two-way pairings with dmc.TimeInput / TimePicker / TimeGrid / DateTimePicker


Live examples

# File: docs/time_clock/demo.py

"""Time Clock demo — rendered on /time-clock via `.. exec::`.

Ported verbatim from the pre-migration pages/time_clock.py (same ids, same callbacks).
"""
import json
import dash_mantine_components as dmc
from dash import callback, Input, Output, ctx, no_update

from dash_mui_charts import TimeClock


# --------------------------------------------------------------------------- #
# Small layout helpers (theme-aware via Mantine)
# --------------------------------------------------------------------------- #
def demo_item(label, component):
    """A labelled clock, like MUI's <DemoItem>."""
    return dmc.Stack(
        [
            dmc.Text(label, size="sm", fw=600, c="dimmed"),
            dmc.Paper(component, withBorder=True, radius="md", p="xs",
                      style={"width": "fit-content"}),
        ],
        gap=6,
    )


def section(title, description, *children):
    return dmc.Stack(
        [
            dmc.Title(title, order=3),
            dmc.Text(description, size="sm", c="dimmed"),
            *children,
        ],
        gap="sm",
        mb="xl",
    )


# --------------------------------------------------------------------------- #
# Layout
# --------------------------------------------------------------------------- #
component = dmc.Container(
    [
        # --- 1. Basic usage --------------------------------------------------
        section(
            "1. Basic usage",
            "Uncontrolled — the component manages its own internal state.",
            dmc.Paper(
                TimeClock(id="tc-basic"),
                withBorder=True, radius="md", p="xs",
                style={"width": "fit-content"},
            ),
        ),

        # --- 2. Uncontrolled vs controlled ----------------------------------
        section(
            "2. Uncontrolled vs. controlled value",
            "Left clock is uncontrolled (defaultValue). Right clock is controlled — "
            "its value lives in Dash; the buttons push new values in, and every "
            "change flows back out.",
            dmc.Group(
                [
                    demo_item(
                        "Uncontrolled clock",
                        TimeClock(id="tc-uncontrolled",
                                  defaultValue="2022-04-17T15:30:00"),
                    ),
                    demo_item(
                        "Controlled clock",
                        TimeClock(id="tc-controlled",
                                  value="2022-04-17T15:30:00"),
                    ),
                ],
                align="flex-start",
                gap="xl",
            ),
            dmc.Group(
                [
                    dmc.Button("Set 09:00", id="tc-set-0900", size="xs",
                               variant="light"),
                    dmc.Button("Set 14:30", id="tc-set-1430", size="xs",
                               variant="light"),
                    dmc.Button("Set 18:45", id="tc-set-1845", size="xs",
                               variant="light"),
                ],
                gap="xs",
            ),
            dmc.Code(id="tc-controlled-out", block=True,
                     children="Pick a time on the controlled clock…"),
        ),

        # --- 3. Form props ---------------------------------------------------
        section(
            "3. Form props",
            "The component can be disabled or read-only.",
            dmc.Group(
                [
                    demo_item(
                        "disabled",
                        TimeClock(id="tc-disabled",
                                  defaultValue="2022-04-17T15:30:00",
                                  disabled=True),
                    ),
                    demo_item(
                        "readOnly",
                        TimeClock(id="tc-readonly",
                                  defaultValue="2022-04-17T15:30:00",
                                  readOnly=True),
                    ),
                ],
                align="flex-start",
                gap="xl",
            ),
        ),

        # --- 4. Views --------------------------------------------------------
        section(
            "4. Views",
            "Choose which views appear and in what order. By default only hours "
            "and minutes are enabled.",
            dmc.Group(
                [
                    demo_item(
                        '"hours", "minutes" and "seconds"',
                        TimeClock(id="tc-views-hms",
                                  views=["hours", "minutes", "seconds"]),
                    ),
                    demo_item(
                        '"hours"',
                        TimeClock(id="tc-views-h", views=["hours"]),
                    ),
                    demo_item(
                        '"minutes" and "seconds"',
                        TimeClock(id="tc-views-ms",
                                  views=["minutes", "seconds"]),
                    ),
                ],
                align="flex-start",
                gap="xl",
            ),
            dmc.Code(id="tc-views-out", block=True,
                     children="Pick on the hours/minutes/seconds clock…"),
        ),

        # --- 5. 12h / 24h format --------------------------------------------
        section(
            "5. 12h / 24h format",
            "The clock uses the locale's hour format by default. Force it with the "
            "ampm prop.",
            dmc.Group(
                [
                    demo_item(
                        "Locale default (enUS → 12h)",
                        TimeClock(id="tc-ampm-default",
                                  defaultValue="2022-04-17T15:30:00"),
                    ),
                    demo_item(
                        "AM/PM enabled",
                        TimeClock(id="tc-ampm-on",
                                  defaultValue="2022-04-17T15:30:00",
                                  ampm=True),
                    ),
                    demo_item(
                        "AM/PM disabled (24h)",
                        TimeClock(id="tc-ampm-off",
                                  defaultValue="2022-04-17T15:30:00",
                                  ampm=False),
                    ),
                ],
                align="flex-start",
                gap="xl",
            ),
        ),
    ],
    size="lg",
    px=0,
    py="md",
)


# --------------------------------------------------------------------------- #
# Callbacks
# --------------------------------------------------------------------------- #
@callback(
    Output("tc-controlled", "value"),
    Input("tc-set-0900", "n_clicks"),
    Input("tc-set-1430", "n_clicks"),
    Input("tc-set-1845", "n_clicks"),
    prevent_initial_call=True,
)
def set_controlled(_a, _b, _c):
    mapping = {
        "tc-set-0900": "09:00",
        "tc-set-1430": "14:30",
        "tc-set-1845": "18:45",
    }
    return mapping.get(ctx.triggered_id, no_update)


@callback(
    Output("tc-controlled-out", "children"),
    Input("tc-controlled", "value"),
    Input("tc-controlled", "timeData"),
    prevent_initial_call=True,
)
def show_controlled(value, time_data):
    return json.dumps({"value": value, "timeData": time_data}, indent=2)


@callback(
    Output("tc-views-out", "children"),
    Input("tc-views-hms", "timeData"),
    prevent_initial_call=True,
)
def show_views(time_data):
    if not time_data:
        return "Pick on the hours/minutes/seconds clock…"
    return json.dumps(time_data, indent=2)

:defaultExpanded: false :withExpandedButton: true


Source: /time-clock

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: