Skip to content

feat(widget)!: route registry, Compact and Dashboard Layouts, dashboard page transitions - #606

Closed
petar-omni wants to merge 6 commits into
mainfrom
refactor/route-registry-and-layouts
Closed

petar-omni wants to merge 6 commits into
mainfrom
refactor/route-registry-and-layouts

Conversation

@petar-omni

@petar-omni petar-omni commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This branch carries four changes:

Change Commits
Dashboard page transitions: the Dashboard now plays exit and enter transitions when switching pages feat(dashboard): play page exit transitions, fix(dashboard): apply the last pressed category after the page exit
Rejected configuration notice: an invalid initial Host Configuration shows the widget-unavailable notice instead of unmounting the host's React root fix(widget): show the unavailable notice for a rejected initial configuration
Playground: it only mounts host setups the widget accepts fix(playground): only mount host setups the widget accepts, chore(mise): bump pinned pnpm to 12.15.0
Route Registry and Layout separation: typed routes, renamed vocabulary, Layout-agnostic Features refactor(widget)!: type routes through a registry and separate Layouts

Dashboard page transitions

 <DashboardRoutes>
   <DashboardShell>              # header + tabs stay mounted across pages
-    <Routes>
+    <AnimatePresence mode="wait" onExitComplete={applyPendingCategory}>
+      <Routes location key={pageKey}>   # one key per page; flow steps keep their page's key
  • Transitions: the leaving page now plays its exit. Before, AnimationPage's exit never ran because nothing wrapped the routes in AnimatePresence.
  • Category presses: a pressed Yield Category is applied only after the Earn page finishes leaving, so the old page never fades out showing the new category.
  • Stale callback: the pending category is read from a ref. AnimatePresence keeps the callback from the render where the exit started, so a press made during the exit used to be dropped, or an earlier press was applied instead.
  • Animations: the Dashboard uses a shorter, blur-only exit; the Compact Layout keeps its existing transition. AnimationPage gets one transition object per Layout from the app container.

Rejected initial configuration

Before, an invalid initial Host Configuration made widgetConfigAtom throw while rendering (e.g. borrowEnabled without dashboardVariant). There is no error boundary, so the host's whole React root unmounted. The widget now renders the widget-unavailable notice instead. Its theme, variant and Layout are decoded field by field from the rejected configuration, so one bad field falls back to its default instead of throwing again.

Playground

  • Theme lock: Utila only offers the light theme and Porto only the dark one.
  • Borrow: borrowEnabled is turned off when the Dashboard Layout isn't selected.
  • Panel: the widget stays clear of the open panel, and Copy link asks for confirmation.

Route Registry and Layout separation

Route paths are now typed through one Route Registry. The Compact and Dashboard Layouts are application composition, and Features no longer branch on the Layout.

 packages/widget/src/
 ├── app/
+│   ├── layouts/
+│   │   ├── compact/            # Compact route tree + shell
+│   │   └── dashboard/          # Dashboard route tree, shell, tabs, page transitions
 │   └── routes/                 # layout-neutral plumbing (initial route, error, guards)
 ├── features/
+│   ├── navigation/             # React adapters: useWidgetNavigate, WidgetNavigate, route match hooks
-│   ├── classic-transaction-flow/
+│   ├── yield-transaction-flow/
 │   └── <feature>/ui/
-│       ├── classic/            # imported by ui/dashboard as a "base"
+│       ├── compact/            # Compact-only screens
+│       ├── dashboard/          # Dashboard-only screens (never imports compact/)
+│       └── components/         # what both Layouts render
 └── services/navigation/
+    └── widget-routes.ts        # Route Registry

Every absolute path is defined once in the registry. Each route carries its pattern, the params inferred from it, the Layouts that mount it, build, match, and matchPrefix:

widgetRoutes.positionDetails.build({ integrationId, balanceId }) // WidgetPath (branded, registry-only)
widgetRoutes.borrow.build("Dashboard")      // a route not mounted in every Layout must name its Layout
widgetRoutes.activityAction.match(pathname) // Option<{ actionId: ActionId }>, decoded by Schema
yieldFlowRoutes = widgetYieldFlowRoutes.Earn.withState(YieldFlowNavigationState)
  • Navigation: WidgetNavigation and the React adapters accept only registry-built paths.
  • Flow state: each flow binds its navigation state schema to its route group, so the hand-written decode*NavigationState functions are gone.
  • Naming: the Classic Transaction Flow is now the Yield Transaction Flow. The non-dashboard layout is now the Compact Layout.
  • Layout: Widget Configuration derives layout from the public dashboardVariant. Layout differences are now one of:
    • styles keyed on data-sk-layout
    • props named after the difference (e.g. selectsDefaultAction, showsBackButton)
    • Layout-specific components
  • Enforcement:
    • New ast-grep rules:
      • no-raw-widget-path
      • no-layout-read-in-features
      • no-layout-name-in-logic
      • no-layout-path-outside-layout-ui
    • dependency-cruiser keeps ui/compact and ui/dashboard independent of each other.
    • tests/app/layouts/layout-routes.test.tsx checks that each Layout mounts exactly the routes declared for it.
  • Docs:
    • GLOSSARY: Layout, Compact Layout, Dashboard Layout, Yield Category, Yield and Borrow Transaction Flow
    • ARCHITECTURE: new sections on Layouts and on routes and navigation
    • ADR 0013: Layouts are application composition

Evidence

  • mise run lint, mise run check-hygiene, and mise run test all pass locally:

    Suite Files Tests
    unit 224 1912
    dom 49 243, plus 1 expected failure
    browser 42 198
  • The ast-grep scan has zero hits. Against the old tree, no-raw-widget-path reported 17.

  • Playground smoke test in Chromium:

    • Dashboard: RWA, DeFi, Stake, Borrow, Manage, and Activity tabs render.
    • Compact: Earn, Manage, and Activity tabs render.
    • No page errors in either.
  • tests/app/journeys/invalid-host-configuration.browser.test.tsx covers the rejected-configuration notice.

Merge Danger

Door: one-way for hosts, two-way internally.

Blast Radius: public API

  • Breaking: DashboardYieldCategory is now YieldCategory, and the dashboardYieldCategoryOrder option is now yieldCategoryOrder. There are no aliases.
  • data-sk-layout on the app container now reads compact instead of widget. It isn't documented for hosts, but host CSS could target it.
  • Route params are now URI-encoded when paths are built. IDs containing reserved characters produce encoded URLs; memory-router behaviour is otherwise unchanged.
  • Section matching respects path segment boundaries, so a path like /activityx no longer counts as Activity.
  • An invalid initial configuration no longer crashes the host's React root; it renders the notice.
  • Dashboard page changes are delayed by the exit animation (0.1s); Compact timings are unchanged.

@changeset-bot

changeset-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3ae0f71

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 386 files, which is 236 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to Team to raise the limit.

Usage-priced reviews support at most 300 files.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 2e1a5b12-dc56-4c61-9db5-b25bc13b576c
Commits

Reviewing files that changed from the base of the PR and between 8bb83cc and 3ae0f71.

Files ignored due to path filters: 1
  • mise.lock is excluded by !**/*.lock
Files selected for processing: 386
  • GLOSSARY.md
  • README.md
  • docs/adr/0011-lifetimes-are-scopes-staleness-is-interruption.md
  • docs/adr/0013-layouts-are-application-composition.md
  • packages/widget/ARCHITECTURE.md
  • packages/widget/playground/main.tsx
  • packages/widget/playground/panel.tsx
  • packages/widget/playground/playground-app.tsx
  • packages/widget/playground/playground-config.ts
  • packages/widget/playground/playground.css
  • packages/widget/playground/widget-props.ts
  • packages/widget/scripts/architecture/dependency-cruiser.config.mts
  • packages/widget/src/App.tsx
  • packages/widget/src/app/composition/providers/mount-animation/index.tsx
  • packages/widget/src/app/composition/providers/theme-wrapper.tsx
  • packages/widget/src/app/composition/providers/widget-presentation.tsx
  • packages/widget/src/app/composition/widget-configuration-unavailable.tsx
  • packages/widget/src/app/layouts/compact/compact-routes.tsx
  • packages/widget/src/app/layouts/dashboard/dashboard-overview.css.ts
  • packages/widget/src/app/layouts/dashboard/dashboard-overview.tsx
  • packages/widget/src/app/layouts/dashboard/dashboard-routes.tsx
  • packages/widget/src/app/layouts/dashboard/dashboard-shell.tsx
  • packages/widget/src/app/layouts/dashboard/dashboard-tabs/index.tsx
  • packages/widget/src/app/layouts/dashboard/dashboard-tabs/styles.css.ts
  • packages/widget/src/app/layouts/dashboard/dashboard-tabs/tab.tsx
  • packages/widget/src/app/routes/model/initial-route.ts
  • packages/widget/src/app/routes/model/tab-resources-prefetch-gate.ts
  • packages/widget/src/app/routes/state/pending-action-deep-link-route.ts
  • packages/widget/src/app/routes/state/tab-resources-prefetch.ts
  • packages/widget/src/app/routes/ui/borrow-feature-route.tsx
  • packages/widget/src/app/routes/ui/classic-routes.tsx
  • packages/widget/src/app/routes/ui/dashboard-routes.tsx
  • packages/widget/src/app/runtime/application-base-runtime.ts
  • packages/widget/src/app/runtime/application-router.ts
  • packages/widget/src/app/runtime/deep-link-coordinator.ts
  • packages/widget/src/app/runtime/transaction-workflow-event-projection.ts
  • packages/widget/src/domain/action/pending-action.ts
  • packages/widget/src/domain/earn/contract.ts
  • packages/widget/src/domain/earn/yield-provider-order.ts
  • packages/widget/src/domain/earn/yield.ts
  • packages/widget/src/features/activity/composition.ts
  • packages/widget/src/features/activity/model/activity-action.ts
  • packages/widget/src/features/activity/model/filters.ts
  • packages/widget/src/features/activity/react/activity-action-route.tsx
  • packages/widget/src/features/activity/react/use-activity-page.ts
  • packages/widget/src/features/activity/routes.tsx
  • packages/widget/src/features/activity/state/page.ts
  • packages/widget/src/features/activity/ui/activity-details/activity-details.page.tsx
  • packages/widget/src/features/activity/ui/compact/activity-page/activity.page.tsx
  • packages/widget/src/features/activity/ui/dashboard/activity/index.tsx
  • packages/widget/src/features/borrow-transaction-flow/model/borrow-transaction-flow.ts
  • packages/widget/src/features/borrow-transaction-flow/model/borrow-transaction-workflow.ts
  • packages/widget/src/features/borrow-transaction-flow/react/borrow-flow-route.tsx
  • packages/widget/src/features/borrow-transaction-flow/state/borrow-flow-session.ts
  • packages/widget/src/features/borrow-transaction-flow/state/review-page.ts
  • packages/widget/src/features/borrow-transaction-flow/ui/borrow-flow-routes.tsx
  • packages/widget/src/features/borrow-transaction-flow/ui/steps.tsx
  • packages/widget/src/features/borrow/borrow-entry/ui/routes.tsx
  • packages/widget/src/features/borrow/composition.ts
  • packages/widget/src/features/borrow/market-position/ui/action.page.tsx
  • packages/widget/src/features/borrow/market-position/ui/actions.page.tsx
  • packages/widget/src/features/borrow/market-position/ui/components/breadcrumb.tsx
  • packages/widget/src/features/borrow/market-position/ui/context.ts
  • packages/widget/src/features/borrow/market-position/ui/details.page.tsx
  • packages/widget/src/features/borrow/market-position/ui/routes.tsx
  • packages/widget/src/features/borrow/wallet/ui/connected-wallet-route.tsx
  • packages/widget/src/features/classic-transaction-flow/composition.ts
  • packages/widget/src/features/classic-transaction-flow/index.ts
  • packages/widget/src/features/classic-transaction-flow/react/classic-flow-route.tsx
  • packages/widget/src/features/classic-transaction-flow/runtime.ts
  • packages/widget/src/features/classic-transaction-flow/state/start-atom.ts
  • packages/widget/src/features/earn/composition.ts
  • packages/widget/src/features/earn/index.ts
  • packages/widget/src/features/earn/react/use-earn-facades.ts
  • packages/widget/src/features/earn/state/earn-selection.ts
  • packages/widget/src/features/earn/state/earn-selection/catalog/catalog.ts
  • packages/widget/src/features/earn/state/earn-selection/catalog/keys.ts
  • packages/widget/src/features/earn/state/earn-selection/model/transitions.ts
  • packages/widget/src/features/earn/state/earn-selection/model/view-inputs.ts
  • packages/widget/src/features/earn/state/earn-selection/model/view.ts
  • packages/widget/src/features/earn/state/earn-selection/state/atoms.ts
  • packages/widget/src/features/earn/state/earn-selection/state/owner.ts
  • packages/widget/src/features/earn/state/earn-selection/state/resource-observations.ts
  • packages/widget/src/features/earn/state/earn-selection/types.ts
  • packages/widget/src/features/earn/state/pending-action-deep-link.ts
  • packages/widget/src/features/earn/state/validator-selection.ts
  • packages/widget/src/features/earn/state/yield-selection.ts
  • packages/widget/src/features/earn/ui/classic/earn-page/components/extra-args-selection/index.tsx
  • packages/widget/src/features/earn/ui/compact/earn-page/components/select-provider/index.tsx
  • packages/widget/src/features/earn/ui/compact/earn-page/components/select-validator-section/index.tsx
  • packages/widget/src/features/earn/ui/compact/earn-page/components/select-validator-section/select-validator-trigger.tsx
  • packages/widget/src/features/earn/ui/compact/earn-page/earn.page.tsx
  • packages/widget/src/features/earn/ui/compact/earn-page/styles.css.ts
  • packages/widget/src/features/earn/ui/components/extra-args-selection/index.tsx
  • packages/widget/src/features/earn/ui/components/footer/index.tsx
  • packages/widget/src/features/earn/ui/components/select-token-section/index.tsx
  • packages/widget/src/features/earn/ui/components/select-token-section/select-token-list-item.tsx
  • packages/widget/src/features/earn/ui/components/select-token-section/select-token.tsx
  • packages/widget/src/features/earn/ui/components/select-token-section/styles.css.ts
  • packages/widget/src/features/earn/ui/components/select-token-section/title.tsx
  • packages/widget/src/features/earn/ui/components/select-yield-section/index.tsx
  • packages/widget/src/features/earn/ui/components/select-yield-section/select-opportunity.tsx
  • packages/widget/src/features/earn/ui/components/select-yield-section/select-yield-reward-details.tsx
  • packages/widget/src/features/earn/ui/components/select-yield-section/styles.css.ts
  • packages/widget/src/features/earn/ui/components/select-yield-section/use-animated-yield-percent-boundary.ts
  • packages/widget/src/features/earn/ui/dashboard/earn-details/earn-details-model.tsx
  • packages/widget/src/features/earn/ui/dashboard/earn-details/index.tsx
  • packages/widget/src/features/earn/ui/dashboard/earn-page/index.tsx
  • packages/widget/src/features/leave-confirmation/react/use-leave-confirmation.ts
  • packages/widget/src/features/leave-confirmation/ui/leave-confirmation-dialog.tsx
  • packages/widget/src/features/navigation/index.ts
  • packages/widget/src/features/navigation/react/widget-navigation.ts
  • packages/widget/src/features/navigation/ui/widget-navigate.tsx
  • packages/widget/src/features/navigation/views.ts
  • packages/widget/src/features/portfolio/composition.ts
  • packages/widget/src/features/portfolio/react/use-position-list-item.ts
  • packages/widget/src/features/portfolio/state/read-models/positions.ts
  • packages/widget/src/features/portfolio/ui/compact/positions-page/components/positions-list-item.tsx
  • packages/widget/src/features/portfolio/ui/compact/positions-page/positions.page.tsx
  • packages/widget/src/features/portfolio/ui/compact/positions-page/style.css.ts
  • packages/widget/src/features/portfolio/ui/components/earn-position-list-item.tsx
  • packages/widget/src/features/portfolio/ui/dashboard/positions/components/positions-list-item.tsx
  • packages/widget/src/features/portfolio/ui/dashboard/positions/components/positions-section-header.tsx
  • packages/widget/src/features/portfolio/ui/dashboard/positions/hooks/use-position-list-item.ts
  • packages/widget/src/features/position-details/composition.ts
  • packages/widget/src/features/position-details/index.ts
  • packages/widget/src/features/position-details/model/flow-actions.ts
  • packages/widget/src/features/position-details/model/hub.ts
  • packages/widget/src/features/position-details/model/position-overview.ts
  • packages/widget/src/features/position-details/react/use-pending-action-select-validator-match.ts
  • packages/widget/src/features/position-details/react/use-pending-actions.ts
  • packages/widget/src/features/position-details/react/use-position-details-hub-match.ts
  • packages/widget/src/features/position-details/react/use-position-details-stake-match.ts
  • packages/widget/src/features/position-details/react/use-position-details.ts
  • packages/widget/src/features/position-details/react/use-unstake-or-pending-action-match.ts
  • packages/widget/src/features/position-details/react/use-unstake-or-pending-action-params.ts
  • packages/widget/src/features/position-details/react/use-unstake-or-pending-action.ts
  • packages/widget/src/features/position-details/react/use-validator-addresses-handling.ts
  • packages/widget/src/features/position-details/state/actions/exit.ts
  • packages/widget/src/features/position-details/state/actions/facts.ts
  • packages/widget/src/features/position-details/state/actions/pending-action.ts
  • packages/widget/src/features/position-details/state/actions/reveal.ts
  • packages/widget/src/features/position-details/state/details-view.ts
  • packages/widget/src/features/position-details/state/stake-entry.ts
  • packages/widget/src/features/position-details/state/stake-view.ts
  • packages/widget/src/features/position-details/state/workflow-view.ts
  • packages/widget/src/features/position-details/state/workflow.ts
  • packages/widget/src/features/position-details/ui/compact/components/position-balances.tsx
  • packages/widget/src/features/position-details/ui/compact/components/position-source-details.tsx
  • packages/widget/src/features/position-details/ui/compact/components/provider-details.tsx
  • packages/widget/src/features/position-details/ui/compact/components/yield-details.tsx
  • packages/widget/src/features/position-details/ui/compact/position-details.page.tsx
  • packages/widget/src/features/position-details/ui/compact/styles.css.ts
  • packages/widget/src/features/position-details/ui/components/amount-block.tsx
  • packages/widget/src/features/position-details/ui/components/exit-receive-token-accessory.tsx
  • packages/widget/src/features/position-details/ui/components/exit-receive-token-note.tsx
  • packages/widget/src/features/position-details/ui/components/position-details-pending-actions.tsx
  • packages/widget/src/features/position-details/ui/components/position-details-unstake-actions.tsx
  • packages/widget/src/features/position-details/ui/components/position-details-validator-modal.tsx
  • packages/widget/src/features/position-details/ui/components/static-action-block.tsx
  • packages/widget/src/features/position-details/ui/components/styles.css.ts
  • packages/widget/src/features/position-details/ui/dashboard/components/position-details-hub.tsx
  • packages/widget/src/features/position-details/ui/dashboard/components/position-details-info.tsx
  • packages/widget/src/features/position-details/ui/dashboard/hooks/use-position-details-stake.ts
  • packages/widget/src/features/position-details/ui/dashboard/index.tsx
  • packages/widget/src/features/wallet/react/wallet-scope-route.tsx
  • packages/widget/src/features/widget-configuration/index.ts
  • packages/widget/src/features/widget-configuration/state/widget-config.ts
  • packages/widget/src/features/widget-shell/classic-layout/index.tsx
  • packages/widget/src/features/widget-shell/composition.ts
  • packages/widget/src/features/widget-shell/dashboard/components/app-container.tsx
  • packages/widget/src/features/widget-shell/react/use-details-match.ts
  • packages/widget/src/features/widget-shell/react/use-header.ts
  • packages/widget/src/features/widget-shell/state/layout-height.ts
  • packages/widget/src/features/widget-shell/ui/animation-page.tsx
  • packages/widget/src/features/widget-shell/ui/app-container.tsx
  • packages/widget/src/features/widget-shell/ui/back-button.tsx
  • packages/widget/src/features/widget-shell/ui/compact/compact-layout/index.tsx
  • packages/widget/src/features/widget-shell/ui/compact/compact-layout/styles.css.ts
  • packages/widget/src/features/widget-shell/ui/compact/details/components/tab.tsx
  • packages/widget/src/features/widget-shell/ui/compact/details/components/tabs.tsx
  • packages/widget/src/features/widget-shell/ui/compact/details/details.page.tsx
  • packages/widget/src/features/widget-shell/ui/compact/details/styles.css.ts
  • packages/widget/src/features/widget-shell/ui/compact/header/index.tsx
  • packages/widget/src/features/widget-shell/ui/compact/header/styles.css.ts
  • packages/widget/src/features/widget-shell/ui/dashboard/header.tsx
  • packages/widget/src/features/widget-shell/ui/dashboard/split-view/index.tsx
  • packages/widget/src/features/widget-shell/ui/dashboard/split-view/styles.css.ts
  • packages/widget/src/features/widget-shell/ui/dashboard/styles.css.ts
  • packages/widget/src/features/widget-shell/ui/layout.css.ts
  • packages/widget/src/features/widget-shell/ui/page-container.tsx
  • packages/widget/src/features/widget-shell/ui/page-cta.tsx
  • packages/widget/src/features/widget-shell/ui/powered-by.tsx
  • packages/widget/src/features/widget-shell/ui/shell-notice/index.tsx
  • packages/widget/src/features/widget-shell/ui/shell-notice/style.css.ts
  • packages/widget/src/features/widget-shell/ui/widget-unavailable/index.tsx
  • packages/widget/src/features/widget-shell/views.ts
  • packages/widget/src/features/yield-entry/model/yield-entry-submission.ts
  • packages/widget/src/features/yield-entry/state/yield-entry.ts
  • packages/widget/src/features/yield-summary/model/yield-details-formatters.ts
  • packages/widget/src/features/yield-summary/ui/components/estimated-reward-amounts/index.tsx
  • packages/widget/src/features/yield-summary/ui/components/yield-details-header/index.tsx
  • packages/widget/src/features/yield-transaction-flow/composition.ts
  • packages/widget/src/features/yield-transaction-flow/index.ts
  • packages/widget/src/features/yield-transaction-flow/model/yield-transaction-flow.ts
  • packages/widget/src/features/yield-transaction-flow/model/yield-transaction-workflow.ts
  • packages/widget/src/features/yield-transaction-flow/react/use-yield-action-continuation-review.ts
  • packages/widget/src/features/yield-transaction-flow/react/yield-flow-route.tsx
  • packages/widget/src/features/yield-transaction-flow/runtime.ts
  • packages/widget/src/features/yield-transaction-flow/state/execution-page.ts
  • packages/widget/src/features/yield-transaction-flow/state/review-page.ts
  • packages/widget/src/features/yield-transaction-flow/state/start-atom.ts
  • packages/widget/src/features/yield-transaction-flow/state/start-flow.ts
  • packages/widget/src/features/yield-transaction-flow/state/yield-summary.ts
  • packages/widget/src/features/yield-transaction-flow/ui/complete/hooks/use-activity-complete.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/complete/hooks/use-complete.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/complete/pages/activity-complete.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/complete/pages/common.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/complete/pages/pending-complete.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/complete/pages/stake-complete.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/complete/pages/unstake-complete.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/hooks/use-pending-review.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/review/hooks/use-stake-review.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/review/hooks/use-unstake-review.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/common-page/common.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/common-page/components/review-top-section.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/pending-review.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/stake-review.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/style.css.ts
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/unstake-review.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/pages/unstake-sign-popup.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/review/types/index.ts
  • packages/widget/src/features/yield-transaction-flow/ui/steps/hooks/use-steps.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/steps/hooks/use-transaction-workflow.hook.ts
  • packages/widget/src/features/yield-transaction-flow/ui/steps/pages/common.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/steps/pages/pending-steps.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/steps/pages/stake-steps.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/steps/pages/styles.css.ts
  • packages/widget/src/features/yield-transaction-flow/ui/steps/pages/unstake-steps.page.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/use-view-transaction.ts
  • packages/widget/src/features/yield-transaction-flow/ui/yield-action-continuation.tsx
  • packages/widget/src/features/yield-transaction-flow/ui/yield-flow-routes.tsx
  • packages/widget/src/features/yield-transaction-flow/views.ts
  • packages/widget/src/index.bundle.ts
  • packages/widget/src/index.package.ts
  • packages/widget/src/public-api/types.ts
  • packages/widget/src/resources/earn-token-catalog/earn-token-catalog.ts
  • packages/widget/src/services/config/host-profile.ts
  • packages/widget/src/services/config/widget-config-boundary.ts
  • packages/widget/src/services/config/widget-config-model.ts
  • packages/widget/src/services/config/widget-config.ts
  • packages/widget/src/services/events/widget-domain-events.ts
  • packages/widget/src/services/navigation/application-router.ts
  • packages/widget/src/services/navigation/widget-navigation.ts
  • packages/widget/src/services/navigation/widget-routes.ts
  • packages/widget/src/services/transaction-workflow/internal/advancement.ts
  • packages/widget/src/services/transaction-workflow/internal/confirmation.ts
  • packages/widget/src/services/transaction-workflow/internal/current.ts
  • packages/widget/src/services/transaction-workflow/internal/held-hash-registration.ts
  • packages/widget/src/services/transaction-workflow/internal/model.ts
  • packages/widget/src/services/transaction-workflow/internal/preparation.ts
  • packages/widget/src/services/transaction-workflow/internal/signing.ts
  • packages/widget/src/services/transaction-workflow/internal/submission.ts
  • packages/widget/src/services/transaction-workflow/transaction-workflow-model.ts
  • packages/widget/src/services/transaction-workflow/transaction-workflow-service.ts
  • packages/widget/src/services/wallet/external-provider.ts
  • packages/widget/src/services/wallet/internal/adapters/evm/driver.ts
  • packages/widget/src/services/wallet/internal/adapters/external-provider/driver.ts
  • packages/widget/src/services/wallet/internal/adapters/ledger/driver.ts
  • packages/widget/src/services/wallet/internal/adapters/ledger/ledger-live-connector-meta.ts
  • packages/widget/src/services/wallet/internal/adapters/ledger/polkadot-ledger-transaction.ts
  • packages/widget/src/services/wallet/internal/adapters/ledger/prepare-ledger-live-transaction.ts
  • packages/widget/src/services/wallet/internal/adapters/safe/driver.ts
  • packages/widget/src/services/wallet/wallet-transactions.ts
  • packages/widget/src/services/zama/zama-service.ts
  • packages/widget/src/shared/styles/theme/ids.ts
  • packages/widget/src/shared/ui/components/select-modal/index.tsx
  • packages/widget/src/shared/ui/primitives/button/styles.css.ts
  • packages/widget/src/shared/ui/widget-presentation.tsx
  • packages/widget/tests/app/composition/widget-instance-lifecycle.dom.test.tsx
  • packages/widget/tests/app/journeys/invalid-host-configuration.browser.test.tsx
  • packages/widget/tests/app/journeys/renders-initial-page.browser.test.tsx
  • packages/widget/tests/app/layouts/compact/compact-position-details-redirects.dom.test.tsx
  • packages/widget/tests/app/layouts/layout-routes.test.tsx
  • packages/widget/tests/app/routes/borrow-feature-route.dom.test.tsx
  • packages/widget/tests/app/routes/initial-route.test.ts
  • packages/widget/tests/app/routes/tab-resources-prefetch-gate.test.ts
  • packages/widget/tests/app/routes/tab-resources-prefetch.test.ts
  • packages/widget/tests/app/runtime/application-router.test.ts
  • packages/widget/tests/app/runtime/application-runtime-identity.dom.test.tsx
  • packages/widget/tests/app/runtime/pending-action-deep-link-route.test.ts
  • packages/widget/tests/app/runtime/transaction-workflow-event-projection.test.ts
  • packages/widget/tests/domain/earn/yield-category-types.test.ts
  • packages/widget/tests/features/activity/activity-continuation-route.dom.test.tsx
  • packages/widget/tests/features/activity/activity-details.dom.test.tsx
  • packages/widget/tests/features/activity/activity-page-view.test.ts
  • packages/widget/tests/features/activity/activity-routes.test.tsx
  • packages/widget/tests/features/activity/activity-workflow.dom.test.tsx
  • packages/widget/tests/features/borrow-transaction-flow/borrow-execution-flow.browser.test.tsx
  • packages/widget/tests/features/borrow-transaction-flow/borrow-flow-operations.test.ts
  • packages/widget/tests/features/borrow-transaction-flow/borrow-flow-pages.test.ts
  • packages/widget/tests/features/borrow-transaction-flow/borrow-flow-route-identity.dom.test.tsx
  • packages/widget/tests/features/borrow-transaction-flow/borrow-flow-routes.test.tsx
  • packages/widget/tests/features/borrow-transaction-flow/summary-rows.dom.test.tsx
  • packages/widget/tests/features/borrow-transaction-flow/transaction-flow-route-readiness.dom.test.tsx
  • packages/widget/tests/features/borrow/borrow-external-provider.browser.test.tsx
  • packages/widget/tests/features/borrow/borrow-routes.test.tsx
  • packages/widget/tests/features/earn/earn-background-refetch.test.ts
  • packages/widget/tests/features/earn/earn-entry-reset.test.ts
  • packages/widget/tests/features/earn/earn-initial-validator.test.ts
  • packages/widget/tests/features/earn/earn-selection.test.ts
  • packages/widget/tests/features/earn/provider-selection-card.browser.test.tsx
  • packages/widget/tests/features/earn/select-validator-section.browser.test.tsx
  • packages/widget/tests/features/earn/validator-selection-limit.test.ts
  • packages/widget/tests/features/mount-animation/compact-mount-geometry.browser.test.tsx
  • packages/widget/tests/features/mount-animation/compact-mount-reveal-gate.browser.test.tsx
  • packages/widget/tests/features/portfolio/positions-list-item.browser.test.tsx
  • packages/widget/tests/features/portfolio/summary-atoms.test.ts
  • packages/widget/tests/features/position-details/page-workflow-state.dom.test.tsx
  • packages/widget/tests/features/position-details/position-action-wallet-scope.dom.test.tsx
  • packages/widget/tests/features/position-details/position-details-action-content.test.ts
  • packages/widget/tests/features/position-details/position-details-action-model.test.ts
  • packages/widget/tests/features/position-details/position-details-action-tabs.browser.test.tsx
  • packages/widget/tests/features/position-details/position-details-exit-command.test.ts
  • packages/widget/tests/features/position-details/position-details-exit-receive-token.browser.test.tsx
  • packages/widget/tests/features/position-details/position-details-hub-model.test.ts
  • packages/widget/tests/features/position-details/position-details-stake-token.test.ts
  • packages/widget/tests/features/position-details/position-details-stake-validators.test.ts
  • packages/widget/tests/features/position-details/position-details-workflow.test.ts
  • packages/widget/tests/features/position-details/position-details-yield-entry.browser.test.tsx
  • packages/widget/tests/features/position-details/position-overview-model.test.tsx
  • packages/widget/tests/features/position-details/position-source-details.browser.test.tsx
  • packages/widget/tests/features/wallet/sk-wallet.dom.test.tsx
  • packages/widget/tests/features/wallet/wallet-scope-route.dom.test.tsx
  • packages/widget/tests/features/widget-shell/dashboard-header.browser.test.tsx
  • packages/widget/tests/features/widget-shell/widget-shell-element-slot.dom.test.tsx
  • packages/widget/tests/features/widget-shell/widget-shell-layout-measurement.dom.test.ts
  • packages/widget/tests/features/yield-entry/yield-entry-submission-model.test.ts
  • packages/widget/tests/features/yield-entry/yield-entry.test.ts
  • packages/widget/tests/features/yield-flow-confidential.test.ts
  • packages/widget/tests/features/yield-transaction-flow/action-preview.dom.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-completion-urls.test.ts
  • packages/widget/tests/features/yield-transaction-flow/yield-exit-review-receive-token.browser.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-flow-navigation.dom.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-flow-operations.test.ts
  • packages/widget/tests/features/yield-transaction-flow/yield-flow-review-page.test.ts
  • packages/widget/tests/features/yield-transaction-flow/yield-flow-route.dom.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-flow-routes.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-review-fees.browser.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-review-kyc-notice.browser.test.tsx
  • packages/widget/tests/features/yield-transaction-flow/yield-steps-view.test.ts
  • packages/widget/tests/features/yield-transaction-flow/yield-transaction-flow-interface.test.ts
  • packages/widget/tests/package-types/bundle-consumer.ts
  • packages/widget/tests/package-types/package-consumer.ts
  • packages/widget/tests/playground/widget-props.dom.test.ts
  • packages/widget/tests/public-api/public-api-conformance.test.ts
  • packages/widget/tests/services/config/host-profile.test.ts
  • packages/widget/tests/services/config/widget-config.test.ts
  • packages/widget/tests/services/navigation/widget-navigation.test.ts
  • packages/widget/tests/services/navigation/widget-routes.test.ts
  • packages/widget/tests/services/transaction-workflow/transaction-workflow-model.test.ts
  • packages/widget/tests/services/transaction-workflow/transaction-workflow-runtime.test.ts
  • packages/widget/tests/services/wallet/evm-wallet-driver.test.ts
  • packages/widget/tests/services/wallet/external-provider-contract.test.ts
  • packages/widget/tests/services/wallet/external-provider-wallet-driver.test.ts
  • packages/widget/tests/services/wallet/ledger-wallet-driver.test.ts
  • packages/widget/tests/services/wallet/polkadot-registry-lazy-load.dom.test.ts
  • packages/widget/tests/services/wallet/prepare-ledger-live-transaction.test.ts
  • packages/widget/tests/services/wallet/safe-wallet-driver.test.ts
  • packages/widget/tests/services/wallet/stellar-wallet-driver.test.ts
  • packages/widget/tests/services/wallet/wallet-router.test.ts
  • packages/widget/tests/services/wallet/wallet-service-contract.test.ts
  • packages/widget/tests/services/zama-service.test.ts
  • packages/widget/tests/shared/ui/components/number-input.dom.test.tsx
  • packages/widget/tests/utils/services/widget-navigation.test.ts
  • packages/widget/tests/utils/services/widget-navigation.ts
  • packages/widget/tests/utils/yield-flow-test-kit.test.ts
  • packages/widget/tests/utils/yield-flow-test-kit.ts
  • tools/ast-grep/rule-tests/no-layout-name-in-logic-test.yml
  • tools/ast-grep/rule-tests/no-layout-path-outside-layout-ui-test.yml
  • tools/ast-grep/rule-tests/no-layout-read-in-features-test.yml
  • tools/ast-grep/rule-tests/no-raw-widget-path-test.yml
  • tools/ast-grep/rules/no-layout-name-in-logic.yml
  • tools/ast-grep/rules/no-layout-path-outside-layout-ui.yml
  • tools/ast-grep/rules/no-layout-read-in-features.yml
  • tools/ast-grep/rules/no-raw-widget-path.yml

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@aws-amplify-eu-central-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-606.d2ribjy8evqo6h.amplifyapp.com

@aws-amplify-eu-central-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-606.df4xyoi0xyeak.amplifyapp.com

The dashboard swapped pages without AnimatePresence, so a leaving page
vanished at once and AnimationPage's exit never ran. Wrap the dashboard
routes in AnimatePresence (mode wait) keyed per page, keep the header and
tabs mounted outside the routes, and apply a pressed yield category only
after the leaving Earn page has exited so it does not render the new
category while fading out. Give the dashboard a shorter, blur-only exit;
the classic widget keeps its transition.
AnimatePresence keeps the onExitComplete callback from the render the exit
started in, so a category pressed during the exit was dropped or an
earlier one applied. Read the pending category from a ref instead, select
it through a setter-only Earn facade so the route tree no longer
re-renders on every selection change, share the tab classifier between
the tabs and the page key, and give AnimationPage one transition object
per variant.
…guration

An invalid initial Host Configuration (e.g. borrowEnabled without
dashboardVariant) made widgetConfigAtom throw while rendering. With no
error boundary, the host's whole React root unmounted. Render the
widget-unavailable notice instead, styled from the rejected
configuration's own theme, variant and layout, each decoded separately so
a bad field falls back to its default instead of throwing again.
Utila is drawn for light and Porto for dark only, so lock the theme for
them. Borrow needs the dashboard variant, so disable borrowEnabled
without it instead of mounting a configuration the widget rejects. Keep
the widget clear of the open panel, confirm Copy link, and note that a
non-production API URL needs that environment's key.
Route paths were plain strings built, matched, and parsed in many places,
"classic" meant three different things, and Features branched on the
dashboard flag at runtime.

- Add the Route Registry (services/navigation/widget-routes.ts): one
  definition per route with typed params, build and match, the Layouts
  that mount it, and flow groups whose owners bind their navigation
  state. Navigation accepts only registry-built paths; React adapters
  live in the navigation Feature.
- Rename the Classic Transaction Flow to the Yield Transaction Flow and
  the non-dashboard layout to the Compact Layout.
- Move the Layout route trees to app/layouts/{compact,dashboard}.
  Widget Configuration derives `layout` from `dashboardVariant`;
  Features never read it, and shared screens move out of ui/compact.
- Enforce with ast-grep (raw widget paths, Layout reads in Features,
  Layout names in logic and file paths) and dependency-cruiser
  (ui/compact and ui/dashboard stay independent), plus a test that each
  Layout mounts exactly its declared routes.
- Record the vocabulary in GLOSSARY.md and the decision in ADR 0013.

BREAKING CHANGE: `DashboardYieldCategory` is now `YieldCategory` and the
`dashboardYieldCategoryOrder` option is now `yieldCategoryOrder`.
@petar-omni

Copy link
Copy Markdown
Contributor Author

Split into the stacked PRs #607 → #608 → #609 (stack #610) to fit CodeRabbit's file limit. #609's tip has the same tree as this PR.

@petar-omni petar-omni closed this Oct 27, 2026
@petar-omni
petar-omni deleted the refactor/route-registry-and-layouts branch October 27, 2026 17:16
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