Skip to content

Examples

Date Picker

DatePickerApp ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔    -  -   ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

from textual.app import App, ComposeResult
from textual_timepiece.pickers import DatePicker


class DatePickerApp(App[None]):

    def compose(self) -> ComposeResult:
        yield DatePicker()

    def on_date_picker_date_changed(self, message: DatePicker.DateChanged) -> None:
        message.stop()
        if message.date:
            msg = f"Date changed to {message.date.format_common_iso()}."
        else:
            msg = "Date was removed."

        self.notify(msg)


if __name__ == "__main__":
    DatePickerApp().run()

Date Range

DateRangeApp ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ 2025-02-05🔒    -  -   ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

from textual.app import App, ComposeResult
from textual_timepiece.pickers import DateRangePicker
from whenever import Date, weeks


class DateRangeApp(App[None]):

    def compose(self) -> ComposeResult:
        yield DateRangePicker(Date(2025, 2, 5), date_range=weeks(1))


if __name__ == "__main__":
    DateRangeApp().run()

Date Select

DateSelectApp ────────────────────────────────────── March 2025 MonTueWedThuFriSatSun   1  2   3  4  5  6  7  8  9  10 11 12 13 14 15 16  17 18 19 20 21 22 23  24 25 26 27 28 29 30  31 ──────────────────────────────────────

from textual.app import App, ComposeResult
from textual import on
from textual.widgets import Label
from textual_timepiece.pickers import DatePicker, DateSelect
from whenever import Date, days


class DateSelectApp(App[None]):

    def compose(self) -> ComposeResult:
        yield DateSelect(Date.today_in_system_tz(), date_range=days(3))
        yield Label(variant="accent")

    @on(DateSelect.DateChanged)
    @on(DateSelect.EndDateChanged)
    def on_date_changed(self, message: DateSelect.DateChanged | DateSelect.EndDateChanged) -> None:
        new_content = f"  {message.widget.date} - {message.widget.end_date}  "
        self.query_one(Label).update(new_content)


if __name__ == "__main__":
    DateSelectApp().run()

DateTime Range Picker

DTPickerRangeApp ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ 2025-03-1012:49:37🔓    -  -     :  :   ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ Started timer!

from textual.app import App, ComposeResult
from textual_timepiece.pickers import DateTimeRangePicker
from textual import on
from whenever import Date, SystemDateTime


class DTPickerRangeApp(App[None]):

    def on_mount(self) -> None:
        self.query_one(DateTimeRangePicker).disable_end()
        self.set_timer(10, self.stop_timer)
        self.notify("Started timer!")

    def compose(self) -> ComposeResult:
        yield DateTimeRangePicker(SystemDateTime.now().local())

    def stop_timer(self) -> None:
        dt_range = self.query_one(DateTimeRangePicker).disable_end(disable=False)
        dt_range.end_dt = SystemDateTime.now().local()


if __name__ == "__main__":
    DTPickerRangeApp().run()

Activity Heatmap

ActivityApp │││││││││││││││││││││││││<<<2025>>>││││││││││││││││││││││││││ Mon████████████████████████████████████████████████ Tue████████████████████████████████████████████████ Wed██████████████████████████████████████████████████ Thu██████████████████████████████████████████████████ Fri██████████████████████████████████████████████████ Sat██████████████████████████████████████████████████ Sun██████████████████████████████████████████████████  1 2 3 4 5 6 7 8 910111213141516171819202122232425 JanFebMarAprMayJun

import random
from collections import defaultdict

from textual.app import App, ComposeResult
from textual_timepiece.activity_heatmap import ActivityHeatmap, HeatmapManager


class ActivityApp(App[None]):
    def _on_heatmap_manager_year_changed(
        self,
        message: HeatmapManager.YearChanged,
    ) -> None:
        message.stop()
        self.set_heatmap_data(message.year)

    def retrieve_data(self, year: int) -> ActivityHeatmap.ActivityData:
        """Placeholder example on how the data could be generated."""
        random.seed(year)
        template = ActivityHeatmap.generate_empty_activity(year)
        return defaultdict(
            lambda: 0,
            {
                day: random.randint(6000, 20000)
                for week in template
                for day in week
                if day
            },
        )

    def set_heatmap_data(self, year: int) -> None:
        """Sets the data based on the current data."""
        self.query_one(ActivityHeatmap).values = self.retrieve_data(year)

    def _on_mount(self) -> None:
        self.set_heatmap_data(2025)

    def compose(self) -> ComposeResult:
        yield HeatmapManager(2025)


if __name__ == "__main__":
    ActivityApp().run()

Single Line Picker

MiniPickerApp 2025-03-1012:49:3700:00:00🔓2025-03-1012:49:37

from textual.app import App, ComposeResult
from textual_timepiece.pickers import DateTimeDurationPicker
from whenever import Date, SystemDateTime, weeks


class MiniPickerApp(App[None]):

    def compose(self) -> ComposeResult:
        yield DateTimeDurationPicker(SystemDateTime.now().local(), classes="mini")


if __name__ == "__main__":
    MiniPickerApp().run()