Jun 06, 12-1 PM (2)
Jun 06, 1-2 PM (2)
Jun 06, 2-3 PM (2)
Jun 06, 3-4 PM (18)
Jun 06, 4-5 PM (1)
Jun 06, 5-6 PM (6)
Jun 06, 6-7 PM (0)
Jun 06, 7-8 PM (6)
Jun 06, 8-9 PM (0)
Jun 06, 9-10 PM (1)
Jun 06, 10-11 PM (27)
Jun 06, 11-12 AM (9)
Jun 07, 12-1 AM (14)
Jun 07, 1-2 AM (2)
Jun 07, 2-3 AM (0)
Jun 07, 3-4 AM (0)
Jun 07, 4-5 AM (1)
Jun 07, 5-6 AM (1)
Jun 07, 6-7 AM (3)
Jun 07, 7-8 AM (0)
Jun 07, 8-9 AM (0)
Jun 07, 9-10 AM (1)
Jun 07, 10-11 AM (2)
Jun 07, 11-12 PM (2)
Jun 07, 12-1 PM (5)
Jun 07, 1-2 PM (35)
Jun 07, 2-3 PM (2)
Jun 07, 3-4 PM (4)
Jun 07, 4-5 PM (2)
Jun 07, 5-6 PM (4)
Jun 07, 6-7 PM (0)
Jun 07, 7-8 PM (0)
Jun 07, 8-9 PM (17)
Jun 07, 9-10 PM (1)
Jun 07, 10-11 PM (21)
Jun 07, 11-12 AM (9)
Jun 08, 12-1 AM (9)
Jun 08, 1-2 AM (5)
Jun 08, 2-3 AM (3)
Jun 08, 3-4 AM (4)
Jun 08, 4-5 AM (2)
Jun 08, 5-6 AM (9)
Jun 08, 6-7 AM (5)
Jun 08, 7-8 AM (25)
Jun 08, 8-9 AM (36)
Jun 08, 9-10 AM (41)
Jun 08, 10-11 AM (24)
Jun 08, 11-12 PM (22)
Jun 08, 12-1 PM (40)
Jun 08, 1-2 PM (48)
Jun 08, 2-3 PM (33)
Jun 08, 3-4 PM (27)
Jun 08, 4-5 PM (12)
Jun 08, 5-6 PM (23)
Jun 08, 6-7 PM (14)
Jun 08, 7-8 PM (3)
Jun 08, 8-9 PM (6)
Jun 08, 9-10 PM (19)
Jun 08, 10-11 PM (29)
Jun 08, 11-12 AM (8)
Jun 09, 12-1 AM (5)
Jun 09, 1-2 AM (3)
Jun 09, 2-3 AM (1)
Jun 09, 3-4 AM (3)
Jun 09, 4-5 AM (26)
Jun 09, 5-6 AM (5)
Jun 09, 6-7 AM (23)
Jun 09, 7-8 AM (51)
Jun 09, 8-9 AM (35)
Jun 09, 9-10 AM (45)
Jun 09, 10-11 AM (51)
Jun 09, 11-12 PM (46)
Jun 09, 12-1 PM (86)
Jun 09, 1-2 PM (84)
Jun 09, 2-3 PM (36)
Jun 09, 3-4 PM (38)
Jun 09, 4-5 PM (16)
Jun 09, 5-6 PM (18)
Jun 09, 6-7 PM (18)
Jun 09, 7-8 PM (19)
Jun 09, 8-9 PM (16)
Jun 09, 9-10 PM (16)
Jun 09, 10-11 PM (28)
Jun 09, 11-12 AM (10)
Jun 10, 12-1 AM (11)
Jun 10, 1-2 AM (16)
Jun 10, 2-3 AM (11)
Jun 10, 3-4 AM (19)
Jun 10, 4-5 AM (5)
Jun 10, 5-6 AM (2)
Jun 10, 6-7 AM (46)
Jun 10, 7-8 AM (82)
Jun 10, 8-9 AM (18)
Jun 10, 9-10 AM (59)
Jun 10, 10-11 AM (46)
Jun 10, 11-12 PM (134)
Jun 10, 12-1 PM (49)
Jun 10, 1-2 PM (33)
Jun 10, 2-3 PM (32)
Jun 10, 3-4 PM (28)
Jun 10, 4-5 PM (36)
Jun 10, 5-6 PM (12)
Jun 10, 6-7 PM (12)
Jun 10, 7-8 PM (38)
Jun 10, 8-9 PM (11)
Jun 10, 9-10 PM (9)
Jun 10, 10-11 PM (20)
Jun 10, 11-12 AM (7)
Jun 11, 12-1 AM (10)
Jun 11, 1-2 AM (2)
Jun 11, 2-3 AM (0)
Jun 11, 3-4 AM (2)
Jun 11, 4-5 AM (8)
Jun 11, 5-6 AM (12)
Jun 11, 6-7 AM (34)
Jun 11, 7-8 AM (106)
Jun 11, 8-9 AM (36)
Jun 11, 9-10 AM (20)
Jun 11, 10-11 AM (105)
Jun 11, 11-12 PM (25)
Jun 11, 12-1 PM (38)
Jun 11, 1-2 PM (37)
Jun 11, 2-3 PM (14)
Jun 11, 3-4 PM (20)
Jun 11, 4-5 PM (5)
Jun 11, 5-6 PM (7)
Jun 11, 6-7 PM (26)
Jun 11, 7-8 PM (90)
Jun 11, 8-9 PM (11)
Jun 11, 9-10 PM (5)
Jun 11, 10-11 PM (25)
Jun 11, 11-12 AM (5)
Jun 12, 12-1 AM (8)
Jun 12, 1-2 AM (2)
Jun 12, 2-3 AM (2)
Jun 12, 3-4 AM (4)
Jun 12, 4-5 AM (7)
Jun 12, 5-6 AM (15)
Jun 12, 6-7 AM (46)
Jun 12, 7-8 AM (19)
Jun 12, 8-9 AM (28)
Jun 12, 9-10 AM (22)
Jun 12, 10-11 AM (29)
Jun 12, 11-12 PM (42)
Jun 12, 12-1 PM (24)
Jun 12, 1-2 PM (26)
Jun 12, 2-3 PM (22)
Jun 12, 3-4 PM (38)
Jun 12, 4-5 PM (23)
Jun 12, 5-6 PM (19)
Jun 12, 6-7 PM (26)
Jun 12, 7-8 PM (12)
Jun 12, 8-9 PM (17)
Jun 12, 9-10 PM (5)
Jun 12, 10-11 PM (30)
Jun 12, 11-12 AM (6)
Jun 13, 12-1 AM (6)
Jun 13, 1-2 AM (2)
Jun 13, 2-3 AM (0)
Jun 13, 3-4 AM (3)
Jun 13, 4-5 AM (0)
Jun 13, 5-6 AM (3)
Jun 13, 6-7 AM (7)
Jun 13, 7-8 AM (5)
Jun 13, 8-9 AM (6)
Jun 13, 9-10 AM (14)
Jun 13, 10-11 AM (12)
Jun 13, 11-12 PM (1)
Jun 13, 12-1 PM (0)
3,235 commits this week
Jun 06, 2026
-
Jun 13, 2026
Merge pull request #296 from MeshJS/claude/ballot-vote-ux
feat(governance): clearer ballot voting UX (segmented vote + one entry per action)
Merge remote-tracking branch 'origin/preprod' into claude/ballot-vote-ux
# Conflicts: # src/components/pages/wallet/governance/proposals.tsx
Merge pull request #297 from MeshJS/claude/gov-type-chips
feat(governance): color-coded proposal type chips
Merge remote-tracking branch 'origin/preprod' into claude/ballot-vote-ux
# Conflicts: # src/components/pages/wallet/governance/proposals.tsx
Merge remote-tracking branch 'origin/preprod' into claude/gov-type-chips
# Conflicts: # src/components/pages/wallet/governance/proposals.tsx
Merge pull request #295 from MeshJS/claude/assets-overflow-fix
fix(assets): stop token rows overflowing the Assets card
Merge pull request #294 from MeshJS/claude/tx-row-hierarchy
fix(ux): lead transaction rows with the label, demote the hash
Merge pull request #293 from MeshJS/claude/tx-pagination-redesign
fix(ux): themed, non-overflowing, mobile-friendly pagination
feat(governance): color-coded proposal type chips
The proposal meta row showed the governance action type as plain uppercase
text ("TREASURY WITHDRAWALS"), visually indistinguishable from the other meta
fields and hard to scan in a long list.
Add a GovernanceTypeChip that renders each Conway action type as a color-coded
outline Badge with an icon:
- treasury_withdrawals amber Coins
- info_action blue FileText
- parameter_change purple Settings2
- hard_fork_initiation orange GitBranch
- no_confidence red XCircle
- new_constitution teal FileText
- new/update_committee indigo Users
- unknown slate Hash (Title-Cased fallback label)
Used in both the mobile and desktop meta rows (single shared component, no
view drift). Purely presentational — no data or vote-flow changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
feat(governance): clearer ballot voting UX — segmented vote + one entry per action
The per-proposal voting controls were confusing: a raw OS <select> for the
Yes/No/Abstain choice, plus TWO competing actions (a green "Add to Ballot"
button in proposals.tsx AND a mystery ballot icon in VoteButton).
- Replace the native <select> with a shadcn segmented Yes/No/Abstain control
(color-coded selected state, icons). Guard `(v) => v && setVoteKind(v)` so a
re-click can't blank the vote read into the tx.
- One clear primary: the Vote button now states the choice ("Vote Yes",
"Vote Yes (Proxy)") and uses the themed primary style.
- One ballot entry: the icon-only ballot button becomes a labeled "Add to
ballot" / "In N ballots" secondary, with a tooltip distinguishing the two
flows (vote on-chain now vs collect for co-signers).
- Remove the now-duplicate green "Add to Ballot" buttons (mobile + desktop) in
proposals.tsx; keep the View links.
vote()/voteProxy() bodies, proxy path, keepRelevant, metadata label 674, the
closed-vote Lock state, and all toasts are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
fix(assets): stop token rows overflowing the Assets card
Long token names ($drep.collective) and raw quantities pushed the value/ticker past the card's right edge (the clipped "↗1 $S…"). Root cause: the flex row + left group had no min-w-0, so text couldn't shrink, and the name/quantity/ticker were never truncated. - min-w-0 on the row + flex-1 min-w-0 on the left group (lets text shrink). - 60px avatar wrappers flex-shrink-0 (so the image never compresses instead). - name h3 truncates (+ title tooltip) and is bounded via truncateTokenSymbol for the raw-unit hex fallback; remove ml-auto from the link. - value block flex-shrink-0; quantity via numberWithCommas (tabular-nums); ticker truncates with a max width + title. Full name stays reachable via tooltip + the Cardanoscan token link. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
fix(ux): lead transaction rows with the human label, demote the hash
The on-chain history rows (desktop table + mobile cards) led with the raw
truncated tx hash — the least human-meaningful field — while the actual
description ("Ballot Vote: …") was buried below. Flip the hierarchy to match
the pending-tx cards:
- primary: the dbTransaction description, or a "Sent"/"Received" fallback (and
the cert label on desktop) so rows without a DB record aren't identified by
a bare hash.
- date below.
- hash demoted to a quiet muted mono link with the external-link arrow.
Also standardize the hash truncation on getFirstAndLast(hash, 8, 8) (was two
different inline substring schemes) and drop the now-redundant standalone
description block on mobile. Cardanoscan links, outputs, certs, signers, and
the row actions menu are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
fix(ux): themed, non-overflowing, mobile-friendly pagination control
The transactions pagination bar overflowed its card on the right and used hardcoded dark colors + a raw <select>. Rewrite the body (props unchanged): - container: themed `border bg-card`, `flex-wrap min-w-0 gap-3` so the groups reflow instead of spilling off the right edge. - sort toggle: outline Button, icon-only on mobile (label hidden < sm). - page size: shadcn Select (was a native unstyled <select>); same options + reset-to-page-1 behavior. - nav: compact icon-only prev/next (h-9 w-9), muted tabular-nums page indicator; rely on Button's native disabled styling. PaginationProps is unchanged, so both call sites (transactions + DRep list) behave identically. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Merge pull request #292 from MeshJS/claude/ux-error-normalization
feat(ux): friendly-error helper + toastError wrapper
Merge pull request #291 from MeshJS/claude/mobile-dialog-responsive
fix(mobile): keep dialogs within the viewport (responsive width + dvh + scroll)
feat(ux): friendly-error helper + toastError wrapper; adopt in DRep register
PR 5 of the UX/mobile quick-wins pass.
- src/utils/errors.ts `getFriendlyError(error)` maps the common raw errors
(CIP-30 {code:-2}, account-changed, 429/too-many-requests, insufficient
funds, Blockfrost/UTXOS, user-decline) to short human messages, falling back
to the raw message.
- src/utils/toast-error.ts `toastError(error, title?)` — destructive toast with
the normalized message (additive; doesn't touch the TOAST_LIMIT=1 reducer).
- Adopt in DRep registration's catch (raw e.message -> getFriendlyError), while
keeping the "Copy Error" action for raw debug details.
Other error-prone flows (new-transaction, WalletAuthModal) can adopt the
helper incrementally.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
fix(mobile): keep dialogs within the viewport (responsive width + dvh + scroll)
PR 4 of the UX/mobile quick-wins pass. Centered Dialogs overflowed small screens — content (and action buttons) got clipped off-screen, especially the wide governance modals. Make the base DialogContent mobile-safe without changing desktop layout: w-[calc(100%-1.5rem)] (stay within the viewport with a small margin), max-h-[90dvh] + overflow-y-auto (scroll internally instead of off-screen). The max-w-lg cap and centered position are unchanged at desktop. BallotModal and RegisterDrepModal switch their max-h from vh to dvh so the mobile toolbar doesn't hide the bottom. (Kept dialogs centered rather than converting to a bottom sheet to avoid restructuring positioning on the shared base that backs every dialog; the overflow fix is the critical part. Needs a quick on-device / Chrome-MCP visual check before promoting past preprod.) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Merge pull request #290 from MeshJS/claude/mobile-address-input
fix(mobile): bech32-safe address inputs + decimal keypad + no iOS zoom
Merge pull request #289 from MeshJS/claude/ux-skeleton-emptystate
feat(ux): Skeleton + EmptyState primitives; fix blank pages & loading/empty bug
Merge pull request #288 from MeshJS/claude/mobile-touch-targets
feat(mobile): >=44px touch targets on coarse-pointer devices
Merge pull request #287 from MeshJS/claude/mobile-foundations
feat(mobile): viewport-fit + dvh + safe-area insets (foundations)
fix(mobile): bech32-safe address inputs + decimal keypad + no iOS zoom
PR 6 of the UX/mobile quick-wins pass (input correctness).
- Recipient address fields used invalid type="string" with mobile autocorrect/
autocapitalize active — which can silently corrupt case-sensitive bech32
addresses. Now type="text" with inputMode="text" autoCapitalize="off"
autoCorrect="off" spellCheck={false}.
- Amount fields get inputMode="decimal" (numeric keypad on mobile).
- Base Input uses text-base on mobile (sm:text-sm on desktop) so iOS Safari
no longer zooms in on focus (<16px triggers it).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
feat(ux): Skeleton + EmptyState primitives; fix blank wallet pages & loading/empty conflation
PR 3 of the UX/mobile quick-wins pass. - Add shared `Skeleton` (shadcn) and `EmptyState` (Card-based) primitives. - Wallet detail routes (info/transactions/governance/assets) rendered a blank fragment while `appWallet` loaded — replace with a `WalletDetailSkeleton` so there's no white flash on every wallet open. - all-transactions: it showed "No transactions yet" *while still loading* (undefined === loading). Split into a skeleton (loading) vs an `EmptyState` (loaded and empty). - proposals: plain-text "No proposals found" → `EmptyState`. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
feat(mobile): enforce >=44px touch targets on coarse-pointer devices
PR 2 of the UX/mobile quick-wins pass. Buttons/inputs were 32-36px, below the recommended 44px touch target. A single @media (pointer: coarse) rule enlarges interactive controls on touch devices only — no per-call-site edits and zero change to desktop density. Plain text links are intentionally excluded. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>