Repository navigation
feat: icon bubble colours follow one rule (TASK-22761) - #3457
kushagrasarathe wants to merge 20 commits into
Conversation
Product surfaces fold content open four different ways today: the radix Accordion, ListItem rows with a hand-rolled chevron and useState, the receipt's underlined toggle (no aria-expanded), and the residence text link. Kush wants one component for one job, so this extends 0_Bruddle/Accordion with what the others need (ListItem row trigger, flush and kept-mounted content, ListGroup position, a link variant) and adds /dev/accordion, which renders each real surface before and after so the design owner can decide before any screen is migrated. Existing Accordion call sites render unchanged; no product screen uses the new props yet.
Kush ruled the country rows on add money and withdraw are their own card with the list a separate card below; the bordered item would wrap both, so the trigger carries the border instead. Radix's h3 header put a stray heading into pages like the setup residence step, where a row or in-card toggle is not a section heading. The offScaleSpacing baseline rises by the flush content's 1px border overlap (-mx-px -mb-px), which is geometry, not rhythm.
…oggle One disclosure component for every product collapsible (TASK-23071). A search still opens the list and hides the row, as before.
Deletes the useState, rotating chevron and aria-expanded wiring. Other countries becomes its own card with the list below it, matching add money (kush, 2026-09-25). The shared-currency branch has no live currency today but stays, now tested with an appended currency.
Both were raw buttons with their own toggle state; the receipt one had no aria-expanded. Closing the residence toggle still clears the stored second pick, now in onValueChange.
Every disclosure row is an Accordion trigger now, which sets it itself.
… 2px border The 2px border pushed the tile's content 1px on select (QA-42). An inset ring takes no layout; bare ring is redefined in globals.css, so inset-ring.
Other countries wrapped to two lines, and the add money body said "your". Both now read Pick a country in every locale; es-AR inherits the withdraw key from es-419.
… DS page The proposal shipped, so its before/after page goes; the DS accordion page now shows the row-in-group, detached and link variants with the real list.
Inheriting es-419's "Elige un país" put two voices on one English string; the duplicate-value drift test flags it.
The -mx-px -mb-px on flush content is border-overlay geometry, the same category as the tabs chip weld, so the ratchet log records it. TASK-23071
A bubble's colour now answers one question. Concepts are blue (a method, an identity object, information) or pink (Peanut's own: the Peanut user, friends, card, rewards, badges); yellow was doing double duty as both 'Peanut's own' and 'needs attention'. Rewards trades the trophy placeholder for the points star, and PerkIcon becomes that same rewards bubble on the s/m/l scale instead of a green circle with an off-scale 40px size. STATE_BUBBLE_COLORS carries the mixed-list rule (icon = concept, colour = state) so every surface reads it from one place. The unused logo colour is gone.
Half the modals picked their bubble colour through a raw class, and the rest fell through to pink, so pink meant nothing. tone is now required by the type whenever an icon renders, a brand tone covers Peanut's own moments, and every caller names its tone per the colour spec. Raw bg iconContainerClassName overrides are gone from product callers.
…2761) The link-state map drew a check or a clock instead of the thing the row is, and only link rows carried state at all. Every concept bubble in activity (link, request, crypto, bank, QR, card) now keeps its concept glyph and takes yellow while pending, red when failed, gray when cancelled or refunded, its own colour when done. The identity verification row and drawer head follow the same rule. External address and wallet counterparties read as the crypto concept instead of a wallet on yellow, and a flag that fails to load falls back to a real bank IconBubble.
…TASK-22761) Active rows were green and processing rows blue, so the same method changed colour with its status in a way no other list did. Available and unlockable rows now show their concept colour (QR, Pix, crypto blue; P2P and card pink), waiting is yellow, not available is gray.
… used (TASK-22761) The showcase said yellow was for warnings while half the app used it for Peanut's own things. It now states the six colours with what each means, what to use it for and what never, the state glyphs, the per-surface rules, and a current-usage list per colour, and drops the logo colour from the props table.
The remaining audited call sites: the home activation CTAs and the getting-started checklist (card pink, verify and money moves blue), receipt more actions, claim account and residence change (blue), corridor gate (review yellow, support blue), additional verification pending (yellow), KYC failed (red), region restricted (gray), unlock method, backup FAQ, passkey info and already claimed (blue), the balance warning (yellow). Error empty states turn red so failed-to-load no longer reads like nothing-here. Four same-pixel bubbles move off raw bg classes onto the colour prop.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…rs-22761 # Conflicts: # src/components/0_Bruddle/Accordion.tsx # src/components/0_Bruddle/__tests__/Accordion.test.tsx
Code-analysis diffPainscore total: 8870.53 → 8876.39 (+5.86) 🆕 New findings (118)
…and 98 more. ✅ Resolved (118)
…and 98 more. 📈 Painscore deltas (top movers)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
|
/chip review |
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
The icon-color refactor is largely consistent, but it reverts two gate-drawer QA decisions already present on dev.
Findings
-
MAJOR · src/features/deposit-accounts/components/CorridorGateDrawer.tsx:183 · Keep the selected currency in account-gate titles
For a pending-review, wait, or support gate on EUR, the heading is now generic (for example, “We are setting this up”) and the corridor appears only in a caption below the buttons. Base commit 167d013 explicitly removed that caption and required the selected currency in these headings; this head also deletes those regression assertions. Restore the currency-specific title copy/interpolation and remove the post-button rail caption, keeping the base tests. -
MINOR · src/components/Kyc/modals/KycProcessingModal.tsx:78 · Keep support as the tertiary escape after a primary action
When verification is stale and can resume, Contact support is now a full-width secondary button beside Continue verification. The base-branch QA change deliberately made it a tertiary link below the primary action; the same reversal occurs in the failed Unlock payments retry and account-limit drawer, with the old assertions removed. Preserve the base support-link hierarchy while applying the icon-color changes.
Inline anchors unavailable for 2 finding(s); the findings remain in this summary.
Checked clean
- Pinned head and base verified; reviewed the changed icon/state mapping and affected callers.
- Unit, typecheck, lint, format, and aggregate CI checks succeeded at this head; visual capture jobs were still running.
- No new security, privacy, money, or API surface in the diff.
Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.
Third opinion: did not run — claude-api_error. This review is one reviewer short.
Exact head: 08bae3623bb4 · Context: repo · Took 8m
|
English · Español · Español (Argentina) · Português (Brasil) Review preview: 92eb273 → 08bae36. Capture complete in all locales. |
🖼 Visual diff — 16 screens moved29 of 164 shots changed · 135 identical · baseline
job summary · before/after/diff images — artifact Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data. |
|
Closing in favour of #3456 (merged as 9b7a2b1). Thanks Kush, a lot of this lives on there, credited to you and TASK-22761. Taken from this PR:
Different, on Hugo's call (2026-09-25):
Six open design calls are listed in the #3456 body; they're yours when you have a minute. |
Summary
Icon bubble colours meant different things on different screens: yellow was both "Peanut's own" and "needs attention", pink was ActionModal's silent default, and link rows swapped their icon for a check or a clock. This PR gives every bubble colour one meaning and applies it across the app. The definition was approved by Kush (TASK-22761) and now lives on
/dev/ds/primitives/icon-bubble.Task
TASK-22761
The rule
brand)Mixed lists (activity rows, receipt head, Unlock payments, identity verification): icon = the concept, colour = the state. Done or active = the concept colour, pending/processing = yellow, failed = red, cancelled/refunded/not available = gray.
What changed
0_Bruddle/conceptIcons.tsx): peanutUser, friends, card, rewards, badges move to pink (brand). Rewards uses the points star instead of the trophy. NewSTATE_BUBBLE_COLORS+conceptBubbleFor(concept, status)carry the mixed-list rule in one place.logocolour is removed; each colour's meaning is documented in JSDoc.brandtone.toneis required by the type whenever an icon renders (discriminated props). The silentbg-action-primarydefault is gone. All product callers name a tone; rawiconContainerClassNamebg overrides are removed.TransactionAvatarBadge):LINK_STATE_BUBBLESis replaced by the state rule for every concept row (link, request, crypto, bank, QR, card). A statusless open request reads as pending. Flags, merchant logos and user avatars are unchanged.PerkIconis now the rewardsIconBubble(pink, star) at s/m/l; the off-scale 40px size is gone.UserCard,ContributorCard,PeanutActionDetailsCard). A flag that fails to load falls back to a real bankIconBubble(AvatarWithBadge.fallbacknow takes a node)./dev/ds/primitives/icon-bubbledocuments when to use a bubble, the six colours, state icons, concepts, per-surface rules and current usage per colour./dev/ds/patterns/modaldocuments the brand tone and the required tone.Per-site changes (47 spec rows;
file:lineis on the base branch, icon is today's)features/home/components/HomeActionDrawers.tsx:69users: yellow -> pink (Home > Send drawer: Send to friends)Home/ActivationCTAs.tsx:433globe-lock: pink -> blue (Home activation CTA, verify + 6 other steps)Home/ActivationCTAs.tsx:433arrow-down: pink -> blue (Home activation CTA, deposit step)Home/ActivationCTAs.tsx:433credit-card: yellow -> pink (Home activation CTA, card step)Home/ActivationCTAs.tsx:433qr-code/credit-card: pink -> blue (Home activation CTA, outbound step)Home/GettingStartedChecklist.tsx:168credit-card/arrow-up/user-plus/arrow-down: yellow -> blue (Home > Getting-started checklist, 4 rows)TransactionDetails/TransactionAvatarBadge.tsx:105clock: gray -> yellow (Activity row + receipt header, link/request rows with status)TransactionDetails/TransactionAvatarBadge.tsx:105clock: gray -> yellow (Activity row + receipt header, link/request rows with status)TransactionDetails/TransactionAvatarBadge.tsx:105check: green -> blue (Activity row + receipt header, link/request rows with status)TransactionDetails/TransactionAvatarBadge.tsx:115arrow-down-left: green -> yellow (Activity, request row with no mapped status)TransactionDetails/TransactionAvatarBadge.tsx:120credit-card: yellow -> pink (Activity, card_pay / refund without merchant logo)TransactionDetails/ReceiptMoreActionsDrawer.tsx:48share/link/download/ban/peanut-support/invite-heart: yellow -> blue (Receipt > More actions)Send/views/SendRouter.view.tsx:147img: yellow -> pink (Send picker: Peanut contacts)Send/views/Contacts.view.tsx:182img: yellow -> pink (Send > Contacts row)features/payments/flows/contribute-pot/components/RequestPotActionList.tsx:393user-plus: pink -> blue (Pot, use Peanut balance)Claim/Generic/Claimed.view.tsx:33info: yellow -> blue (Claim, already claimed)features/payments/flows/qr-pay/views/QrPayKycGateView.tsx:35img: pink -> blue (QR pay KYC gate)features/payments/flows/qr-pay/views/QrPayKycGateView.tsx:70shield: pink -> yellow (QR pay, verification in progress)features/payments/flows/qr-pay/views/QrPayProviderRejectionView.tsx:36img: pink -> red (QR pay provider rejection)app/(mobile-ui)/withdraw/crypto/page.tsx:1030alert: pink -> yellow (Crypto withdraw compatibility warning)features/deposit-accounts/components/ClaimAccountScreen.tsx:90/94/98wallet/clock/link: gray -> blue (Claim account info rows)features/deposit-accounts/components/CorridorGateDrawer.tsx:173clock/peanut-support/user-id: gray -> blue (Corridor gate drawer)Profile/views/UnlockPayments.view.tsx:705img: yellow -> pink (Unlock Payments > Everywhere: P2P)Profile/views/UnlockPayments.view.tsx:710coins: green -> blue (Unlock Payments > Everywhere: Crypto)Profile/views/UnlockPayments.view.tsx:708credit-card: yellow -> pink (Unlock Payments > Spend: Card)Profile/views/UnlockPayments.view.tsx:710qr-code: green -> blue (Unlock Payments > Spend: QR payments)Profile/views/UnlockPayments.view.tsx:710qr-code: blue -> yellow (Unlock Payments > Spend: QR payments)Profile/views/UnlockPayments.view.tsx:710arrow-up-right: green -> blue (Unlock Payments > Spend: Pix key)Profile/views/UnlockPayments.view.tsx:710arrow-up-right: blue -> yellow (Unlock Payments > Spend: Pix key)Profile/views/ResidenceChangeDrawer.tsx:141globe: pink -> blue (Residence change drawer)Kyc/AdditionalVerificationView.tsx:84user-id: blue -> yellow (KYC additional verification panel)Kyc/modals/KycFailedModal.tsx:58alert: yellow -> red (KYC failed)Kyc/modals/KycRegionRestrictedModal.tsx:35globe-lock: pink -> gray (KYC region restricted)Kyc/SumsubHelpModal.tsx:79question-mark: pink -> blue (Sumsub help)Global/IframeWrapper/index.tsx:246question-mark: pink -> blue (KYC iframe help)Kyc/AdvisoryPreemptModal.tsx:45badge: pink -> blue (KYC advisory)Kyc/BridgeTosStep.tsx:119alert/badge: pink -> blue (Bridge ToS step)Kyc/ProvideEmailStep.tsx:79user-id: pink -> blue (KYC provide email)IdentityVerification/UnlockMethodModal.tsx:52shield: pink -> blue (Unlock method modal)Global/StaleCardApproval/ReEnableModal.tsx:94credit-card: yellow -> pink (Card re-enable)Home/EnableAutoBalanceBanner.tsx:138credit-card: yellow -> pink (Card auto-balance)features/limits/views/LimitsPageView.tsx:128credit-card: yellow -> pink (Limits page, card row)Global/BalanceWarningDrawer/index.tsx:102wallet: pink -> yellow (Balance warning)Profile/BackupFaqDrawers.tsx:47info: pink -> blue (Backup FAQ)Setup/components/PasskeyInfoDrawer.tsx:32lock: pink -> blue (Passkey info)Global/PostSignupActionManager/index.tsx:63check: pink -> green (Post-signup action)Global/UnsupportedBrowserModal/index.tsx:56alert: pink -> yellow (Unsupported browser)Develop #13/completed also changes the glyph: check -> link (icon = concept). patch: updated to sdk v0.0.85 to hotfix bnb chain. #14 changes the glyph too: arrow-down-left -> link.
Design notes / accepted trade-offs
design/design.md(link rows take icon and colour from the link state). Link rows now keep the link icon and only the colour follows the state. The mono PR updates design.md.conceptIcons.tsx, not inTransactionAvatarBadge.tsx, because the KYC row reads it too.TransactionCardandTransactionDetailsHeaderCardstill both read it throughTransactionAvatarBadge, so the two surfaces cannot drift.PerkIconsmall(40px) maps tos(32px) on the perk receipt banner.colorprop.useHomeCarouselCTAs,dev/home-ctas) still set bubble colours throughiconContainerClassName; they were not in the audit.Risks
ActionModalprops are now a discriminated union: any new caller that passesiconwithouttonefails typecheck (intended).AvatarWithBadge.fallbackchanged shape (object -> node). Both callers are migrated.QA
bareListLeading18 = 18). eslint on changed files: 7 warnings, same as base.Screenshots
375×667, headless Chromium,
next dev --webpack. Before =origin/dev(140e604), after = this PR head (08bae36). Each image: before on the left, after on the right. "fixture" =?__fixture=<name>with no backend; "surface" =/dev/surfacesgallery. The activity and receipt rows use a capture-only fixture built fromTransactionDetails/__tests__/fixtures/render-baseline.jsonentries; it was not committed.CI visual diff for all fixtures at 4 widths: ds-shots comment.
Note:
origin/devdoes not yet have the one-accordion PR (ui#3455) that this branch includes, so an accordion row can differ in a pair. Bubble colours are the change under review.Checked, no visible change (pixel-identical or expected unchanged): KYC start, KYC processing, KYC in progress, KYC status drawer, invite friends (pink stays pink, now via
brandtone), guest sign-in, early user, setup notifications, scan to download, camera permission, add money list, withdraw list, Send > Contacts (avatars, no bubble), empty-state gallery, rewards, limits page (fixture has no card row).Not captured: post-signup check (#141), QR pay KYC gate / provider rejection (#50–52), crypto withdraw warning (#78), already-claimed view (#43), card re-enable (#121, gallery blocks it) and auto-balance banner (#122), corridor gate drawer (#84), Sumsub / iframe help (#111/112), pot "use Peanut balance" (#40), rewards/invites/contacts/direct-request/recover-funds error states, limits card row (#125), avatar fallback on
UserCard/ContributorCard/PeanutActionDetailsCard. Each needs provider or backend state that no fixture or gallery entry serves; the sandbox API was not started.The
pr-assets-3457branch holds these images only. It is deleted after merge.🤖 Generated with Claude Code