Skip to content

feat(mobile): modernize dashboard & nav mobile UX - #161

Merged
VoMinhKhoii merged 2 commits into
mainfrom
claude/mobile-ux-improvements-1vjnvb
Jun 29, 2026
Merged

feat(mobile): modernize dashboard & nav mobile UX#161
VoMinhKhoii merged 2 commits into
mainfrom
claude/mobile-ux-improvements-1vjnvb

Conversation

@VoMinhKhoii

@VoMinhKhoii VoMinhKhoii commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

A pass of mobile-UX polish on the Flutter app (apps/mobile-flutter) to make it feel more modern and interactive: swipe-to-open navigation, broader haptic feedback, a cleaner weight input, app-wide tap-to-dismiss keyboard, trimmed dashboard dead space, and a draggable log-meal FAB.

Changes

  • Nav drawer — slide to open: added a left-edge swipe-to-open gesture (1:1 finger tracking with fling/threshold settle), in addition to the hamburger tap. (shell/tab_scaffold.dart)
  • Haptics audit: tactile cues added where they were missing — the shared NhamButton, the header back button, the drawer open, and the meal FAB (open / close / submit / pick-up / edge-snap). Weight save now also gives a heavy warn-buzz on rejected input. (shared/widgets/nham_primitives.dart, shell/app_header.dart, dashboard widgets)
  • Weight input: submit button moved beneath the field (full-width, thumb-friendly) instead of side-by-side; field is always labelled "Today's weight"; removed the scale icon. (dashboard/widgets/compact_weight_log.dart)
  • Tap-to-dismiss keyboard, app-wide: tapping empty surface now drops focus, added to the shared Screen primitive so every screen inherits it. (shared/widgets/nham_primitives.dart)
  • Dashboard end-space: removed the trailing margin on the last section and tightened the bottom padding to the FAB's actual footprint, eliminating the dead gap at the end of the scroll. (dashboard/screens/dashboard_screen.dart)
  • Draggable log-meal FAB: the FAB can now be picked up and dropped anywhere; it snaps to the nearest edge, remembers the spot for the session, lifts/deepens its shadow while held, and the meal-input bar re-anchors above or below it. (dashboard/widgets/floating_meal_trigger.dart)

Testing

Manual review only — no Flutter SDK is available in this environment, so changes were verified by hand (structure, balanced braces, no unused imports; the repo's lints are non-fatal and no CI runs flutter analyze). Recommend a local flutter run to confirm the new gestures feel right.

Notes

  • FAB position persistence is session-scoped (Riverpod provider) — survives tab switches and rebuilds, resets on app restart. No shared_preferences dependency exists in the project and flutter_secure_storage is meant for secrets, so cross-launch persistence was intentionally skipped. Happy to add it if wanted.

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • The meal action button can now be dragged and will snap to the nearest edge, with the input bar repositioning automatically for better reachability.
    • Added a left-edge swipe area to open the app drawer more easily.
  • Bug Fixes

    • Improved dashboard spacing so content aligns better with the bottom action area.
    • Reduced extra spacing below the final dashboard section.
    • Tapping outside inputs now dismisses the keyboard.
    • Weight entry and app navigation now include clearer haptic responses for a more responsive feel.

Flutter app (apps/mobile-flutter) mobile-UX polish:

- Nav drawer: add left-edge swipe-to-open (1:1 finger tracking + fling/
  threshold settle), not just the hamburger tap. Light haptic on open.
- Haptics audit: tactile cues on the shared NhamButton, the header back
  button, the drawer open, and the meal FAB (open/close/submit/pick-up/
  snap). Weight save now also warns (heavy impact) on rejected input.
- Weight input: stack the submit button beneath the field (full-width,
  thumb-friendly) instead of side-by-side; always label it "Today's
  weight"; drop the scale icon.
- Tap anywhere on empty surface dismisses the keyboard, app-wide (added
  to the shared Screen primitive, so every screen inherits it).
- Dashboard: trim the dead space at the end (no trailing margin on the
  last section + tighter bottom padding sized to the FAB footprint).
- Log-meal FAB is now draggable — pick it up, drop it anywhere; it snaps
  to the nearest edge and remembers the spot for the session. Lifts/
  shadows while held; the meal-input bar re-anchors above/below it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WrWVKndNCM8jguxsJMvEPP
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@VoMinhKhoii, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable usage-based reviews in Billing to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information, and refer to the rate limits docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 693e0360-83ba-44d7-a441-e04ed3e16035

📥 Commits

Reviewing files that changed from the base of the PR and between 8a146a9 and 9af7a06.

📒 Files selected for processing (1)
  • apps/mobile-flutter/lib/shell/tab_scaffold.dart
📝 Walkthrough

Walkthrough

Adds a draggable, session-persistent meal FAB with snap-to-edge behavior and dynamic input bar anchoring. Introduces haptic feedback to buttons, back navigation, and drawer open/swipe gestures. Refactors compact weight log to a vertical layout. Adds tap-to-dismiss keyboard on Screen. Adjusts dashboard scroll padding and section bottom margin handling.

Changes

Dashboard UX improvements

Layer / File(s) Summary
Global haptics and tap-to-dismiss keyboard
lib/shared/widgets/nham_primitives.dart, lib/shell/app_header.dart
NhamButton now triggers HapticFeedback.lightImpact() before onPressed; Screen wraps content in a GestureDetector to dismiss keyboard on background tap; _BackButton adds selectionClick haptic before calling onBack.
Tab scaffold left-edge swipe-to-open drawer
lib/shell/tab_scaffold.dart
Computes panelWidth (88vw, max 320px), adds a 20px left-edge GestureDetector strip driving drawer open animation, and emits lightImpact haptic when drawer settles open.
Compact weight log vertical layout
lib/features/dashboard/widgets/compact_weight_log.dart
Removes icon import; replaces horizontal field+button row with vertical column (label, full-width TextField, standalone submit row); adds heavyImpact haptic on invalid submission; updates submit button padding.
Draggable/snappable meal FAB
lib/features/dashboard/widgets/floating_meal_trigger.dart
Converts FloatingMealTrigger to ConsumerStatefulWidget; adds mealFabPositionProvider for session-persistent position; implements pan gesture with edge snapping, clamped movement, and dynamic above/below input bar anchoring; adds haptics on open/close/submit/drag.
Dashboard scroll padding and section trailing margin
lib/features/dashboard/screens/dashboard_screen.dart
Reduces ListView bottom padding from bottomInset + 96 to bottomInset + 76 in both content and skeleton; adds last flag to _Section to suppress bottom margin on the Consistency section.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • VoMinhKhoii/Nham#155: Modifies the same compact_weight_log.dart and floating_meal_trigger.dart files with overlapping UI and haptic behavior changes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main mobile dashboard and navigation UX changes in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/mobile-ux-improvements-1vjnvb

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/mobile-flutter/lib/features/dashboard/widgets/compact_weight_log.dart (1)

177-180: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Avoid uppercasing translated copy in code.

toUpperCase() here can produce incorrect text in some locales. Keep the intended casing in the translation itself, or route this through a locale-aware casing helper instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/mobile-flutter/lib/features/dashboard/widgets/compact_weight_log.dart`
around lines 177 - 180, The translated label in compact_weight_log.dart is being
force-uppercased in code, which can break locale-specific text handling. Update
the Text usage in the dashboard weight card so it renders the translation from
tr('dashboard.weightCard.todaysWeight') without calling toUpperCase(), and if
uppercase styling is still required, move that casing into the translation or
use a locale-aware helper instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/mobile-flutter/lib/shell/tab_scaffold.dart`:
- Around line 100-106: The edge-swipe handling in GestureDetector inside
tab_scaffold.dart is missing cancel handling, which can leave _controller.value
stuck mid-drag. Add onHorizontalDragCancel alongside onHorizontalDragUpdate and
onHorizontalDragEnd, and have it snap the drawer to the nearest open/closed
state using the same _onEdgeDragEnd or equivalent logic so interrupted swipes
always settle cleanly.

---

Nitpick comments:
In `@apps/mobile-flutter/lib/features/dashboard/widgets/compact_weight_log.dart`:
- Around line 177-180: The translated label in compact_weight_log.dart is being
force-uppercased in code, which can break locale-specific text handling. Update
the Text usage in the dashboard weight card so it renders the translation from
tr('dashboard.weightCard.todaysWeight') without calling toUpperCase(), and if
uppercase styling is still required, move that casing into the translation or
use a locale-aware helper instead.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8f0c8424-6502-452b-b09e-e6ebea1025cf

📥 Commits

Reviewing files that changed from the base of the PR and between 355073c and 8a146a9.

📒 Files selected for processing (6)
  • apps/mobile-flutter/lib/features/dashboard/screens/dashboard_screen.dart
  • apps/mobile-flutter/lib/features/dashboard/widgets/compact_weight_log.dart
  • apps/mobile-flutter/lib/features/dashboard/widgets/floating_meal_trigger.dart
  • apps/mobile-flutter/lib/shared/widgets/nham_primitives.dart
  • apps/mobile-flutter/lib/shell/app_header.dart
  • apps/mobile-flutter/lib/shell/tab_scaffold.dart

Comment thread apps/mobile-flutter/lib/shell/tab_scaffold.dart
An interrupted left-edge swipe cancels the horizontal-drag recognizer
without firing onHorizontalDragEnd, which could leave the drawer's
animation controller stuck mid-position (half-open). Add
onHorizontalDragCancel to settle it to the nearest open/closed state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WrWVKndNCM8jguxsJMvEPP
@VoMinhKhoii
VoMinhKhoii marked this pull request as ready for review June 29, 2026 06:02
@VoMinhKhoii
VoMinhKhoii merged commit d7d05e6 into main Jun 29, 2026
10 checks passed
@VoMinhKhoii
VoMinhKhoii deleted the claude/mobile-ux-improvements-1vjnvb branch June 29, 2026 06:02
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