-
-
Notifications
You must be signed in to change notification settings - Fork 29
Mobile Friendly Checklists
Scope: all four pages β the list, the editor, settings, and the guide. Layers:
mobile.cssLAYERS 40-40e, andmobile.jsLAYERS 40c-40e (the editor's footer, and the list's filter sheet). Parent: MobileβFriendly Β· Techniques: Β§9, Β§14, Β§30, Β§32
Checklists is the first module contributed from outside the project, and it was built with mobile.css already linked on every page. Three of its four pages therefore measured clean before anything was done to them, which is a genuinely good starting position and also the reason two faults went unnoticed for a release.
What was missing was not rules but scoping: not one of the four pages carried a data-mobile-page marker, so nothing in mobile.css could be aimed at the module even if it had needed to be.
<style> block:
<link rel="stylesheet" href="../assets/css/mobile.css?v=148"> <!-- line 71 -->
<style> .chk-layout { display: flex; height: calc(100vh - 48px); } </style>That is Β§9 exactly β every sameβspecificity rule in mobile.css loses on document order β and it is easy to miss precisely because the link is there. A page with no link at all announces itself; a page with the link in the wrong place looks done.
π "
mobile.cssis linked" is not the check. "mobile.cssis linked after the page's own stylesheet" is.
This is the useful part of the round, and it is written up in full as Techniques Β§32.
.chk-card left=296 w=340 <- first card starts 296px in, on a 360px screen
main.chk-main w=100 <- the pane holding it
-
The grid has a floor.
repeat(auto-fill, minmax(340px, 1fr))reads as at least 340px, soauto-filllays out a 340px track on a 360px screen and the cards overflow. A real fault β fixed first, and it changed nothing measurable. -
Because the pane was already 100px.
.chk-layoutis a flex row whose 260px sidebar carriesflex-shrink: 0, leaving.chk-mainone hundred pixels wide. A1frtrack inside 100px is 100px. This is the fixedβsidebar shape for the fifth time in the rollout, and the treatment is the usual one: stack, cap the sidebar, hand the scroller role to the main pane explicitly. -
And the card still would not shrink. With the track at
1frinside a fullβwidth pane,.chk-cardmeasured 489px in a 336px track β because a grid item hasmin-width: autojust as a flex item does (Β§14). The track was right and the item ignored it.
β The lesson is the order, not any of the three rules. When a fix that should have moved something moves nothing, look outward before you look again at the rule you just wrote. Β§9 teaches this for load order; a correct rule inside a container that is already the wrong size behaves identically.
| All four pages |
data-mobile-page markers added (checklists, checklists-help, checklists-edit, checklists-settings) |
| Three pages |
mobile.css moved below the page's own <style>
|
| List page | layout stacks, sidebar capped at 32vh with the house 12px padding, .chk-main given the scroller role, grid to one column, card allowed to shrink |
| Settings, guide | nothing β they measured clean and still do |
| List page, round two | the scope panel became a sheet and the step role badges stopped spilling β see below |
| Editor | measured clean, then gained a sticky footer and the 16px rule β see below |
Desktop control at 1400px, run after moving the stylesheet because moving a stylesheet changes the cascade: flex row, 260px sidebar with its right border and 20px padding, main at 28px/36px, grid three 342px columns, card min-width: auto β all untouched.
Both faults here came from the same place: the module was written by somebody following the pattern from the outside, and the pattern's two invisible parts are the marker and the link's position. Neither shows up in a screenshot, and one of them makes the whole stylesheet silently lose ties.
- Grep for
data-mobile-pageon every new page, not formobile.css. - Check the link is after the page's
<style>. - Then measure β three of these four pages needed nothing, and knowing that quickly is worth more than guessing at rules.
Back and Save move to a sticky footer as icons (Ed). The top bar carried Back, the title, an unsaved-changes flag and Save, which at 360px left the title almost nothing - and Save is the control you reach for after scrolling to the bottom of a long template, the far end of the page from where it lived.
The real nodes are relocated, not copied: #edSave has a click handler bound in the page's own script and #edBack is an <a> carrying the href, so a clone would be a control that does nothing beside an original that still works. Each one's own label is harvested into aria-label, because an icon with no text has no accessible name, and everything is restored exactly above 768px.
Tapping Search templates zoomed the page. .chk-search is 13px, and Β§3 is unambiguous about what that costs:
iOS zooms on focus for any field under 16px β the page spills wider than the screen β Safari reflows the layout to a desktop width β the whole
max-width: 768pxblock stops matching.
So the symptom is not a bit of zoom, it is every mobile rule switching off at once. Fixed for the module rather than the one box: there are 21 focusable fields across these pages and the next one added would inherit the fault. No TinyMCE here, so the pointer: coarse content_style case does not arise.
Verified at 360x740: 21 fields, none under 16px, the search box exactly 16.
Both from Ed, using it.
The teal pill on each step β a suggested role, reading things like Tier 2 support β was pushing the page sideways.
.chk-step-row a tick Β· the step title Β· the role badge (space-between)
.chk-step-role white-space: nowrap
.chk-step-main min-width: (auto) <- the fault
Β§14 again: a flex item's automatic minimum is its content width, so the title would not shrink and the badge was pushed past the card's edge. The badge now drops to its own line, indented under the title β a role is a property of the step, not a continuation of its name, and at 336px there is no arrangement that fits both on one line.
β οΈ Those rows are styled INLINE, and an inline style beats any selector without!important. See Β§9's note on!importantfor the third option that was taken here: the markup was given three class names and nothing else changed, so desktop renders identically and the mobile layer has something to aim at.
A New button, a search box and three filter groups β scope, categories, roles β is most of a phone screen before a single template is shown. Β§4: a crowded panel gets its own screen. A Filters button in a sticky footer opens it fullβscreen.
The real .chk-sidebar is relocated in and out, not cloned β the calendar's 16a move β and here the reason is concrete: the filter links call setScopeFilter(..., this) with this, and the activeβlink bookkeeping walks .scope-link / .cat-link / .role-link. Two copies would be two sets of links disagreeing about which one is active.
π The sheet closes on a filter tap and not on a search keystroke. A filter is an arrival β you have chosen, and the thing you chose is behind the sheet. A keystroke is not. The System Wiki round is why that distinction is written down: closing on every tap there would have made a whole branch of the tree unreachable.
Verified by driving it at 360Γ740: 20 step rows with zero badges past the edge, one sidebar copy, the sheet fullβscreen when open and display: none when closed, still open after typing in search, and a tap on Task both closed it and took the list from 5 cards to 3. Desktop at 1400px: no sheet, no bar, sidebar still in the layout, step rows back to nowrap.
Checklists calls t() in PHP but never loads i18n.js and never exports window.translations, so window.t does not exist on these pages and the clientβside strings are hardβcoded English. Preβexisting β the labels added here fall back to English to match rather than inventing a second mechanism β but it is a real gap if the module is ever to be translated.
-
assets/css/mobile.css(LAYERS 40, 40b, 40c, 40d) andassets/js/mobile.js(LAYER 40c - the editor's footer). - Pages:
checklists/index.php,checklists/edit/,checklists/settings/,checklists/help.php. - Changelog: #1770-#1772.
- Parent: MobileβFriendly Β· Siblings: Mobile: Tickets, Mobile: Knowledge.
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- π§ͺ Developer tests
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- π Date & Time Formats
- Theming & Dark Mode
- ποΈ Recent β getting back to what you were doing
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
-
MobileβFriendly
- β³ π« Mobile: Tickets
- β³ π» Mobile: Assets
- β³ π Mobile: Calendar
- β³ π Mobile: Knowledge
- β³ π¦ Mobile: Service Status
- β³ πΌ Mobile: Watchtower
- β³ π§© Mobile: Problem Management
- β³ π Mobile: Change Management
- β³ πΏ Mobile: Software
- β³ β Mobile: Tasks
- β³ π Mobile: Forms
- β³ π Mobile: Contracts
- β³ π Mobile: Domains
- β³ π Mobile: People
- β³ π Mobile: LMS
- β³ πΊοΈ Mobile: CMDB
- β³ πΊοΈ Mobile: Network Mapper
- β³ π§ Mobile: Process Mapper
- β³ βοΈ Mobile: Workflow
- β³ π₯οΈ Mobile: System
- β³ π Mobile: Reporting
- β³ π Mobile: System Wiki
- β³ π Mobile: Self-Service Portal
- β³ π§° Mobile: Techniques & Tricks
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- β³ π‘οΈ CSRF protection (S4) β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- π CardDAV contact sync
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π REST API: Domains
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ π·οΈ REST API: Cost centres
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ π Rota copy and paste β Developer Deep Dive
- β³ β Checklists & SOPs
- β³ βοΈ Mandatory fields
- β³ π·οΈ Ticket categories
- β³ π₯ Assigning tickets to a team, and escalation
- β³ π’ One board across every company
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
-
β³
βοΈ Telegram channel - β³ β CSAT company scope and filters β Developer Guide
- β³ π₯ Microsoft Teams channel
- β³ π¨οΈ Mattermost channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ β Record previews
- β³ π Ticket notes: internal or shared
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ π¨ Telling the analyst a ticket is theirs
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π’ Ticket numbering
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ π Confidential tickets
- β³ π₯ Portal managers
- β³ π Who has seen a ticket
- β³ π Reading long tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ ποΈ The folder pane
- β³ π½ Just my tickets, or no closed ones
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- β³ π Scheduled work in your own calendar
- Problem Management
- Tasks
-
Assets
- β³ π’ Moving an asset between companies
- β³ π Shared asset locations
- β³ π§βπΌ Assigning assets to analysts
- β³ π Warranty and lease alerts
- β³ π Saved table views
- β³ π¨οΈ Recording anything, and importing it
- β³ π·οΈ QR asset labels
- β³ π Who holds what, and handover documents
- β³ π₯οΈ The inventory agent (PowerShell)
- β³ ποΈ Proxmox VE servers
- β³ βοΈ VMware Cloud Director servers
- β³ π Linking equipment to tickets
- β³ βοΈ Follow-up tasks on a ticket
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
-
Forms
- β³ π¨ The form designer β Developer Guide
- β³ π Layout & the grid β Developer Guide
- β³ ποΈ Collections β grouping submissions
- β³ π Submissions as PDFs
- β³ β‘ What happens next β a form's own actions
- β³ π οΈ Sections & conditional logic β Developer Guide
- β³ π οΈ Lookup fields β Developer Guide
- β³ π‘οΈ Catalogue request approvals
- People
- Domains
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ π’ One board across every company
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)
- What this is
-
π Bugs resolved
- β³ π’ Chat tickets ignored your ticket numbering
- β³ π Dates shown as a dash, or in server time
- β³ π Assets β Users showed people from other companies
- β³ π Restricted analysts could read other modules' data
- β³ πΌοΈ Replies with a picture in the thread failed to send
- β³ π Reply attachments never reached the customer
- β³ π οΈ Outbound email attachments β Developer Guide
- β³ π A global SSO provider was missing from the portal
- β³ π Behind a proxy, the SSO redirect said http
- β³ βοΈ The portal tagline moved when you saved it
- β³ π¨ The portal settings screen forgot what you saved
- β³ π‘οΈ The approvals inbox said "Error" and nothing else
- β³ π A table's answers were missing from the PDF
- β³ β A single-select column let you tick every option
- β³ π The portal ignored a form's field widths
- β³ π The tasks board stopped taking clicks
- β³ ποΈ #121 The index list is out of date after upgrading
- β³ π #133 The calendar subscription was empty
- β³ π #131 Tasks always reopened on the board
- β³ π₯ #129 Every page returned HTTP 500 after upgrading
- β³ π³ #127 A PHP warning above the System page
- β³ π #126 Notes stamped with the server's clock
- β³ π Storing every date in UTC
- β³ πͺ The portal was down for everyone signed in
- β³ βοΈ #120 Workflow notes could never be written
- β³ βοΈ #123 Three errors when running Database Verification
- β³ π #122 The description box was a stub in the corner
- β³ π£ Demo data deleted real accounts
- β³ π #117 Sign-in redirected to the wrong address
- β³ π¨ #108 The priority dot was invisible
- β³ β±οΈ #116 Time logged from the right-click menu
- β³ π #114 API keys refused by our own guard
- β³ ποΈ #110 Assigning a task told nobody
- β³ πͺ #107 Signed out while still working
- β³ π #103 "Share with Requester" reached nobody
- β³ π #102 Search found nothing for hyphens
- β³ πͺ #101 Source code editor opened behind
- β³ βοΈ #88 Subtasks could not be ticked off
- β³ π» #84 Asset deep link selected nothing
- β³ π« #79 A new ticket arrived with no status
- β³ π§ #79 A ticket from email did not say so
- β³ π #78 Bell opened to nothing
- β³ π¬ #77 Mail only collected from Inbox
- β³ π #74 The default password could not be changed
- β³ π¦ #70 Renaming an impact level
- β³ π€ #67 App-only mailboxes could not send
- β³ π #45 Verify only ever worked for Microsoft
- β³ π #45 IMAP reported as not authenticated
- β³ βοΈ An email template stopped escaping itself
- β³ π The portal dashboard showed the wrong time
- β³ π’ The folder said 99 and the list showed 96