# Herdr Mobile Touch UI Threshold and Layout Adaptation: A Complete Guide

> Learn about Herdr mobile touch UI threshold and layout adaptation. Discover how Herdr optimizes its interface for smaller screens with configurable thresholds and precise hit-area calculations. Full guide available.

- Repository: [Can Celik/herdr](https://github.com/ogulcancelik/herdr)
- Tags: tutorial
- Published: 2026-05-31

---

**Herdr switches to a touch-friendly mobile layout when the terminal width drops to 64 columns or below, using configurable thresholds and precise hit-area calculations defined in [`src/ui/mobile.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/ui/mobile.rs).**

The Herdr terminal workspace manager automatically adapts its interface for touchscreen and small-screen devices through a deterministic width-based detection system. When the terminal viewport shrinks past a configurable threshold, the application abandons its desktop sidebar layout in favor of full-screen panels with enlarged touch targets. This mechanism relies on simple geometric comparisons and rectangular hit-area calculations that prioritize performance and responsiveness.

## How Herdr Detects Mobile Terminal Width

Herdr uses a single integer comparison to determine when to render the mobile touch interface rather than the standard desktop layout. This approach avoids expensive layout recalculations and ensures immediate responsiveness to terminal resizing.

### The Default 64-Column Threshold

The default mobile threshold is defined in [`src/config.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/config.rs) as a constant value:

```rust
// src/config.rs#L34
pub const DEFAULT_MOBILE_WIDTH_THRESHOLD: u16 = 64;

```

This value is loaded into `AppState` at startup and stored in the `mobile_width_threshold` field (`src/app/state.rs#L1330`). Users can override this default by specifying a custom value in their configuration file, allowing the mobile layout to activate at wider or narrower terminal sizes as needed.

### The is_mobile_width Helper Function

The actual detection logic resides in [`src/ui/mobile.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/ui/mobile.rs) within the `is_mobile_width` function:

```rust
// src/ui/mobile.rs#L44-L46
pub(crate) fn is_mobile_width(area: Rect, threshold: u16) -> bool {
    area.width > 0 && area.width <= threshold
}

```

This helper returns `true` when the terminal `area.width` is greater than zero and less than or equal to the configured threshold. The check against zero ensures graceful handling of zero-size frames during initialization or minimization events. When this function returns `true`, Herdr sets `ViewState.layout` to `Mobile`; otherwise, it retains the `Desktop` layout.

## Mobile Layout Adaptation Components

When the mobile layout activates, Herdr replaces the traditional sidebar with a full-screen switcher panel and responsive header bar. The geometry for these components is calculated dynamically based on the current terminal dimensions.

### Mobile Header and Hit Areas

The mobile header displays the workspace name, current tab number, and a menu button. Its interactive geometry is computed by `compute_mobile_header_hit_areas` (`src/ui/mobile.rs#L48-L62`), which returns a `MobileHeaderHitAreas` struct containing the clickable rectangle for the menu button.

The header spans the full width of the terminal and reserves specific coordinate ranges for touch targets, ensuring that fingertip interactions register reliably even on high-resolution displays.

### Switcher Panel Geometry

The switcher panel occupies the remaining screen real estate below the header and presents a vertically scrolling list of workspaces, tabs, agents, and global menu items. The function `mobile_switcher_areas` (`src/ui/mobile.rs#L64-L86`) defines:

- **The scrollable viewport rectangle** that bounds the content area
- **The close button location** within each list item
- **The left-hand scrollbar thumb** position calculated by `render_left_scrollbar` (`src/ui/mobile.rs#L76-L86`)

These areas are stored as `ratatui::layout::Rect` objects that map physical screen coordinates to logical UI elements.

### Touch Hit-Testing Implementation

Touch and mouse events are mapped to UI actions through `mobile_switcher_target_at` (`src/ui/mobile.rs#L101-L158`). This function accepts a physical coordinate pair and returns a `MobileSwitcherTarget` enum variant indicating which element was touched:

```rust
pub enum MobileSwitcherTarget {
    NewWorkspace,
    Workspace(usize),
    NewTab,
    Tab(usize),
    Agent(usize),
    GlobalMenu,
    // ... additional variants
}

```

The hit-testing algorithm performs simple rectangle containment checks against the pre-calculated hit areas, making touch response instantaneous even with large numbers of workspaces or tabs.

## Configuring the Mobile Width Threshold

Users can customize when the mobile layout activates by editing the Herdr configuration file. To change the threshold from the default 64 columns to a custom value, add the following to `$HOME/.config/herdr/config.toml`:

```toml
[ui]
mobile_width_threshold = 80   # Switch to mobile at 80 columns instead of 64

```

The `load_live_config` function reads this value during startup and propagates it to `AppState.mobile_width_threshold`. This field is then passed to every call to `is_mobile_width` throughout the application lifecycle.

To force a specific layout mode programmatically during testing or development:

```rust
let mut app = AppState::test_new();
app.mobile_width_threshold = 100; // Require 100+ columns for desktop layout

```

## Touch UI Implementation Details

### Hit Area Calculations with ratatui

Herdr leverages the `ratatui` crate's `Rect` type for all geometric calculations. These rectangles define the exact screen coordinates (x, y, width, height) of interactive elements. The `mobile_screen_rect` function (`src/ui/mobile.rs#L44-L53`) computes the union of the header and terminal areas to ensure the switcher covers the full available space when the terminal dimensions are constrained.

Rendering utilizes low-level drawing primitives such as `fill_rect` (`src/ui/mobile.rs#L96-L108`) and `draw_horizontal_rule` to create high-contrast touch targets using simple Unicode symbols (`│`, `▌`, "switch", "close") that remain legible across different terminal emulators and color schemes.

### Scroll Handling in Mobile View

The mobile switcher supports vertical scrolling through the `mobile_switcher_scroll` field stored in `AppState`. The helper function `mobile_switcher_max_scroll_for_height` calculates the maximum valid scroll offset based on the total content height versus visible rows, ensuring the viewport never scrolls beyond the available content.

## Summary

- **Herdr uses a 64-column default threshold** defined in [`src/config.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/config.rs) to determine when to switch from desktop to mobile layout, stored in `AppState.mobile_width_threshold` (`src/app/state.rs#L1330`).
- **The `is_mobile_width` function** (`src/ui/mobile.rs#L44-L46`) performs a simple width comparison to detect mobile terminals, guarding against zero-size areas.
- **Mobile layout components** include a compact header with menu button hit areas and a full-screen switcher panel with calculated scrollable viewports (`src/ui/mobile.rs#L48-L86`).
- **Touch hit-testing** maps physical coordinates to logical actions using `mobile_switcher_target_at` (`src/ui/mobile.rs#L101-L158`) and rectangular collision detection against `Rect` hit areas.
- **Users can customize the threshold** via the `mobile_width_threshold` setting in [`config.toml`](https://github.com/ogulcancelik/herdr/blob/main/config.toml), with changes loaded at startup by `load_live_config`.

## Frequently Asked Questions

### What is the default mobile width threshold in Herdr?

Herdr defaults to **64 columns** for the mobile width threshold, defined as `DEFAULT_MOBILE_WIDTH_THRESHOLD` in `src/config.rs#L34`. When the terminal width is less than or equal to this value (and greater than zero), the application renders the touch-optimized mobile interface instead of the desktop sidebar layout.

### How does Herdr calculate touch hit areas for mobile UI?

Hit areas are calculated as `ratatui::layout::Rect` structures that define the exact screen coordinates of interactive elements. The functions `compute_mobile_header_hit_areas` and `mobile_switcher_areas` (`src/ui/mobile.rs#L48-L86`) generate these rectangles based on current terminal dimensions, which `mobile_switcher_target_at` then uses to map touch coordinates to specific actions like selecting workspaces or tabs.

### Where is the mobile layout configuration stored in Herdr?

The mobile width threshold configuration resides in the user's TOML config file at `$HOME/.config/herdr/config.toml` under the `[ui]` section as `mobile_width_threshold`. This value is read during startup by `load_live_config` and stored in `AppState.mobile_width_threshold` (`src/app/state.rs#L1330`) for runtime access by the layout detection logic.

### Can I force Herdr to always use desktop layout regardless of terminal size?

While there is no explicit "disable mobile" flag, you can effectively force desktop layout by setting `mobile_width_threshold` to `1` or `0` in your [`config.toml`](https://github.com/ogulcancelik/herdr/blob/main/config.toml). Since `is_mobile_width` requires `area.width > 0`, setting the threshold to `0` ensures the function always returns `false`, keeping the layout in `Desktop` mode even on very small terminals.