Skip to content

Mobile Friendly Tasks

Ed Mozley edited this page Aug 26, 2026 · 1 revision

Mobile: Tasks

Tasks is the tenth module made mobile‑friendly, after Tickets, Assets, Calendar, Knowledge, Service Status, Watchtower, Problem Management, Change Management and Software. Same hard rule: one @media (max-width: 768px) block, desktop byte‑identical.

🧰 Code‑level catalogue of the techniques: Mobile: Techniques & Tricks.

Shipped as #1205, commit a8ea82fa, plus #1206, commit 28471532. LAYER 25.


The starting point

viewport = 360   docScrollW = 1144   ← on ALL SIX pages, identically

The tenth module, and the tenth time the same number appeared on every page at once β€” nav.header-nav at 730px in the shared header, the iOS reflow‑to‑desktop trap. The module had never opted in. Three tags per page took all six to docScrollW === 360.


Scope β€” six pages, most of the work already done

Page State
tasks/ β€” the Kanban board Done β€” one column per screen with snap, plus a dots indicator (25a, 25b)
tasks/ β€” the list view Done β€” table β†’ card feed (25c)
tasks/table/ Done by opting in β€” the shared .dt-wrap scroller from the Assets round
tasks/calendar/ Done by opting in, plus the view switcher (25e)
tasks/timeline/ β€” the Gantt Done by opting in β€” a Gantt keeps its columns and scrolls, as it should
tasks/settings/ Done by opting in + data-mobile-page="settings"
tasks/help.php Done by opting in β€” inherits the contents strip

The detail panel needed no width work at all: tasks.css already carries its own @media (max-width: 900px) { .detail-panel { width: 100% } }. That turned out to be the trap rather than the gift β€” see below.


25a β€” the board: one status per screen

At 240px a column showed 1.5 of them on a phone: one column and a distracting sliver of the next. Too narrow to read, too wide to be a clean screen.

.board-view { scroll-snap-type: x mandatory; scroll-padding-left: 12px; }
.board-view .board-column { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; }

A sideways drag now turns the page β€” To Do β†’ In Progress β†’ Blocked.

πŸ”‘ min-width: 0 is load‑bearing. tasks.css sets a 240–280px floor and a flex item cannot shrink below its min-width however small the basis. Invisible to a docScrollW === innerWidth check, because the board scrolls, not the page.

Drag‑and‑drop between columns stays a desktop interaction. This makes the board readable on a phone, not draggable.

25b β€” and then nothing said a swipe would work

Full‑width columns cost the one thing the 1.5‑column view gave for free: the visible edge of the next column. A dot per column, injected by mobile.js, restores it.

πŸ”΄ The dots did nothing at first

Appended inside mobile.js's main IIFE, which returns early on line 159:

if (!mc || !document.querySelector('.email-list-container')) return;   // tickets inbox wiring

They were absent, not broken β€” so a parse check passed and the CSS was fine. Only asking the live page "is renderBoard wrapped?" found it. Moved to its own top‑level IIFE with its own mq.

πŸ”‘ A wrap‑don't‑edit block belongs in its own IIFE. Sharing one with another module's wiring means inheriting that module's early return.

25c / 25e β€” the list feed and the view switcher

The list table was 593px of Title / Assignee / Due / Priority / Status in 360px, and the Title column holds prose β€” so a card feed, not a scroller. This deliberately differs from the table view one page over, which keeps its columns: the two views exist precisely because one is for reading and the other for comparing.

.view-toggle / .view-btn are four modules' class names (Β§15); the existing rule was scoped to .calendar-main, which the Tasks calendar does not have. Scoped here to .tasks-main.


πŸ”΄ The detail panel β€” what I got wrong, twice

This is the part worth reading. The panel is the module's most-used screen on a phone and it took three attempts and two corrections from Ed.

Attempt 1: I treated the symptom

Ed reported "just a hint of left to right scroll but then it kind of rubber bands back". I measured "does anything cross the panel's right edge" β€” none β€” and concluded the drag came from scrollports behind the fixed panel, so I contained their overscroll:

.detail-panel { overscroll-behavior: contain; overflow-x: hidden; }

Which is true and worth having, and was not the cause.

Attempt 2: Ed found it β€” and my "fix" made it worse

"on task details the due date form field is spilling off to the right"

.detail-row is a flex pair β€” Status+Priority, Assignee+Team, Start+Due β€” with .detail-field { flex: 1 }. Two date fields could not fit. Measured properly:

row 2 content needs 330px but has 312   ← SHRINK FLOOR of 18px
elements crossing the panel's right edge: NONE

The panel clips it, so the outer check reports nothing. Β§14 says this in as many words β€” "whenever a child measures wider than its parent and the page is still contained, look for a shrink floor before looking for the overflow" β€” and I had run the outer comparison instead. The knowledge was on this wiki and I did not consult it.

Worse: I had already bumped every field to 16px for the anti‑zoom fix while the dates were still side by side, and 16px makes a date field wider. For the few minutes that state was on disk it was a genuine regression, and Ed caught it β€” "we're still not there and it's arguably worse".

Fix: stack every pair.

.detail-panel .detail-row { flex-direction: column; gap: 12px; }
.detail-panel .detail-row .detail-field { flex: 1 1 auto; min-width: 0; width: 100%; }

Attempt 3: Ed asked the question that found the real cause

"the start date and due date form fields are wider than the dropdowns (status, priority etc) why is this?"

Nothing in the CSS makes them differ β€” tasks.css gives .detail-select and .detail-input one shared rule. The difference is the control: a native date input ignores the width you give it, and iOS spells the month out (12 May 2026) where Chrome on Windows draws 12/05/2026.

That is why my desktop harness kept clearing a panel that was broken on his phone β€” it was measuring a different control. Written up as Β§20, the fifth place in mobile.css to need the same reset.

πŸ”‘ A field being wider than its neighbours is the same fault as a field spilling off the right β€” and it is the tell that shows at rest, without a gesture. Ed spotted it by looking; I had three harnesses that could not.

25f β€” the anti‑zoom, and why the existing rule missed it

Ed: "when adding a task on mobile can you use that trick to stop it zooming in". Adding a task in Tasks is not a dialog β€” it is an inline .quick-add-input that unfolds under a column heading β€” so LAYER 3's rule, which knows .modal-content and .modal .form-group, could never reach it. Same shape as the .search-modal fix in #1193.

The reported field was one of nine. tasks.css sets 13px on every field in the module, so the search box, three sidebar filters, the subtask box, the comment box, the tag picker, both link searches and the panel's selects and dates all zoomed identically. Only .detail-title-input (18px) was safe.

Two scopes were needed, not one: .detail-panel is a sibling of .tasks-container, not a child, so a single container scope silently misses most of the fields. .search-input is four modules' class and is scoped accordingly.


Verification

Check Result
docScrollW === innerWidth at 360px βœ… all six pages β€” 1144 β†’ 360
Board column width 336px = viewport βˆ’ padding; snap x mandatory; lands flush left
Dots follow the scroll; display: none on desktop
List view cell heights unequal β€” the card‑feed signature, not a crushed row
Detail panel @ 320px and 390px panel and page contained; zero shrink floors on any row
…with date fields forced to 210px each still contained β€” the check that does not trust the desktop rendering
Every panel field 342w Γ— 44h, identical; dates appearance: none
Desktop @ 1280px snap none; columns 280px, 4.6 visible; dots hidden; thead table-header-group; fields 210w at 13px, appearance: auto

Known rough edges

  • The sidebar is display: none under 600px (tasks.css, pre‑existing). So on a phone there is no way to search or filter tasks β€” the board's status columns are the only filter. That is a real gap, not a mobile‑layout one, and it is why 25f still styles the sidebar fields: they are reachable in the 601–768px band.
  • Dragging cards between columns remains desktop‑only.
  • The task title truncates with an ellipsis in the panel rather than wrapping; the full title is on the card and on focus.

Reference

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally