feat(web/PositionPanel): handle missing position gracefully with deposit CTA (#560) - #629
Merged
Mimah97 merged 1 commit intoJul 28, 2026
Conversation
…sit CTA (Vatix-Protocol#560) The panel already caught null positions and showed a text message, but had no actionable call-to-action, which left users with no obvious next step when the chain returned no position for their address. Changes ------- • Empty-state block replaced with a centred card that includes: - A chart-bar icon (accessible, aria-hidden) to visually signal 'no data' - 'No open position' heading and a one-line explanation - 'Deposit to get started' primary button that scrolls the DepositForm into view and focuses the amount input — no page navigation required • Added a depositFormRef (useRef<HTMLDivElement>) attached to a wrapper div around <DepositForm> so the CTA can scroll to and focus it • Added handleDepositCTA helper that calls scrollIntoView (smooth) then programmatically focuses the first number input inside the form • Updated component-level JSDoc to document the empty-state / CTA behaviour • Added useRef to the React import No-crash guarantee ------------------ All null/undefined positions continue to be handled in the existing conditional render tree (!position branch); the new empty state simply replaces the previous plain-text copy with a styled, accessible block. There is no path that can throw an uncaught render error from a missing position. Acceptance criteria ------------------- ✓ No uncaught render error when position is null/absent ✓ CTA to deposit when empty (scrolls to DepositForm + focuses input) Closes Vatix-Protocol#560
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.
Summary
Closes #560
Upgrades the PositionPanel empty state from a plain-text message to a purposeful, accessible block that guides users toward opening a position.
Problem
When the contract's
get_positionreturnsnull(the user has no recorded position in the market), the panel rendered:This satisfied "no crash" but failed the acceptance criterion "CTA to deposit when empty" — there was no button or interactive element, and the deposit form was potentially off-screen.
Changes
apps/web/components/PositionPanel.tsxEmpty state — replaced the two-line text block with a centred card:
aria-hidden) — visual signal that no data is presentNo open positionheadingYou don't have an active position in this market yet.Deposit to get startedprimary button — scrolls theDepositForminto view viascrollIntoView({ behavior: 'smooth', block: 'center' })and programmatically focuses the amount inputdepositFormRef(new) — auseRef<HTMLDivElement>attached to a wrapper<div>around<DepositForm>, giving the CTA a stable DOM target to scroll to.handleDepositCTA— small helper that readsdepositFormRef.current, scrolls, and focuses the firstinput[type='number']inside the form.JSDoc — updated the component docstring to document the empty-state / CTA behaviour.
Import — added
useRefto the React import (was unused before).No-crash guarantee
The
!positionbranch in the conditional render tree was already correct — all null/absent positions reach the empty-state path without throwing. This PR only changes what is rendered in that branch, not the guard logic.Acceptance criteria
Notes
aria-label, icon isaria-hidden