Skip to content

feat(ui): modernize shell nav and unify health hub - #99

Merged
YKDBontekoe merged 5 commits into
mainfrom
cursor/ui-modernization-e60d
Jul 13, 2026
Merged

YKDBontekoe merged 5 commits into
mainfrom
cursor/ui-modernization-e60d

Conversation

@YKDBontekoe

@YKDBontekoe YKDBontekoe commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

Modernizes KYNOS shell navigation and consolidates health surfaces per the UI modernization plan.

Navigation

  • Replaces floating bottom tab bar with a left-edge glass KynosNavRail (icon-forward, tooltips, haptics)
  • Frees the bottom of the coach tab for chat input
  • Adds subtle ambient gradient at shell level

Health hub

  • Merges orphaned dashboard widgets into TrainingPage as a unified Health hub
  • Tiered layout: Today (readiness + brief) → This week → Body signals & trends → Runs → Collapsible More (check-ins, experiments, gait/Nexus Lab)
  • Sticky section jump bar (Today · Week · Trends · Runs · More)
  • Token-aligned KynosSegmentedControl for chart range/metric pickers

Coach & Journey

  • Leaner coach empty state: readiness chip + brief + 4 glass suggestions
  • Journey tab adds DailyQuestTeaser preview

Design system

  • New shared widgets: KynosPageHeader, KynosCollapsibleSection, KynosSectionJumpBar, KynosSegmentedControl, KynosNavRail
  • LayoutTokens.shellBottomPadding is now context-aware (safe-area)

Validation

  • flutter analyze — 0 errors (2 info-level directive ordering hints)
  • flutter test — 250 passed
  • flutter build web — succeeded

Follow-ups (not in this PR)

  • Secondary screen polish (Settings, onboarding assets, web icons)
  • Retire standalone DashboardPage routing references in CODEMAP
  • Glass assistant bubbles (GlassCard on coach messages)
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Replaced bottom navigation with a left-side navigation rail for easier app-wide navigation.
    • Introduced a unified Health hub with sections for today, weekly progress, body signals, recent runs, and more.
    • Added daily quest previews to the Character page.
    • Added collapsible sections, section jump navigation, page headers, and segmented controls.
    • Coach chat now displays readiness information and simplified suggestion prompts.
  • Improvements

    • Updated scrolling, spacing, animations, and safe-area behavior for the new navigation layout.
    • Added HealthKit connection and expanded health insights within the Health hub.

Replace the floating bottom tab bar with a left-edge glass navigation rail
for a coach-first layout that keeps the chat input area clear.

Merge dashboard today surfaces into the Health tab as a unified hub with
tiered sections, sticky jump chips, and collapsible advanced blocks.
Polish the coach empty state with a compact readiness chip and streamline
Journey with a daily quest teaser.

Co-authored-by: Youri Bontekoe <YKDBontekoe@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@cursor[bot], you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
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 refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 58dcdd4d-501f-4d24-a3c9-ca53b4351aa1

📥 Commits

Reviewing files that changed from the base of the PR and between bb954e3 and bd6f13c.

📒 Files selected for processing (7)
  • CODEMAP.md
  • lib/features/character/presentation/pages/character_page.dart
  • lib/features/dashboard/presentation/pages/dashboard_page.dart
  • lib/features/training/presentation/pages/training_page.dart
  • lib/shared/widgets/daily_quest_teaser.dart
  • lib/shared/widgets/kynos_segmented_control.dart
  • lib/shared/widgets/widgets.dart
📝 Walkthrough

Walkthrough

The app shell now uses a left navigation rail, while TrainingPage becomes a unified health hub with pinned navigation and refreshed health sections. New shared widgets support headers, section jumps, segmented controls, and collapsible content. Character, dashboard, coach chat, and related tests are updated accordingly.

Changes

Health hub redesign

Layer / File(s) Summary
Shared health-hub widgets
lib/shared/widgets/*, lib/shared/providers/dashboard_summary_provider.dart
Adds reusable collapsible sections, page headers, section jump bars, segmented controls, and dashboard provider exports.
Shell navigation rail
lib/core/theme/layout.dart, lib/shared/widgets/kynos_nav_rail.dart, lib/app/shell_page.dart, test/shared/widgets/kynos_nav_rail_test.dart, test/widget_test.dart
Replaces bottom navigation with a left-edge rail, updates shell spacing and safe-area behavior, and validates rail selection and tooltips.
Unified health hub page
lib/features/training/presentation/pages/training_page.dart, test/features/training/training_page_test.dart
Reworks TrainingPage into five scrollable health sections with pinned navigation, broader refresh handling, HealthKit connection content, and segmented chart controls.
Health content integrations
lib/features/character/presentation/pages/character_page.dart, lib/features/dashboard/presentation/pages/dashboard_page.dart, lib/features/coach_chat/presentation/widgets/message_list.dart
Adds the daily quest teaser, adopts context-aware shell padding, and displays readiness information in the coach empty state.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ShellPage
  participant KynosNavRail
  participant TrainingPage
  participant HealthProviders
  User->>KynosNavRail: Select Health
  KynosNavRail->>ShellPage: Return selected index
  ShellPage->>TrainingPage: Display health hub
  TrainingPage->>HealthProviders: Refresh health and dashboard data
  TrainingPage-->>User: Render pinned header and health sections
Loading

Possibly related PRs

Poem

A rabbit hops where rail lights gleam,
Health cards bloom like carrots in a dream.
Chips jump sections, charts softly sway,
Quests and readiness brighten the day.
“Tap,” says the bunny, “and onward we go!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the summary well but is missing the required Checklist template section and Agent notes section. Add the Checklist section with the required items and include Agent notes per the repository template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, specific, and accurately summarizes the main UI modernization work 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.

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.

cursoragent and others added 2 commits July 13, 2026 13:45
Co-authored-by: Youri Bontekoe <YKDBontekoe@users.noreply.github.com>
Co-authored-by: Youri Bontekoe <YKDBontekoe@users.noreply.github.com>
@cursor
cursor Bot marked this pull request as ready for review July 13, 2026 13:58
Co-authored-by: Youri Bontekoe <YKDBontekoe@users.noreply.github.com>

@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: 3

🧹 Nitpick comments (5)
lib/features/coach_chat/presentation/widgets/message_list.dart (1)

17-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Import KynosChip from the shared widget barrel

Use package:kynos/shared/widgets/widgets.dart here instead of importing kynos_chip.dart directly so shared-widget imports stay consistent.

🤖 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 `@lib/features/coach_chat/presentation/widgets/message_list.dart` around lines
17 - 18, Update the KynosChip import in message_list.dart to use the shared
widget barrel package:kynos/shared/widgets/widgets.dart instead of the direct
kynos_chip.dart import, while leaving the widget usage unchanged.

Source: Coding guidelines

lib/features/training/presentation/pages/training_page.dart (1)

49-49: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Split this page into extracted section widgets.

At ~579 lines with a five-section inline build, this file exceeds the project's file-size limit. Extract the "Today", "This week", "Body signals/Trends", "Recent runs", and "More" sections into presentation/widgets/ to bring the file under the target and simplify build.

As per coding guidelines: "Keep hand-written files under about 250 lines; split larger UI code into presentation/widgets/."

🤖 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 `@lib/features/training/presentation/pages/training_page.dart` at line 49,
Refactor _TrainingPageState.build by extracting the inline Today, This week,
Body signals/Trends, Recent runs, and More sections into focused widgets under
presentation/widgets/. Pass each widget only the state and callbacks it needs,
preserve existing behavior and layout, and leave TrainingPage under the
project’s approximately 250-line file-size limit.

Source: Coding guidelines

lib/shared/widgets/kynos_section_jump_bar.dart (1)

28-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use Gap for inter-chip spacing.

-            if (i > 0) const SizedBox(width: Spacing.xs),
+            if (i > 0) const Gap(Spacing.xs),

Requires adding import 'package:gap/gap.dart';. As per coding guidelines: "use Gap instead of SizedBox for semantic spacing".

🤖 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 `@lib/shared/widgets/kynos_section_jump_bar.dart` at line 28, Replace the
inter-chip SizedBox spacing in the section jump bar’s chip-building logic with
Gap, add the package:gap/gap.dart import, and preserve the existing Spacing.xs
width and conditional placement.

Source: Coding guidelines

lib/core/theme/layout.dart (1)

9-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use @Deprecated here instead of doc-comment text
/// @deprecated`` does not trigger analyzer deprecation warnings, so shellNavBarHeight and `shellBottomPaddingLegacy` remain usable without any migration signal. Replace both with `@Deprecated('...')`.

🤖 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 `@lib/core/theme/layout.dart` around lines 9 - 22, Replace the doc-comment
deprecation markers on shellNavBarHeight and shellBottomPaddingLegacy with Dart
`@Deprecated` annotations containing migration guidance. Keep the existing
comments and values unchanged, and ensure both declarations emit analyzer
deprecation warnings.
test/features/training/training_page_test.dart (1)

7-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Override providers with fakes per testing guidelines.

TrainingPage reads from multiple providers (dashboardSummaryProvider, healthSummaryProvider, todayInsightsStateProvider, etc.) but the test uses a bare ProviderScope with no overrides. As per coding guidelines, "widget tests must use ProviderScope with overridden fakes instead of real repositories." The test passes only because it checks static strings, but it is fragile and non-compliant.

🧪 Proposed fix: add provider overrides
   testWidgets('TrainingPage renders health hub header', (tester) async {
     await tester.pumpWidget(
-      const ProviderScope(child: MaterialApp(home: TrainingPage())),
+      ProviderScope(
+        overrides: [
+          dashboardSummaryProvider.overrideWith(() => FakeDashboardSummaryProvider()),
+          healthSummaryProvider.overrideWith(() => FakeHealthSummaryProvider()),
+          todayInsightsStateProvider.overrideWith(() => FakeTodayInsightsProvider()),
+          // Add other provider overrides as needed
+        ],
+        child: MaterialApp(home: TrainingPage()),
+      ),
     );
🤖 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 `@test/features/training/training_page_test.dart` around lines 7 - 16, Update
the TrainingPage widget test to override its consumed providers, including
dashboardSummaryProvider, healthSummaryProvider, and todayInsightsStateProvider,
with deterministic fake values or notifier implementations in ProviderScope.
Keep the existing header assertions unchanged and avoid allowing real
repositories or provider side effects during the test.

Source: Coding guidelines

🤖 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 `@lib/features/character/presentation/pages/character_page.dart`:
- Line 20: Move the DailyQuestTeaser widget from the dashboard presentation
widgets to lib/shared/widgets, export it through the shared widgets barrel, and
update both dashboard and character consumers to import it from the shared
barrel instead of the dashboard feature.

In `@lib/features/training/presentation/pages/training_page.dart`:
- Around line 70-90: Update _refreshHealthHub to await the futures for every
invalidated run/week provider, including healthHistoryProvider(days: 28),
healthHistoryProvider(days: days), recentRunsProvider(days: 365, limit: 60), and
recentRunsProvider(days: 30, limit: 3), so refresh completes only after all
displayed cards reload.

In `@lib/shared/widgets/kynos_segmented_control.dart`:
- Around line 70-91: Wrap the `_Segment` interactive content in `Semantics`,
matching `_RailItem`’s accessibility pattern by exposing `button: true`,
`selected: selected`, and `label: label`. Also ensure the `GestureDetector` uses
an opaque hit-test behavior so the full segment area remains interactive.

---

Nitpick comments:
In `@lib/core/theme/layout.dart`:
- Around line 9-22: Replace the doc-comment deprecation markers on
shellNavBarHeight and shellBottomPaddingLegacy with Dart `@Deprecated` annotations
containing migration guidance. Keep the existing comments and values unchanged,
and ensure both declarations emit analyzer deprecation warnings.

In `@lib/features/coach_chat/presentation/widgets/message_list.dart`:
- Around line 17-18: Update the KynosChip import in message_list.dart to use the
shared widget barrel package:kynos/shared/widgets/widgets.dart instead of the
direct kynos_chip.dart import, while leaving the widget usage unchanged.

In `@lib/features/training/presentation/pages/training_page.dart`:
- Line 49: Refactor _TrainingPageState.build by extracting the inline Today,
This week, Body signals/Trends, Recent runs, and More sections into focused
widgets under presentation/widgets/. Pass each widget only the state and
callbacks it needs, preserve existing behavior and layout, and leave
TrainingPage under the project’s approximately 250-line file-size limit.

In `@lib/shared/widgets/kynos_section_jump_bar.dart`:
- Line 28: Replace the inter-chip SizedBox spacing in the section jump bar’s
chip-building logic with Gap, add the package:gap/gap.dart import, and preserve
the existing Spacing.xs width and conditional placement.

In `@test/features/training/training_page_test.dart`:
- Around line 7-16: Update the TrainingPage widget test to override its consumed
providers, including dashboardSummaryProvider, healthSummaryProvider, and
todayInsightsStateProvider, with deterministic fake values or notifier
implementations in ProviderScope. Keep the existing header assertions unchanged
and avoid allowing real repositories or provider side effects during the test.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0ec76666-7ee5-45ac-bdd1-b7e7e9d2d809

📥 Commits

Reviewing files that changed from the base of the PR and between 6899ca1 and bb954e3.

📒 Files selected for processing (16)
  • lib/app/shell_page.dart
  • lib/core/theme/layout.dart
  • lib/features/character/presentation/pages/character_page.dart
  • lib/features/coach_chat/presentation/widgets/message_list.dart
  • lib/features/dashboard/presentation/pages/dashboard_page.dart
  • lib/features/training/presentation/pages/training_page.dart
  • lib/shared/providers/dashboard_summary_provider.dart
  • lib/shared/widgets/kynos_collapsible_section.dart
  • lib/shared/widgets/kynos_nav_rail.dart
  • lib/shared/widgets/kynos_page_header.dart
  • lib/shared/widgets/kynos_section_jump_bar.dart
  • lib/shared/widgets/kynos_segmented_control.dart
  • lib/shared/widgets/widgets.dart
  • test/features/training/training_page_test.dart
  • test/shared/widgets/kynos_nav_rail_test.dart
  • test/widget_test.dart

Comment thread lib/features/character/presentation/pages/character_page.dart Outdated
Comment thread lib/features/training/presentation/pages/training_page.dart
Comment thread lib/shared/widgets/kynos_segmented_control.dart Outdated
Move DailyQuestTeaser to shared/widgets to fix cross-feature import.
Await all health hub provider futures on pull-to-refresh.
Add Semantics to KynosSegmentedControl segments.

Co-authored-by: Youri Bontekoe <YKDBontekoe@users.noreply.github.com>
@YKDBontekoe
YKDBontekoe merged commit ae2600f into main Jul 13, 2026
13 checks passed
@YKDBontekoe
YKDBontekoe deleted the cursor/ui-modernization-e60d branch July 13, 2026 14:28
kynos-release-bot Bot pushed a commit that referenced this pull request Jul 13, 2026
# [1.20.0](v1.19.0...v1.20.0) (2026-07-13)

### Features

* transform KYNOS into an agentic health coach ([#98](#98)) ([6899ca1](6899ca1))
* **ui:** modernize shell nav and unify health hub ([#99](#99)) ([ae2600f](ae2600f))
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