Skip to content

Mobile Friendly People

Ed Mozley edited this page Oct 2, 2026 · 1 revision

Mobile‑Friendly: People

Scope: all five pages - the people list, a person, the companies, a company, and the guide. Layers: mobile.css LAYER 42 (42a-42e). No mobile.js branch - the header's ☰ drawer and the waffle already work, and nothing on these pages needs wrapping. Parent: Mobile‑Friendly Β· Techniques: Β§3, Β§11, Β§21, Β§23, Β§28, Β§31


Where it started

People was built after the rollout, with mobile.css and mobile.js linked on every page, markers on all five, and a @media (max-width: 640px) block of its own in people.css that already turned every table into labelled blocks. Nothing spilled sideways. Measured at 360Γ—740 through an explicit‑width iframe, then looked at:

Page Found Answer
Every page but Companies πŸ”΄ Could not be scrolled by a finger. A person page was 9,712px of document in a 740px screen Hand the scroller role to the page's own container (42a)
List Search, Show and Company with their headings: 320px before the first person, every field 13px A compact strip - search, then the two drop‑downs side by side: 109px. 16px fields
Every table Every value labelled, empty ones too ("Job title:" over nothing); a ticket's subject given the same room as its date A real card: identifier and status pill on line one, prose on its own line, labels only where a value means nothing alone
Company Its people scrolled inside a 420px box inside the scrolling page One scroller

πŸ”΄ The page that moved for the probe and not for a thumb

htmlBody: visible/hidden   bodyH=740
docH:     9712/740
scroller: none

inbox.css gives <body> overflow: hidden, and LAYER 2 makes it a 100dvh flex column. A page whose own container never takes the scroller role is then taller than a body that clips - and because <html> is overflow: visible, the body's hidden propagates to the viewport. The window cannot be scrolled by a person.

It can be scrolled by code. window.scrollTo(0, 99999) moved it to scrollY = 8972, and the header went with it. A probe that scrolls programmatically and asserts the position changed would have passed this page.

πŸ”‘ overflow: hidden stops the USER, not scrollTo(). A scroll assertion has to be made on an element whose computed overflow-y is auto or scroll - which is what Β§28's one-line check asks for, and why it found nothing here. "Nothing qualifies" is the finding, not a probe failure.

The fix is 41a's, one module on:

body[data-mobile-module="people"] .ppl-page {
    flex: 1 1 auto; min-height: 0;          /* Β§28: or the content is the floor */
    overflow-y: auto; overflow-x: hidden;
}

The list page keeps its filter strip pinned and scrolls .ppl-main-list instead, so a search is always one tap away.

The module's own breakpoint, folded in

people.css had two blocks. The 900px one stacks the panes in a narrow desktop window and stays where it is. The 640px one was the phone design - and the Morning Checks round (LAYER 26) set the precedent: before styling a module for a phone, find out what is already styling it, and give it one home. It moved into LAYER 42 and now starts at 768 like everything else.

The cards

One shape for all eight tables, using two techniques already in the rollout:

  • Β§23's flex: 1 1 60% on the identifier, so a status pill shares its line at the right;
  • the Domains round's forced line break - a zero‑height, full‑width tr::after placed by order - so everything after line one starts at the left whatever the first line did.

A ticket's subject is a sentence, so it gets a full line (Β§11). The labels come from the data-label the module already stamps (its own translated headings), printed only on the columns that cannot speak for themselves: a priority word, a second name, a bare date or count. Self-describing values - an email, a pill, a job title - go unlabelled, and an empty cell is removed outright (td:empty { display: none }), so no heading is left over nothing.

Which status pill rides on line one is keyed on the column count for courses (.ppl-table:has(thead th:nth-child(4))), because a person's courses have a status in column 2 and a company's courses table has a bare count there.

⚠️ Two card shapes from one rule

The first screenshot of the list showed two kinds of card: a short email pulled the job title up beside it and a long one did not - Β§23's tell, the difference was the data. The email now takes a line of its own; every card is name / email / role and company.

πŸ”΄ display: flex defeats [hidden]

"Show all" and the company page's people filter both work by setting hidden on rows. A card row is display: flex, which beats the browser's [hidden] { display: none }, so every hidden row would have reappeared. tr[hidden] { display: none } in the layer; proved by driving both (below).

Verification

At 360Γ—740 on all five pages: nothing off either edge (left < 0 included), every field 16px, and on each page that has more than a screen of content the scroller found, scrolled to the end, and what is under the finger changed. Β§31's test on every control: a search for nobody took the list from 74 rows to the "Nobody matches." state and back to 74; the company filter took 75 people to 0; Show all went 10 β†’ 50 with no hidden row visible before the tap.

Desktop control at 1100px on all five pages - fingerprint every element's box, disable mobile.css in place, fingerprint again: identical, 4,723 boxes, and no data-mobile-label stamped. The people.css change only removed rules below 640px.

Still owed

  • A device pass. Everything here is headless.

See also: People Β· Mobile‑Friendly Β· Techniques Β· Mobile: Domains (41a's scroller, the forced line break)

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally