Skip to content

feat(app): native-feel pass - #55

Open
frahlg wants to merge 2 commits into
mainfrom
ux-native-feel-pass
Open

feat(app): native-feel pass#55
frahlg wants to merge 2 commits into
mainfrom
ux-native-feel-pass

Conversation

@frahlg

@frahlg frahlg commented Aug 21, 2026

Copy link
Copy Markdown
Member

Two commits: the UX pass, and one small test fix that unblocks CI (details below). No merge until reviewed.

What changed

Native feel

  • Press feedback for every control: one global :active rule plus touch-action: manipulation in base.css (previously only the four tab buttons answered a press).
  • Direction-aware tab transitions: the incoming panel slides from the side of travel (routeIndex exported from route.svelte.ts). Hidden views never animate; reduced motion collapses to an instant swap through the existing token.
  • Haptic tick on tab switch where the platform has one.
  • Phone-shaped shell on wide screens: .app caps at 34rem and centres, so iPad/desktop no longer show a left-hugging column under a full-width tab bar.
  • interactive-widget=resizes-content: Android Chrome shrinks the layout for the keyboard instead of painting it over the EV sheet's inputs.
  • Live theme: a matchMedia listener follows the OS mid-session unless a choice is stored.
  • Manifest: "id": "/", long-press shortcuts for Plan and History.
  • Update check runs once at registration, so an install left foregrounded still learns about new builds.

Robustness

  • The settling pane says "Opening your home" after 700 ms instead of sitting blank.
  • Cancel on the pairing and recovering stages — a stalled passkey ceremony no longer needs the OS to escape. A result that lands anyway still applies.

Polish

  • New tokens: --scrim per theme, --z-band/overlay/sheet, --radius-pill. Both sheets and the canvas zero-line consume them; no raw colour outside tokens.css except documented cases.
  • LiveChart steps straight to new readings and snaps its axis under reduced motion.
  • Micro-text floor 10px, range pickers meet the 44px target floor, label grammar via .label.

The test-fix commit

LivePanel.svelte.test.ts failed on main before this PR: Now's hero (from #53/#54) fetches /api/status and /api/savings/daily in chunks that land inside the window the test judged, so "the live line needs only the stream" read as a failure. The fix lets those background asks settle first, then measures what the tap alone adds — which is the thing the test was written to prove. Fails on main, passes here.

Verification

  • npm run verify: 918 tests passed, 1 skipped, svelte-check 0 errors / 0 warnings, production build clean.
  • New tests: route ordering, tab direction, settling note timing, launch update check, stalled-ceremony Cancel.

Deferred (need device testing or their own PR)

  • iOS startup images (white flash on dark cold starts) — needs PNG generation per device class.
  • Status bar style black → default — must be verified against the WebKit inset bug on hardware.
  • Global px→rem for Dynamic Type — large mechanical diff, better alone.

Note

Cursor Bugbot is generating a summary for commit 83375eb. Configure here.

frahlg added 2 commits August 21, 2026 19:18
Press feedback on every control, direction-aware tab transitions and a
haptic tick on tab switch. The shell keeps a phone shape on wide screens;
the theme follows the OS live; the Android keyboard shrinks the layout so
bottom sheets stay usable.

Two failure paths now leave on their own: a stalled passkey ceremony gets
a Cancel, and an open that outlives a beat says what it is doing. Manifest
gains id and long-press shortcuts; update checks run at launch.

Polish: scrim, z-index and pill tokens replace literals in the sheets and
the canvas zero-line; micro-text sits at 10px or above; range pickers meet
the 44px target floor.
The hero's box-page snapshot and the charger ask land in chunks after
mount, inside the window this test judged. Let them settle first, so the
assertion measures what the tap alone adds — which is the thing it was
written to prove.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83375eb093

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/App.svelte
Comment on lines +903 to +904
max-width: 34rem;
margin-inline: auto;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep fixed sheets within the capped shell

On viewports wider than 34rem, this caps and centers the main app but not its modal sheets: the .sheet rules in both LivePanel.svelte and EvPanel.svelte use position: fixed; left: 0; right: 0, so they remain viewport-wide because this ancestor does not establish their fixed-position containing block. Opening a live-flow or EV sheet on a tablet/desktop therefore produces a full-width panel beneath a narrow centered app; constrain those sheets to the same width and centering as the shell.

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83375eb. Configure here.

Comment thread src/App.svelte
position: fixed;
inset: 0;
max-width: 34rem;
margin-inline: auto;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sheets ignore phone-shaped shell

Medium Severity

Capping .app at 34rem and centering it does not create a containing block for position: fixed descendants. EvPanel and LivePanel sheets still use left: 0 / right: 0 against the viewport, so on tablet and desktop they span the full window while the shell stays phone-width. portal places those layers on .app, but fixed positioning remains viewport-relative without a transform or similar on the shell.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 83375eb. Configure here.

@cursor
cursor Bot requested a review from davmoz August 21, 2026 17:25

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a non-blocking comment: Cursor Bugbot skipped and reported one unresolved finding that needs human review, so this PR is not approved. Assigned Leitet and davmoz.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor
cursor Bot requested a review from Leitet August 21, 2026 17:25
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ftw-webapp 83375eb Commit Preview URL

Branch Preview URL
Aug 21 2026, 05:22 PM

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.

1 participant