Skip to content

Feature: Add Mail-style swipe actions to mobile web sidebar threads #9148

Description

@Pearcekieser

Problem or use case

On a phone-sized browser, the thread sidebar has no pointer hover, so its quick lifecycle actions
are harder to reach than they are on desktop. Organizing work requires opening a thread menu even
for frequent actions such as settling, snoozing, or pinning a thread.

This makes inbox-style thread triage feel slower than comparable touch-first list interfaces such
as Apple Mail.

Proposed solution

Allow a left swipe on an active or pinned thread card in the mobile-width web sidebar to reveal
three large touch targets:

  • Settle
  • Snooze, opening the existing snooze preset picker
  • Pin, or Unpin when the thread is already pinned

The row should follow the finger and settle open or closed after release. Only one row should stay
open at a time, tapping the revealed row should close it, and closing the sidebar should clear any
open tray.

The actions should reuse the current capability checks and command paths so older environments do
not show unsupported controls.

Why this matters

People often check and organize T3 Code work remotely from a phone. Making the most common thread
actions directly reachable turns the mobile web sidebar into a practical triage surface instead of
requiring repeated menu navigation.

Smallest useful scope

  • Mobile-width web sidebar only.
  • Full active and pinned thread cards only; settled and snoozed slim rows keep their existing
    controls.
  • Existing settle, snooze, pin, and unpin commands; no server or wire-contract changes.
  • No change to the native iOS or Android clients.

Interaction constraints

  • Ambiguous diagonal gestures must remain vertical scrolling.
  • A swipe must not change row height, list order, or auto-layout measurements.
  • The gesture must coexist with current pinned-thread drag behavior and possible active-thread
    reordering work in feat(web): reorder active sidebar threads #8666.
  • A synthetic click after pointer-up must not navigate or immediately close a newly opened tray.
  • Reduced-motion and capability-gated states should retain their existing behavior.

Alternatives considered

  • Keep the context menu as the only touch entry point. This works, but adds extra taps for the most
    common organization actions.
  • Show persistent buttons on every mobile row. This reduces title space and makes a dense sidebar
    visually noisy.
  • Add actions to slim settled/snoozed rows in the first pass. Their lifecycle actions differ, so
    excluding them keeps the initial gesture model focused and predictable.

Risks or tradeoffs

Horizontal swipe and vertical scrolling share the same touch surface. Direction locking should be
biased toward scrolling, and only the inner row surface should translate so the list's
auto-animate geometry remains unchanged.

Whole-row drag listeners are another possible collision point. Swipe handling should remain
isolated so the active-thread reorder work in #8666 can integrate without coupling gesture state
to thread lifecycle state.

Examples or references

Before While dragging Actions revealed
Mobile sidebar before swipe Thread following a partial swipe Settle, Snooze, and Pin actions revealed

Reference interaction: Apple Mail's swipe-to-reveal message actions.

Acceptance criteria

  • A left swipe on a mobile-width active thread card tracks the pointer and reveals supported
    actions.
  • Releasing after a deliberate swipe leaves the tray open; a short swipe settles closed.
  • Settle, snooze, and pin/unpin call the existing thread action implementations.
  • Snooze opens the current preset picker rather than applying an arbitrary default.
  • Vertical and ambiguous diagonal gestures scroll without moving the row horizontally.
  • Only one tray stays open, and it closes when the sidebar closes.
  • Swipe transforms do not affect row height, list ordering, or auto-layout measurements.
  • Desktop/fine-pointer behavior and native mobile clients are unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions