style(address-book): DS migration demo — saved-addresses view (stacked on #2837) - #2856
Closed
kushagrasarathe wants to merge 307 commits into
Closed
style(address-book): DS migration demo — saved-addresses view (stacked on #2837)#2856kushagrasarathe wants to merge 307 commits into
kushagrasarathe wants to merge 307 commits into
Conversation
…ose X on balance warning, fix QR url fallback precedence
…cy grey visual via opacity-100 override
ds(12): /dev/ds foundations generated from the @theme token source
…rimitives # Conflicts: # src/app/(mobile-ui)/dev/components/page.tsx
ds-06: primitives restyle — button, card, list item, navigation to the figma boards
ds-06: fold PeanutLoading into Loading — one loader
ds-06: input, toggle, badge, avatar to the figma boards
ds-06: ActionModal board restyle + migrate 10 modal stragglers
ds-06: card family consolidation — ActionListCard→ListItem, InfoCard tokens, MantecaDetailsCard deleted
…rimitives # Conflicts: # src/components/Claim/Link/views/MantecaReviewStep.tsx
ds-06: re-land cards consolidation (#2720 merged into its stale stacked base)
…:75689 why: KR3 architecture move (thin page + flow hook + dumb views, matching features/payments/flows/semantic-request) and the DS 07 home layout: bare avatar top-left, rewards link top-right, centered balance with add/send/request submenu, cta card slot composed as-is, activity feed on the ListItem primitive. - home/page.tsx is now a shim; all logic in src/features/home/ - balance visibility moved to a useSyncExternalStore over the persisted user preference so page/flow hook stay useState-free - modal priority chain extracted unchanged into HomeModals - TransactionCard, KycStatusItem, BadgeStatusItem, CardUnlockHistoryItem now render through the ListItem primitive (shared with /history) - ListItem + Global/Card gain aria-label passthrough (replaces the CardUnlockHistoryItem button wrapper) - withdraw quick action dropped from home per the figma board (3 submenu buttons) — flagged in the PR as a product-affecting change
why: AvatarWithBadge with no name renders a colorless, invisible circle — seen on harness users seeded without a username.
why: new shared-state logic (toggle + persist + multi-subscriber sync) needs a failing check if it breaks.
- NaN-guard the balance-warning env thresholds - drop the user non-null assertion in BalanceWarningModal close - mount-gate WelcomeUnlockModal + IosPwaInstallModal chunks - accessible names for the profile link and balance toggle (new home.* keys in en/es-419/pt-BR)
- balance-visibility store: in-memory session cache so the toggle works when localStorage writes fail; map lookup per render instead of a localStorage read; posthog fires after the write - eye toggle stays reachable when the balance query errors (old-page parity; it also controls activity amounts) - HistorySkeleton padding matches ListItem rows (no load jump) - useHomeFlow test (page gate, mount effects, avatarName derivation)
why: the figma home board renders initials on the avatar palette, never a generic icon. usernameless users now fall back to full-name initials, and a user with no name at all gets an avatar-yellow token circle (the palette's no-name default) instead of a plain person icon.
One layout shell for (mobile-ui), (setup) and the public payment wrapper: AppShell variant app|onboarding with nav/banner/modals slots. Desktop now shows the same centered mobile column (max-w-md) — WalletNavigation sidebar and TopNavbar are gone. Bottom nav rebuilt to the figma navigation board 17802:61534: home/card/support pill tabs (active = white pill, 68x52px pressables) + the 52px pink QR circle. Support unread badge preserved.
…style Build the four missing DS components from the figma boards: - Notification (0_Bruddle, board 17802:61535): 5 priorities on the background-badge tokens, body / title+body, dismiss, up to 2 CTAs reusing Button size=small. No prod consumer yet — /dev/ds is the consumer for now. - LinkButton (0_Bruddle, board 17980:17351): Body/XS underlined standalone navigation link, foreground-secondary at rest, black on hover, optional trailing icon, 44px hit area. - Accordion (0_Bruddle, board 17802:61540): styled compound wrapper over the radix base; BridgeLimitsView migrated off its inline radix styling. - Slider (Global, board 17802:61531): restyle to tokens — track bg-border-disabled, fill/tick action-primary, bordered thumb with shadow-2 and 44px hit area, label-l value text. Snap logic untouched. Each component gets a /dev/ds page with all variants; nav additions are additive-only to limit conflicts with the ds/07 branch.
TransactionDetailsReceipt (1009 LoC) split into an orchestrator plus ReceiptDetailsCard / ReceiptActions / ReceiptTokenRows / ReceiptReferralNudge views, a ReceiptRow list-row primitive and two hooks (useTokenDisplay via tanstack query, useReceiptActions for every charges/requests/claim-link call so views import no api modules). The details card owns layout: px-4 + divide-y dashed dividers, so rows and provider sub-rows carry no last-row border logic — shouldHideBorder/shouldHideGroupBorder removed from the view model. Provider rows (card payment, Manteca, Bridge deposit) and the perk receipt moved off PaymentInfoRow onto ReceiptRow; legacy palette classes replaced with semantic tokens. i18n keys unchanged.
…ring, controlled first-paint, cta tuple type - tailwind-merge misclassifies text-body-s/xs as text-color and strips them against text-foreground-* in the same twMerge call; keep the size token outside the merge (Accordion trigger/content, LinkButton) - slider thumb ring: outline-none poisons --tw-outline-style, add focus-visible:outline-solid so the ring paints - seed slider internal state from the controlled value so a controlled slider does not first paint at 100% and jump - ctas typed as a 1-2 tuple so a third CTA is a compile error, not a silent drop; key by index (labels can repeat)
…ken skeleton while fallback lookup runs
…450) The advisory eslint job reached 0 errors after the sprint-155 cleanup, so flip it to blocking: drop continue-on-error and add it to ci-success.needs. Also remove the 6 eslint-disable directives the cleanup left unused, so the branch lints with zero errors and zero unused-directive warnings.
Review finding: when eslint is the failing job the diagnostic echo showed only the other five jobs, all green, hiding the actual cause.
ci: make eslint blocking now errors are at zero (TASK-21450)
Wire scripts/ds-lint-counts.mjs --check into CI as a blocking job: the five DS debt counts may only go down. Allowlist the /dev/ds and /dev/components showcase pages for every metric (they render token values programmatically by design — they were the whole inlineStyle 207->211 false regression) and tighten the baseline to current-tree truth, locking in the DS 05/06 gains (stock text sizes 1392->1103, non-DS view classes 473->439).
…opped The background-page fade washed content out too aggressively in real use; the .35-alpha soft shadow reads better. Gradient wrapper reverted to plain.
…n every non-failed state
Verified every getTitle output against board 17490:115877. The board's
head model is: the TITLE carries the transaction-type wording, the
BADGE carries the state. Its pending card-payment drawer
(Activity/CardPayment, 17835:81079) is titled 'Paid to Museumsinsel'
with a Pending badge — not 'Paying to'.
Board copy vs code:
- completed QR/card pay: 'Paid to {name}' — already matched
- pending QR/card pay: board 'Paid to {name}'; code said
'Paying to {name}' -> now 'Paid to {name}' (cancelled follows the
same rule: type wording + Cancelled badge + struck amount)
- failed card pay: 'Payment to {name}' — already matched (2790915)
- request pot: 'Request', black amount, no badge — already matched
(2790915)
'title.payingTo' lost its last consumer — removed from en / es-419 /
pt-BR (es-AR never carried it).
Board-uncovered cases (kept as-is, board shows no send / receive /
add / withdraw / bank / claim receipts): 'Sent to' / 'Sending to',
'Received from', 'Added from' / 'Adding from', 'Withdrew to' /
'Withdrawing to', 'Claimed to' / 'Claiming to', link-tx labels, and
the self-contained 'Failed QR payment attempt' label.
Kush + Hugo: the doc site was styling its own scaffolding on raw tokens while documenting the primitives that already own those shapes. The chrome now composes the DS components wherever one fits: - DesignNote -> Notification (was a hand-rolled copy of the banner) - CatalogCard -> ListItem + IconBubble + chevron inside the Link - DocHeader -> TitleBlock size=m (h1 kept for heading semantics) - SectionDivider -> Divider - DoDont -> Card wells + IconBubble verdict dots - WhenToUse -> Card wells - Playground -> Card panels; controls run on BaseSelect / BaseInput / Checkbox (the primitives the playground documents) - UsageAudit -> Card hero/stat-tiles/item-rows/footnote; BaseInput search - ds root page -> Card hero + TitleBlock, Card stat tiles, ListItem section index, Card quick-rules - StatusTag already wrapped StatusBadge; TierNav already borrows the SegmentedControl vocabulary (verified, unchanged) Legitimately still custom (no DS primitive fits): PropsTable (no DS table), CodeBlock (no DS code surface; copy affordance is a bare icon button), DocSidebar (compact 192px nav rail — ListItem's 48px card rows triple its height), DocSection (two-column doc layout; TitleBlock lacks the heading-xs step and can't host the inline code toggle), UsageAudit filter/status chips (7-tone semantic palette, no DS chip primitive), DocPage (plain stack wrapper). Showcase content untouched; nav drift test green.
…etch useCurrency seeded `code` from the prop on the first render and then ignored the prop for the rest of its life. Both callers derive the currency from useSearchParams(), which is empty on the first render of a statically exported page — so the withdraw page passed null, the hook latched it, never fetched, and price stayed null forever behind an unresolvable loader (#1848). - useCurrency: sync `code` when the prop changes, report the sync gap as isLoading, add refetch(), ignore superseded in-flight responses, and drop a stale rate when the next fetch fails. - New shared RateUnavailable (alert + retry) wired into all four rate-dependent flows: InputAmountStep, withdraw/manteca (which had no error branch at all), MantecaReviewStep (rendered '1 USD = undefined ARS'), and the bridge bank flow. - i18n: move rateUnavailable from addMoney.errors to the shared errors namespace across all four catalogs rather than duplicating the string. Fixes #1848. Replaces #2707, which could not be merged: resolving its conflict with dev required a merge commit, and that drags in 7 pre-2026-08-18 unsigned src/content bumps the signature ruleset rejects.
…lable key The marketing subsets are generated from the app catalogs and mirror the `errors` namespace, so moving rateUnavailable into it left them stale — which renders as a raw message key on the marketing site.
…alf-cancelled press finding 13 described
Review follow-ups — each one re-opened the dead end this PR set out to close: - withdraw/manteca: a retry put the page back into the bare loader with no header, so a stalling retry froze the screen again. Both rate states now keep NavHeader mounted. - InputAmountStep: the retry was hidden whenever another error or a blocking limits card was showing, even though the rate block is what disables Continue — leaving no way to clear it. Now always rendered when the rate failed. - add-money bank: Continue is disabled while the rate is in flight but showed no loading state, reading as an unexplained dead button.
The three audit data files (~524KB / 9,041 lines) shipped in every prod client bundle, guarded only by a runtime notFound(). Each page now loads its data through an inline statically-foldable condition (the DEV_TOOLS_ENABLED expression) around a require(), so webpack drops the dead branch in prod. Both next configs now define NEXT_PUBLIC_VERCEL_ENV unconditionally — next skips null env values, so without the '' fallback the preview leg never folded off-Vercel and the data stayed bundled. Verified: prod-build client chunks 311KB/65KB/49KB -> 10.6KB/1.9KB/1.3KB; grep of .next for data-only literals returns nothing; dev still renders all three pages with full data; preview keeps them (VERCEL_ENV=preview folds the gate to true).
Jota (PR #2813): 'too much padding on top' on the badge receipt. The drawer stacked py-4 on DrawerContent plus p-4 on the body above the handle's own spacing, while the TX-details chrome it mirrors (board 17835:84492: handle 8px above / 24px below, then content) starts content right after the handle — like TransactionDetailsDrawer already does. Now pb-4 + px-4 only.
…etry-dev feat(native): make the deferred-link match rate measurable
ci: resolve release versions as <major>.<build>.<ota> instead of typing them
…lance fix: block account deletion while the wallet still holds funds
…ze-dev fix(fx): stop the add-money and withdraw screens freezing on a rate fetch
…-level perf(capgo): stop logging transient update failures at error level
…loop-dev fix(kyc): launch Manteca RFIs via start-action instead of the generic resubmit
…op, native routing) Conflicts (5 files), doctrine DS-structure-wins / dev-behavior-ported: - add-money bank page, withdraw/manteca, InputAmountStep, MantecaReviewStep: dev's #2843 rate-failure recovery (RateUnavailable with always-reachable retry) ported; its ErrorAlert internals swapped to the DS Notification (ErrorAlert is retired on this branch) and its PeanutLoading calls to the one DS Loading. The branch's older inline rate Notification (whose i18n key dev moved) removed as superseded. - AddressLink: DS tokens + tw wrapper kept; dev's capacitor target behavior ported. Post-merge fixes so nothing from this PR ships rule breaks (ruling 3): - manteca page's repeated header+gate block extracted to Global/RateUnavailable/RateGateScreen (new component, justified in its docblock: the inline repeat tripped the page de-inlining ratchet) - useCurrency docstring reworded — 'useSearchParams()' in a comment was a ratchet false positive - add-money rate-failure test updated to the RateUnavailable contract (same copy + retry button instead of the retired testid) Gates: prettier clean, typecheck clean, 313/313 suites (3801 tests), ds-lint ratchet no metric increased.
qa: fixtures, screenshot diffing, and a CI job that can actually fail
fix: three production bugs the fixture work surfaced
…ribing labels render bare
Reported case: a completed crypto deposit's receipt showed only
'kushagra.peanut.me' with no type wording. getTitle DID build
'Added from …', but VerifiedUserLabel's AddressLink lane fires on any
crypto-address username and discards the worded name prop entirely,
rendering the ENS-resolved address instead. Same drop hit every family
whose userName is a raw 0x (crypto add/withdraw, P2P with address
peers, link claims from addresses, claim-external).
- VerifiedUserLabel: AddressLink lane now only wins when the caller
passed no worded copy (name === username). List rows unchanged —
their name is already the resolved/shortened handle.
- TransactionDetailsHeaderCard: reverse-resolve address usernames via
usePrimaryNameServer (the TransactionCard pattern) before wording,
so the title reads 'Added from {ens}', falling back to the
shortened 0x.
- SELF_DESCRIBING_NAME_KEYS: reaper fail copy, refund labels, the
failed-QR label and the open-request label early-return bare from
getTitle — kills 'Sending to Send didn't complete' and
'Received from Refund from X' compounds (folds in the old ad-hoc
failedQrPayment check).
- Own open request pots title as 'You requested' (new
transaction.title.youRequested in en/es-419/pt-BR, translations
aligned with the existing peanutActionDetailsCard key); unresolved
incoming requests stay bare 'Request'.
- Tests: VerifiedUserLabel is no longer mocked in the header suite
(that mock is what hid the drop); new cases lock ENS deposit,
no-ENS fallback, reaper, refund, and both request wordings.
…-migration-2837 # Conflicts: # src/app/(mobile-ui)/withdraw/crypto/page.tsx # src/components/AddWithdraw/AddWithdrawRouterView.tsx # src/components/Common/SavedAccountsView.tsx # src/components/Withdraw/views/Confirm.withdraw.view.tsx
ActionListCard and ErrorAlert no longer exist on the DS line, and the address-book rows predate the semantic tokens. Rows now compose ListItem (getCardPosition replaces the hand-rolled position ternary), the stale pill takes the badge-helper token its own comment was waiting for, the edit drawer reports failures through Notification, and the success message renders bare because PaymentSuccessView already styles that line. No behavior, props, or logic changed — ds-lint ratchet is clean.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Contributor
Author
|
/chip review |
Contributor
There was a problem hiding this comment.
Chip review: Review clean
The saved-address design-system migration preserves selection, editing, failure feedback, and success-label behavior; no actionable correctness, security, adversarial, or slop finding survived verification.
Checked clean
- Pinned HEAD, exact base, merge base, trusted author, PR title, and PR description matched the supplied review target.
- Reviewed the five-file migration commit and the address-book-related merge resolutions layered over the design-system parent.
- Verified saved-address row grouping, chain-name fallback, row selection, edit-event propagation, and the 44px edit hit target against ListItem and Card contracts.
- Verified rename/delete busy states and failure feedback retain the drawer's existing behavior through Notification.
- Verified saved nicknames and addresses remain React text/content rather than unsafe HTML, with no new secret, authorization, or trust-boundary exposure.
- Verified the success nickname renders under PaymentSuccessView's existing message typography and prefix behavior.
- git diff --check passed and the design-system lint ratchet passed all 11 metrics.
- Targeted Jest suites could not start because the detached worktree has no local dependencies and the shared installation could not resolve next-intl/ts-jest for this project root.
Second opinion skipped: openrouter-empty-reply.
Exact head: 0937f67a38ae · Context: repo
…last-used tone Lets the migrated saved-addresses view render with zero backend (?__fixture=withdraw-address-book) and gives ds-shots a state to diff once a baseline exists. Dates are relative so the tones do not drift.
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
Demo PR for the design-system walkthrough recording: migrates the saved-addresses view from #2837 (Alek's crypto address book) to the design system. Styling and components only — no behavior, props, or logic changed.
Stacked branch: Alek's
feat/crypto-address-bookhead + merge offeat/design-system(the DS primitives and semantic tokens do not exist ondevyet), + one migration commit (0937f67a3). Not for merge into Alek's branch as-is — it exists to show the migration shape; the real migration lands after #2813 merges to dev.What the migration commit does:
SavedAddressesList: rows composeListItem(deletedActionListCardis gone on the DS line);getCardPositionreplaces the hand-rolled position ternary; the chain mini-bubble and edit affordance take semantic tokens; the edit button keeps a 44px hit area via pseudo-element (touch law).LastUsedPill: stale tone takesbg-background-badge-helper— the exact token the component's own comment was waiting for.SavedAddressEditDrawer: deletedErrorAlert→Notification priority="error"(flow-level failure per design.md); legacy type/color classes →text-body-*/text-label-l/foreground-*tokens; off-scalepx-5→px-4;shadowSize="4"dropped (DS purple carries it by default).SaveAddressPrompt:text-xs text-grey-1→text-body-xs text-foreground-secondary(2 sites).withdraw/crypto/page.tsx: success-message nickname renders as a bare string —PaymentSuccessViewalready styles the message line, so the wrapper span and its classes were redundant.Merge-conflict resolutions (Alek × DS branch) keep his behavior with DS styling: the saved-addresses section renders as a
Section, the nickname spans take semantic tokens.Task
Demo PR — walkthrough recording, no tracking task on purpose.
Risks / breaking changes
None to prod: base is
feat/crypto-address-book, and this PR is a demo artifact. Behavior parity is asserted by Alek's own tests passing unchanged (6/6 address-book, 16/16 withdraw-area, 3829 full suite).QA
npx tsc --noEmitclean · full jest suite green · prettier clean.node scripts/ds-lint-counts.mjs --check— ratchet fully green, 11/11 metrics at or below baseline (the address-book code had introducedlegacyColorClasses 0→2,stockTextSize +2,classNameSitesInPages +1; all back to baseline).Screenshots
Captured at 375×667 via the new
withdraw-address-bookfixture (/withdraw?__fixture=withdraw-address-book— zero backend). Assets live onpr-assets-2856, deleted post-merge.Also adds the
withdraw-address-bookfixture entry (dev-tooling only): one saved address per last-used tone, relative dates so the tones never drift. The ds-shots job has no baseline for this new screen, so the fixture + these captures stand in as the visual evidence.🤖 Generated with Claude Code