feat(Dashboard): add controlled activeSection and defaultSection navigation - #420
Merged
k-deejah merged 1 commit intoJul 29, 2026
Conversation
…gation Adds external control over the active nav section so consumers can deep-link into a screen, plus a retry hook on ErrorBoundary for failed client init. - Dashboard: `activeSection` + `onSectionChange` for controlled mode, and `defaultSection` for the uncontrolled initial section. `onSectionChange` fires in both modes; in controlled mode the parent owns what renders. - ErrorBoundary: `onRetry` runs before the error state clears, so children re-mount with a re-initialised dependency instead of throwing again. - main.tsx: wire a retry handler that re-creates the client on retry. Resolves Sorokit#407
|
@jadonamite Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #407
1 & 2. Controlled and uncontrolled section navigation
Dashboardheld the active section in privateuseState, so a consumer had no way to deep-link into a screen.activeSection?: NavSection+onSectionChange?: (s: NavSection) => voidfor controlled mode. WhenactiveSectionis passed,Dashboardrenders it and never overrides it internally — the parent owns the state and updates it fromonSectionChange.defaultSection?: NavSectionfor the uncontrolled initial section (defaults towallet, preserving today's behaviour).onSectionChangefires in both modes, so a parent can observe navigation without taking ownership of it.SCREENS[active] ?? SCREENS.walletkeeps an unknown section from rendering blank.3.
ErrorBoundaryonRetryNew
onRetry?: () => void, invoked fromresetbefore the error state clears — so the re-initialisation attempt has already happened by the time children re-mount under the newresetKey. It fires from the default fallback's "Try again" and from a customfallback'sresetcallback alike.componentStackis also cleared on reset, which it wasn't before.main.tsxnow wires it up: client creation moved behind acreateClient()factory inside aRootcomponent, and the retry handler re-creates the client into state.One deviation worth flagging. The issue describes the handler as calling
initClient(createSorokitClient(...))again. NeithercreateSorokitClientnor anyinitClientcall exists inmain.tsxon currentmain— it builds a mock client and passes it toSorokitProvideras a prop. I implemented the equivalent against the code as it stands (re-create the client, feed it back through the prop) rather than inventing an API. If you'd ratherRootdrive thegetClient()singleton instead, that's a small change.Verification
npx vitest run src/screens/Dashboard.test.tsx src/components/ErrorBoundary.test.tsx— 20 passed.Dashboard.test.tsx(9 cases): default screen,defaultSection, uncontrolled navigation,onSectionChangein uncontrolled mode, controlled render, controlled click reports without moving the view, following a parentactiveSectionchange,defaultSectionignored when controlled, and active section propagating to Sidebar/TopBar. Screens and chrome are stubbed so the tests cover onlyDashboard's own logic.ErrorBoundary.test.tsxgains 3 cases:onRetryon the default fallback, via a custom fallback'sreset, and an ordering test proving a child that throws until re-initialised renders successfully after one retry.ESLint clean on all five changed files.
Two pre-existing things I noticed
Sidebarrestores a persisted section on mount.Sidebar's effect readssorokit-active-navfromlocalStorageand callsonNavigate(saved)when it differs fromactive. In controlled mode that surfaces as one unpromptedonSectionChangeshortly after mount. I left it alone as it's outside this issue, but if the intent is for controlled mode to fully own the section it probably shouldn't fire — happy to follow up.npm run build/tsc -bdon't pass onmain.FeeEstimator.tsxandSorobanPanel.tsxeach contain an unclosed block left by a merge, which also accounts for the current pre-existing test failures. Unrelated to this PR; glad to open a separate repair PR.