# Does Witr Support Mouse Input and Click-to-Sort in Its TUI?

> Discover if witr's TUI supports mouse input and click-to-sort. Learn how witr leverages Bubble Tea for interactive table sorting and mouse functionality.

- Repository: [Pranshu Parmar/witr](https://github.com/pranshuparmar/witr)
- Tags: feature-support
- Published: 2026-08-09

---

**Yes, witr fully supports mouse input and click-to-sort functionality in its terminal UI, leveraging Bubble Tea's built-in mouse mode to enable interactive column header clicking across process, port, container, and lock tables.**

Witr is a terminal-based system monitor built on Charm’s Bubble Tea framework that implements **witr mouse input click-to-sort** capabilities through a custom event dispatcher. The application translates screen coordinates into sort commands, allowing users to reorganize tabular data views with single clicks without keyboard shortcuts. This technical guide examines the implementation details in the `pranshuparmar/witr` repository, analyzing how mouse events are captured, mapped, and processed to drive the sorting interface.

## How Witr Enables Mouse Mode in the Terminal

Witr relies on Bubble Tea’s underlying TUI engine, which automatically activates **mouse mode** (X10/SGR reporting) during initialization in [`internal/tui/view.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/view.go). When the application starts, Bubble Tea negotiates with the terminal emulator to enable mouse event reporting, allowing witr to capture click coordinates, scroll actions, and other pointer interactions. This foundation supports any modern terminal on Linux, macOS, or Windows—including iTerm2, GNOME Terminal, Windows Terminal, and Alacritty—that advertises mouse compatibility.

## The Click-to-Sort Architecture

Witr implements a thin mouse dispatcher that bridges raw terminal events with table-sorting logic through three coordinated components: coordinate mapping, view-specific handlers, and state management.

### Mapping Clicks to Column Indices

When a user clicks a table header, the `MainModel` receives the X-coordinate and determines the target column via the `getColumnAtX` method defined in [`internal/tui/mouse.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/mouse.go). This function iterates through the column configuration, accounting for padding offsets, to translate the screen position into a zero-based column index.

```go
// In internal/tui/mouse.go – map X coordinate to column index
func (m *MainModel) getColumnAtX(x int, cols []table.Column) int {
    cur := 0
    for i, col := range cols {
        w := col.Width + 2 // account for padding
        if x >= cur && x < cur+w {
            return i
        }
        cur += w
    }
    return -1
}

```

### Header Click Handlers

The dispatcher routes captured clicks to specialized handlers based on the active view: `handleProcessHeaderClick`, `handlePortHeaderClick`, `handleContainerHeaderClick`, and `handleLockHeaderClick`. Each handler maps the column index to a database field, toggles the sort direction if the same column is clicked consecutively, or initializes a new descending sort for first-time selections.

```go
// Example: click on a process table header
func (m *MainModel) handleProcessHeaderClick(x int) {
    cols := m.table.Columns()
    colIdx := m.getColumnAtX(x, cols)

    if colIdx >= 0 {
        var newCol string
        switch colIdx {
        case 0: newCol = "pid"
        case 1: newCol = "user"
        case 2: newCol = "name"
        case 3: newCol = "cpu"
        case 4: newCol = "mem"
        case 5: newCol = "time"
        }
        // toggle or set sort direction
        if m.sortCol == newCol {
            m.sortDesc = !m.sortDesc
        } else {
            m.sortCol = newCol
            m.sortDesc = true
        }
        m.sortProcesses()
        m.filterProcesses()
        m.table.SetColumns(m.getColumns())
    }
}

```

## Event Routing and UI Updates

Mouse events flow through [`internal/tui/update.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/update.go), which acts as the central message router for Bubble Tea’s `Update` loop. When a mouse message is detected, the dispatcher invokes the appropriate handler, which mutates the model’s sort state (stored in `m.sortCol` and `m.sortDesc`). The handler then calls view-specific sorting methods like `sortProcesses()` and `filterProcesses()`, followed by `m.table.SetColumns()` to trigger an immediate re-render. This pipeline ensures that clicking any header provides instantaneous visual feedback with the reordered data.

## Supported Tables and Terminal Compatibility

The **witr mouse input click-to-sort** system operates across four primary data views:

- **Process table**: Sort by PID, user, process name, CPU usage, memory usage, or execution time
- **Port table**: Reorder network port listings by protocol, state, or address
- **Container table**: Organize Docker or container runtime data through interactive headers
- **Lock table**: Sort file and resource lock information by holder, type, or path

Any terminal emulator supporting X10 or SGR mouse event protocols can utilize these features without additional configuration flags.

## Summary

- Witr enables **mouse input click-to-sort** by activating Bubble Tea’s mouse mode during initialization in [`internal/tui/view.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/view.go).
- The `getColumnAtX` function in [`internal/tui/mouse.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/mouse.go) translates X-coordinates into column indices by calculating cumulative widths with padding.
- Four dedicated handlers—`handleProcessHeaderClick`, `handlePortHeaderClick`, `handleContainerHeaderClick`, and `handleLockHeaderClick`—manage sort logic for their respective views.
- Clicking an active column toggles the sort direction via `m.sortDesc`, while new columns default to descending order.
- The message router in [`internal/tui/update.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/update.go) coordinates event handling and UI refreshes.
- Unit tests in [`internal/tui/mouse_test.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/mouse_test.go) validate the coordinate mapping and sort triggering logic.

## Frequently Asked Questions

### Does witr support mouse input on all operating systems?

Yes, witr supports mouse input on Linux, macOS, and Windows provided the terminal emulator implements X10 or SGR mouse reporting protocols. Modern terminals like Windows Terminal, iTerm2, and GNOME Terminal automatically enable this functionality when witr initializes its Bubble Tea model.

### How does witr determine which column to sort when I click a header?

Witr calculates the target column using the `getColumnAtX` method in [`internal/tui/mouse.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/mouse.go), which sums column widths and padding to identify which header contains the clicked X-coordinate. The view-specific handler then maps this index to a database field name (e.g., "pid", "cpu") and updates the sort state accordingly.

### Can I disable mouse support in witr if my terminal does not support it?

While the raw source analysis focuses on enabled mouse functionality, Bubble Tea applications typically respect terminal capabilities and gracefully degrade to keyboard-only navigation when mouse reporting is unavailable. Users can navigate and sort using keyboard shortcuts implemented in [`internal/tui/update.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/update.go) if mouse events are not detected.

### Is the click-to-sort functionality covered by automated tests?

Yes, the repository includes unit tests in [`internal/tui/mouse_test.go`](https://github.com/pranshuparmar/witr/blob/main/internal/tui/mouse_test.go) that verify the mouse dispatcher correctly identifies header clicks and triggers the appropriate sort handlers. These tests ensure that coordinate calculations and sort state transitions function correctly across different table views.