Skip to content

Home on a phone: Home screen pages, phone title bars and stage, sheets, 44 px targets (phone-only) - #116

Closed
SashaMIT wants to merge 101 commits into
developfrom
feat/home-phone-layout-0.7.1-models
Closed

SashaMIT wants to merge 101 commits into
developfrom
feat/home-phone-layout-0.7.1-models

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Home on a phone: one-handed Home screen, phone title bars and app stage, sheets, and 44 px targets across the capsules.

Phone-only, as agreed: the desktop-visible changes moved to #134, and this PR is stacked on it (base feat/home-desktop-coherence-0.7.1-models), so the diff here is the 69 phone commits. It no longer carries #68 or #67. Merges after #80 and #134.

What a person sees on a phone

  • Home screen pages of apps with page dots, a snapping Dock, and edit mode (hold to rearrange, move between pages, Dock in/out).
  • A 44 px top bar; overflow goes to Control Centre. Launcher, Spotlight, Control Centre and Notifications open as sheets with handles.
  • Apps open full screen with a phone title bar (Close leading, Minimise trailing) and an instant title plus progress line. Swipe-down on the title bar opens the app switcher; Control Centre → Overview opens it by button. Android Back closes the top layer through stage history; iOS has no system Back, and WebKit keeps stage history off, so iPhone uses the buttons.
  • The sidebar apps (Assistant, System, People, Documents, Marketplace) use one push drawer whose corners carry the drawer fill.
  • Every measured capsule is at 0 targets under 44 px on both phone profiles.
  • On the phone bar, Reconnecting (from Model screens, chat Enter to send, centred windows and Reconnecting (desktop part of #116) #134) shows as the dot only; the words stay for screen readers.

Everything is gated on data-el-form-factor="phone". Three commits are the phone halves of commits now in #134: fa6b52e4a (phone Reconnecting dot and its phone smoke probe), 040dd5608 (System Models controls 44 px on phone), f271632fd (Assistant settings controls 44 px on phone).

Server

  • fc32b732b: gateway_home_system.rs sanitises the stored phone Home arrangement the way it already sanitises the taskbar. layout.homeDock keeps known apps only, each once. layout.homePages keeps known apps only, each once across all pages, and drops empty pages. Covered in test_home_browser_state_drops_unknown_targets.

Gates (at fcaba169e)

  • home-entropy-check, vendor-ui-tokens.sh --check and git diff --check pass at every commit.
  • Per CI and tests: warm caches, fail fast, keep only what catches real bugs #194, unit tests and the phone smoke cover the phone behaviour: 08931e66c removes the 659 lines of phone source-text contracts, and d8ea6675f adds the eight phone unit tests to source-gate.
  • Source gate 14/14; the non-Rust just verify steps.
  • cargo clippy --workspace --all-targets -- -D warnings clean; cargo test -p elastos-server --lib home passes.
  • scripts/home-phone-layout-smoke.mjs on Chromium and WebKit (iPhone 14 portrait/landscape, tablet), small-target thresholds at 0: 5 of 5 local runs green on 3 October (one on both engines, four on Chromium). One Chromium phone-landscape run on 29 September reported every capsule frame as tablet after the rotation probe; it has not recurred. If CI shows it, the size class the shell posts after a resize is the place to look.
  • The smoke's fixture holds the Home event stream open, and its poll reply carries elastos.home.events/v1. A separate closed-stream run (portrait, both engines) holds a Dock tile while a reconnect's summary refresh redraws the Dock; the run requires the redraw before the long-press fires, then the held app's menu and no launch.
  • The smoke is in just product-ui-browser, which test-capsules runs since ci: run the browser layout smokes in test-capsules #135 merged. It gates this PR's CI once Model screens, chat Enter to send, centred windows and Reconnecting (desktop part of #116) #134 merges and this PR targets develop.
  • Charter: docs/HOME_MOBILE.md.

Known and open

  • Pre-existing on feat/0.7.1-models itself, not touched here: people-product-layout-smoke (first-run copy), chat-room-configured-layout-smoke (emoji popover), archive- and library-product-layout-smoke (timeouts, locally), chat-room-ui clippy question_mark, and the two model browser smokes.
  • Still owed before merge: real-phone checks on iOS Safari and Android Chrome, recorded here: soft keyboard, Back (Android Back; iPhone buttons), rotation with a window open, and long-press on a Dock app. Then the installed Home journey and full review on the final head.
  • The event-channel recovery repair (a valid poll resets stream retries; a summary refresh can bypass the retry delay) has its own owner.

Made with Cursor

Part of #92

@andersalm andersalm mentioned this pull request Sep 30, 2026
9 tasks
SashaMIT and others added 29 commits September 30, 2026 12:19
… charter

Adds scripts/home-phone-layout-smoke.mjs: loads the real Home host and GUI
against a fixture host in Playwright Chromium and WebKit at iPhone 14
portrait, landscape and an 820 px tablet, measures targets under 44 px, text
under 12 px and horizontal overflow on every shell surface and one window per
first-party app, writes report.json plus screenshots, and asserts a per-profile
baseline that later PRs may only lower. Records the source truths the phone
layer will change (viewport-fit, bare 100vh, backdrop-filter count).

Wires the smoke into just product-ui-browser, adds docs/HOME_MOBILE.md (size
classes, rubric, gesture-surface rule, baseline, real-device checks, capsule
guidance) linked from ROADMAP.md, and pins the ratchet in home-entropy-check.

No UI change.
- viewport-fit=cover and interactive-widget=resizes-visual on the Home host
  and GUI index files, so env(safe-area-inset-*) is real on iOS and the soft
  keyboard shrinks only the visual viewport on Android like it does on iOS
- shell-form-factor.js: single reader of the 640/1100 size classes and the
  media-feature pointer class; mirrors body[data-form-factor] and
  body[data-pointer]; writes --keyboard-inset from visualViewport on
  coarse-pointer hosts (a phone held sideways stays a phone; desktop
  pinch-zoom is never a keyboard); shouldOpenMaximizedByDefault() delegates
- style.css: --stage-bottom adds --keyboard-inset; overscroll-behavior none
  on the shell; touch-action manipulation and no tap highlight on controls;
  touch-callout off on shell chrome only; 100dvh twin for the last bare
  100vh; side safe-area insets on the bar and the phone window
- home-form-factor.test.mjs in verify; entropy contracts for every truth
  above, mutation-tested; phone smoke reports fallback vs bare 100vh

Co-authored-by: Cursor <cursoragent@cursor.com>
Phone size class in CSS is one media list mirroring classifyFormFactor
(width <= 640, or coarse/hover-less pointer with height <= 640), so a
landscape phone keeps the phone shell. home-entropy-check derives the list
from PHONE_MAX_WIDTH.

Bar: --toolbar-h 44px, every control a 44x44 hit box around the 22px glyph,
16px badge with 12px numerals. Wallet and Overview leave the phone bar;
Control Centre keeps both (Quick open / Overview).

Dock: thumb scroll (taskbar-item touch-action pan-x instead of none),
scroll-snap, scroll-driven edge fades, 14x4 running indicator, safe-area
sides in landscape. With a window open the Dock tucks (body.phone-dock-tucked)
and --stage-bottom shrinks to a 24px handle; tap/swipe the handle peeks the
Dock over the app (phone-dock-peek + scrim); scrim, Escape or picking a
window tucks it. New shell-phone-dock.js, synced from updateTaskbarState.

Smoke: opens Mission Control via Control Centre, probes tuck/peek/tuck on
both phone profiles, lowers phone baselines, records one boot retry for the
WebKit first-profile flake. node:test coverage for the Dock decisions.

Co-authored-by: Cursor <cursoragent@cursor.com>
The phone block set gap: 8px on .taskbar-inner. The hidden launcher and
Assistant face stay in flow (display: flex, collapsed to 0 for the face
animation), so the column gap added 16px of dead space above the icon row:
the pill was 88px with icons low. Drop the gap; the launcher popover already
carries its own spacing inside the clipped region. The phone smoke now pins
the idle pill at --taskbar-h (72px).

Co-authored-by: Cursor <cursoragent@cursor.com>
The plate-free glyphs are drawn at 58.6% of their square for the pointer
desktop; beside 48px app plates on a phone they read small. Launcher via
background-size (its .taskbar-icon transform is reserved for magnification);
Assistant via its inner icon node so the mark's layer animation is untouched.

Co-authored-by: Cursor <cursoragent@cursor.com>
One 44px presentation of .window-head for every chrome mode: leading Close,
centred capsule icon + title, trailing Minimise drawn as a chevron (go home;
the capsule keeps running). Fullscreen hidden. The traffic-light group is
display: contents so the same buttons land in a three-column grid; chrome
modes in shell-core.js are untouched.

The head is in flow above the body in all modes, including unified
sidebar/toolbar: a phone-width capsule has content at the top of its main
column, so the desktop overlay would cover it.

A 2px accent hairline runs under the title until .window-frame.is-ready
(static under reduced motion) so the bar reads as alive while the capsule
boots. shell-window-geometry.js guards drag/resize on phone.

Smoke window baseline 5 -> 2 (only the 24px Dock handle remains).

Co-authored-by: Cursor <cursoragent@cursor.com>
Mission Control is the phone's app switcher: title-bar swipe-down opens it
(pointer capture across the capsule frame, the ending click swallowed), cards
carry the capsule icon + name and a 44 px Close on coarse pointers, portrait
Space thumbs are sized by height, copy loses mouse language. Windows rise
from the Dock in 200 ms (none under reduced motion).

Stage history keeps one entry of the shell's own, decided from history.state
and never more than one back() per close cycle; popstate closes the top layer
then goes home. Off on WebKit (buttons only): one back() after pushState took
the shell frame to about:blank there — recorded in docs/HOME_MOBILE.md.

Pure model unit-tested (scripts/home-phone-stage.test.mjs, in verify); the
phone smoke probes swipe, back, rotation and the Home frame staying alive;
entropy contract pins it all (21 mutations caught).

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ut fixtures

Library imports /apps/home/home-navigation-client.js and the Browser imports
/apps/home/home-clipboard-client.js; neither fixture served them, so both
product layout smokes failed before measuring anything (500 / stuck on
"Loading Library...").

Co-authored-by: Cursor <cursoragent@cursor.com>
The launcher and Assistant sit outside the scrolling app row, so when the
pill reached its width limit flex shrank them to 45 px and their glyphs
drew a third smaller than the app plates. They now keep full tiles and the
scrolling row gives way. The 1.5x glyph scale applies only to plate-free
art (the launcher, and the Assistant when it wears its plate-free mark);
a plate raster already fills its square.

Control Centre and Notifications span the phone stage with even margins
instead of hugging the trailing edge.

Co-authored-by: Cursor <cursoragent@cursor.com>
…push drawer

A capsule cannot tell a phone stage from a narrow desktop window by its own
width, so on phone every capsule kept the desktop traffic-light insets and
opened with dead space above and beside its content. The shell now posts
elastos:shell-layout {formFactor, pointer} to each frame on load and on a
size-class change (shell-capsule-layout.js). The shared theme runtime takes
it only from the opaque parent and only allowlisted values and sets
html[data-el-form-factor] and [data-el-pointer]; the shared sheet zeroes
--window-chrome-safe-top/-leading on phone and adds --el-touch-target and
the drawer tokens.

elastos-drawer.js is the Assistant's saved-chats pattern for any capsule
sidebar, bound by markup alone: content first, a 44 px toggle slides the
sidebar in and pushes the view aside, tapping the view (swallowed), Escape
or picking an item closes it; inert while closed. Vendored only to the
capsules whose sidebar uses it.

Unit-tested in verify; the phone smoke checks the size class reaches every
shared-theme frame on both engines; scripts/lib/phone-drawer-assert.mjs is
the shared smoke assertion for capsule drawers.

Co-authored-by: Cursor <cursoragent@cursor.com>
On phone the store opens on its content; the Discover title leads with a 44 px sidebar toggle that slides the categories in and pushes the store aside. Nav items are 44 px at 16 px and search is 16 px so iOS does not zoom. The layout smoke asserts the closed, open and picked states.

Co-authored-by: Cursor <cursoragent@cursor.com>
The 220 px list column squeezed the editor to half the phone. On phone the editor takes the full width, the title row leads with the list toggle, actions are one row of 44 px buttons, and the editor and fields are 16 px. Split has no room on a phone and reads as Write; the desktop Hide list control gives way to the drawer. The layout smoke asserts the editor size, the hidden controls and the drawer.

Co-authored-by: Cursor <cursoragent@cursor.com>
Favorites, path and search took 225 px above the first file. On phone the navigation row carries Back, Up, the current folder as its title, Search, view and More at 44 px, and Favorites sit under it as one sliding chip row; opening Search gives the field the whole row. Rows are 48 px at 16 px, the Name/Modified header is gone (only names show), and status floats above the footer as a pill. The list now starts at 104 px.

Co-authored-by: Cursor <cursoragent@cursor.com>
The menu button sat 72 px in, clearing traffic lights that do not exist on phone. It now takes the leading edge as a 44 px target, vertically centred on the page title, which is indented to share its line; the open sidebar starts below it. Phone landscape keeps the desktop sidebar. The UI/UX smoke gains a phone step and joins the browser lane.

Co-authored-by: Cursor <cursoragent@cursor.com>
At 640 px and below the list took a fixed 42% band, so with one or two requests the detail started mid-screen. The list is now as tall as its requests (capped at 40 dvh, then it scrolls) and the detail follows directly. The layout smoke fails on the old rule.

Co-authored-by: Cursor <cursoragent@cursor.com>
The toolbar kept a 96 px traffic-light inset on phone. The navigation row now spans the stage with 40-44 px controls and a 44 px, 16 px address field. The layout smoke gains a phone step and joins the browser lane.

Co-authored-by: Cursor <cursoragent@cursor.com>
Records the shell-to-capsule size class, the shared push drawer and the per-capsule phone layouts; the touch token is --el-touch-target.

Co-authored-by: Cursor <cursoragent@cursor.com>
At 1.5x on full tiles the launcher and the Assistant mark matched the plates' height exactly and read too heavy beside them; 1.3x sits them just inside the plates.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Write/Read and Save stay in one unscrolled row; Save as, Publish,
Unpublish, Copy Published Link and Delete open from a More button as
labelled 44 px rows. The menu reuses the real buttons, so their handlers
and enabled state are unchanged; desktop keeps them inline.

Co-authored-by: Cursor <cursoragent@cursor.com>
@SashaMIT

SashaMIT commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Develop moved by 8 PRs (#239, #241, #243–#248) while the pre-push ran, so the head is now 2cf55bde3, with develop at 6a4f17dc6. One conflict: ROADMAP.md. I took develop's version from #239 (it already lists #92), so this PR no longer adds the roadmap link to docs/HOME_MOBILE.md. capsules/system/browser/system.js merged without conflict with #243's change notes. just ci-local-prepush passed on 2cf55bde3.

@SashaMIT

SashaMIT commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Real-phone checks on 2cf55bde3, done by @SashaMIT on 6 October:

  • Device: iPhone, Safari
  • Route: the Home shell from this head on the phone smoke's fixture host, opened over the local network (http://<mac-lan-ip>:8787/apps/home/). It runs the real Home host and GUI code with fixture data and no sign-in, so app bodies show their empty states. The installed Home journey stays with your review.

All four checks pass:

  • Soft keyboard: Spotlight and the Assistant message box stay visible above the keyboard.
  • Back: Close (✕, leading) closes the app; Minimise (chevron, trailing) returns it Home; swipe-down on the title bar opens the app switcher. iOS has no system Back, so these buttons are the iPhone Back path.
  • Rotation: an open app stays open and fills the screen in landscape and again in portrait.
  • Long-press: holding a Dock icon opens its menu as a bottom sheet, with no text selection or magnifier, and lifting the finger opens nothing.

Still open: the same four checks on Android Chrome, including Android Back. No Android phone was available for this round.

@andersalm

Copy link
Copy Markdown
Contributor

Review round 2 (Codex, GPT family) on 2cf55bd: code PASS. Round 1's Documents regression and events schema are fixed; no desktop regression; no new network or capability surface; 70/70 phone tests.
Two gates still open: (1) @SashaMIT please merge current develop so CI runs the installed Home journey (#240) on this PR; (2) Android Chrome checks (keyboard, Back, rotation, Dock long-press). We run (2) on BrowserStack.

@andersalm andersalm mentioned this pull request Oct 7, 2026
3 of 7 tasks
@andersalm

Copy link
Copy Markdown
Contributor

@SashaMIT the two review follow-ups (layout smoke null measurement, stream recovery) now live in #92.
Please merge current develop so the installed journey runs, then the Android checks.

…yout-0.7.1-models-split

Co-authored-by: Cursor <cursoragent@cursor.com>
@andersalm

Copy link
Copy Markdown
Contributor

@SashaMIT go ahead and push the develop merge through the pre-push gate, no need to ask first; post the head SHA here.

@SashaMIT

SashaMIT commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Merged develop 34b2e5c (0 behind); local pre-push gate passed for 8c9ccb9, so CI can now run the installed Home journey.
Android checks follow once that run is green.

SashaMIT and others added 2 commits October 10, 2026 21:22
…yout-0.7.1-models-split

Co-authored-by: Cursor <cursoragent@cursor.com>
…yout-0.7.1-models-split

Co-authored-by: Cursor <cursoragent@cursor.com>
@SashaMIT

Copy link
Copy Markdown
Contributor Author

Merged develop again (alpha.15, 0 behind); local pre-push gate passed for 12c06a6, so CI can run the installed Home journey.
Android checks follow once that run is green.

@SashaMIT

Copy link
Copy Markdown
Contributor Author

Merged develop again (alpha.15, #344 and #346). Clean merge, 0 behind, gate passed for aed3673; our diff is still the phone layout work and the vendored CSS/theme.

@andersalm

Copy link
Copy Markdown
Contributor

@SashaMIT cross-family review of aed3673: two P2s on phone Back, otherwise clear. (1) shell-phone-stage.js:48: the layer count misses #assistant-space and #desktop-context-menu, so Back leaves Home instead of closing Assistant or the long-press menu; count them and route Back to their close functions. (2) shell-phone-stage.js:92: after switching Spaces from the Dock, Back minimises the hidden window from the other Space; apply the hidden/data-space-visible check to the active candidate and fallback. A browser test for each, and it can merge.

Back counted neither layer, and the Agent room is not a desktop Space, so the fullscreen Escape handler took the gesture and left the room open. Back now closes those two first, and minimises the window on the current Space rather than a hidden window from another Space.

Co-authored-by: Cursor <cursoragent@cursor.com>
@SashaMIT

Copy link
Copy Markdown
Contributor Author

Back on a0dc89d closes the long-press menu and Assistant before the fullscreen Escape handler, and minimises the window on the current Space.
Chromium and WebKit phone-portrait layout smoke passed.

@andersalm

Copy link
Copy Markdown
Contributor

Merged into develop through the 0.8.0 release train #372 (merge 3f8676a). #309 landed at f173210 (bcb8174 + rebuilt UI assets + 3 test fixes), which contains #116's commits.

@andersalm andersalm closed this Oct 14, 2026
@andersalm

Copy link
Copy Markdown
Contributor

Correction: this PR did NOT land. b01464f ("keep Sasha phone work in PR116") removed all 111 files of this diff from the Chat branch before #309/#372 merged, so develop (alpha.17 37df2f6, alpha.18 ac7d018) has no phone shell. Landing a0dc89d now = revert b01464f + the 3-file Back fix (~69 files vs develop), plus the missing re-review of a0dc89d and the Android checks.

@andersalm

Copy link
Copy Markdown
Contributor

Restored on branch fix/080-phones (b925a48, not pushed): revert of b01464f + a0dc89d Back fix + fixes; phone smoke PASS on Chromium (WebKit not run), desktop shell smokes unchanged. Codex round 4 still finds phone Back gaps (brand menu inside the toolbar, animated context-menu hide lets a second Escape exit fullscreen, Mission Control not ranked) plus one desktop composer rule (agent-harness.css:2877 not gated on the phone form factor). Next design: an explicit closer per surface and one z-ordered ranking. Proposed for 0.8.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants