Skip to content

panic_button

panic_button

Panic button widget with arm-then-fire safety mechanism.

The button sits in the main layout but is excluded from the Tab focus chain (can_focus = False). A single click arms it (visual change + 5-second auto-disarm timer); a second click fires the emergency panic sequence.

PanicButton(**kwargs)

Bases: Static

Clickable emergency button with arm-then-fire two-phase activation.

Initialize in idle (disarmed) state.

Source code in src/terok/tui/widgets/panic_button.py
def __init__(self, **kwargs: Any) -> None:
    """Initialize in idle (disarmed) state."""
    super().__init__(**kwargs)
    self._armed = False
    self._disarm_timer: Timer | None = None

can_focus = False class-attribute instance-attribute

DEFAULT_CSS = '\n PanicButton {\n height: 3;\n margin-top: 1;\n content-align: center middle;\n text-align: center;\n background: $error;\n color: white;\n text-style: bold;\n }\n\n PanicButton.armed {\n background: darkred;\n text-style: bold reverse;\n }\n ' class-attribute instance-attribute

Fired

Bases: Message

Posted when the arm-then-fire sequence completes.

on_mount()

Set the idle label once the widget is mounted.

Source code in src/terok/tui/widgets/panic_button.py
def on_mount(self) -> None:
    """Set the idle label once the widget is mounted."""
    self.update(_LABEL_IDLE)

arm()

Transition from idle to armed state with auto-disarm timer.

Source code in src/terok/tui/widgets/panic_button.py
def arm(self) -> None:
    """Transition from idle to armed state with auto-disarm timer."""
    if self._armed:
        return
    self._armed = True
    self.add_class("armed")
    self.update(_LABEL_ARMED)
    self._disarm_timer = self.set_timer(_DISARM_SECONDS, self.disarm)

disarm()

Return to idle state, cancelling any pending timer.

Source code in src/terok/tui/widgets/panic_button.py
def disarm(self) -> None:
    """Return to idle state, cancelling any pending timer."""
    if not self._armed:
        return
    self._armed = False
    self.remove_class("armed")
    self.update(_LABEL_IDLE)
    if self._disarm_timer is not None:
        self._disarm_timer.stop()
        self._disarm_timer = None

fire()

Complete the arm-then-fire sequence: disarm and emit Fired.

Source code in src/terok/tui/widgets/panic_button.py
def fire(self) -> None:
    """Complete the arm-then-fire sequence: disarm and emit [`Fired`][terok.tui.widgets.panic_button.PanicButton.Fired]."""
    self.disarm()
    self.post_message(self.Fired())

on_click()

Handle mouse clicks: arm on first click, fire on second.

Source code in src/terok/tui/widgets/panic_button.py
def on_click(self) -> None:
    """Handle mouse clicks: arm on first click, fire on second."""
    if self._armed:
        self.fire()
    else:
        self.arm()